NSFileManager+DirectoryLocations.m 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. //
  2. // NSFileManager+DirectoryLocations.m
  3. //
  4. // Created by Matt Gallagher on 06 May 2010
  5. //
  6. // Permission is given to use this source code file, free of charge, in any
  7. // project, commercial or otherwise, entirely at your risk, with the condition
  8. // that any redistribution (in part or whole) of source code must retain
  9. // this copyright and permission notice. Attribution in compiled projects is
  10. // appreciated but not required.
  11. //
  12. #import "NSFileManager+DirectoryLocations.h"
  13. enum
  14. {
  15. DirectoryLocationErrorNoPathFound,
  16. DirectoryLocationErrorFileExistsAtLocation
  17. };
  18. NSString * const DirectoryLocationDomain = @"DirectoryLocationDomain";
  19. @implementation NSFileManager (DirectoryLocations)
  20. //
  21. // findOrCreateDirectory:inDomain:appendPathComponent:error:
  22. //
  23. // Method to tie together the steps of:
  24. // 1) Locate a standard directory by search path and domain mask
  25. // 2) Select the first path in the results
  26. // 3) Append a subdirectory to that path
  27. // 4) Create the directory and intermediate directories if needed
  28. // 5) Handle errors by emitting a proper NSError object
  29. //
  30. // Parameters:
  31. // searchPathDirectory - the search path passed to NSSearchPathForDirectoriesInDomains
  32. // domainMask - the domain mask passed to NSSearchPathForDirectoriesInDomains
  33. // appendComponent - the subdirectory appended
  34. // errorOut - any error from file operations
  35. //
  36. // returns the path to the directory (if path found and exists), nil otherwise
  37. //
  38. - (NSString *)findOrCreateDirectory:(NSSearchPathDirectory)searchPathDirectory
  39. inDomain:(NSSearchPathDomainMask)domainMask
  40. appendPathComponent:(NSString *)appendComponent
  41. error:(NSError **)errorOut
  42. {
  43. //
  44. // Search for the path
  45. //
  46. NSArray* paths = NSSearchPathForDirectoriesInDomains(
  47. searchPathDirectory,
  48. domainMask,
  49. YES);
  50. if ([paths count] == 0)
  51. {
  52. if (errorOut)
  53. {
  54. NSDictionary *userInfo =
  55. [NSDictionary dictionaryWithObjectsAndKeys:
  56. NSLocalizedStringFromTable(
  57. @"No path found for directory in domain.",
  58. @"Errors",
  59. nil),
  60. NSLocalizedDescriptionKey,
  61. [NSNumber numberWithInteger:searchPathDirectory],
  62. @"NSSearchPathDirectory",
  63. [NSNumber numberWithInteger:domainMask],
  64. @"NSSearchPathDomainMask",
  65. nil];
  66. *errorOut =
  67. [NSError
  68. errorWithDomain:DirectoryLocationDomain
  69. code:DirectoryLocationErrorNoPathFound
  70. userInfo:userInfo];
  71. }
  72. return nil;
  73. }
  74. //
  75. // Normally only need the first path returned
  76. //
  77. NSString *resolvedPath = [paths objectAtIndex:0];
  78. //
  79. // Append the extra path component
  80. //
  81. if (appendComponent)
  82. {
  83. resolvedPath = [resolvedPath
  84. stringByAppendingPathComponent:appendComponent];
  85. }
  86. //
  87. // Check if the path exists
  88. //
  89. BOOL exists;
  90. BOOL isDirectory;
  91. exists = [self
  92. fileExistsAtPath:resolvedPath
  93. isDirectory:&isDirectory];
  94. if (!exists || !isDirectory)
  95. {
  96. if (exists)
  97. {
  98. if (errorOut)
  99. {
  100. NSDictionary *userInfo =
  101. [NSDictionary dictionaryWithObjectsAndKeys:
  102. NSLocalizedStringFromTable(
  103. @"File exists at requested directory location.",
  104. @"Errors",
  105. nil),
  106. NSLocalizedDescriptionKey,
  107. [NSNumber numberWithInteger:searchPathDirectory],
  108. @"NSSearchPathDirectory",
  109. [NSNumber numberWithInteger:domainMask],
  110. @"NSSearchPathDomainMask",
  111. nil];
  112. *errorOut =
  113. [NSError
  114. errorWithDomain:DirectoryLocationDomain
  115. code:DirectoryLocationErrorFileExistsAtLocation
  116. userInfo:userInfo];
  117. }
  118. return nil;
  119. }
  120. //
  121. // Create the path if it doesn't exist
  122. //
  123. NSError *error = nil;
  124. BOOL success = [self
  125. createDirectoryAtPath:resolvedPath
  126. withIntermediateDirectories:YES
  127. attributes:nil
  128. error:&error];
  129. if (!success)
  130. {
  131. if (errorOut)
  132. {
  133. *errorOut = error;
  134. }
  135. return nil;
  136. }
  137. }
  138. if (errorOut)
  139. {
  140. *errorOut = nil;
  141. }
  142. return resolvedPath;
  143. }
  144. //
  145. // applicationSupportDirectory
  146. //
  147. // Returns the path to the applicationSupportDirectory (creating it if it doesn't
  148. // exist).
  149. //
  150. - (NSString *)applicationSupportDirectory
  151. {
  152. NSString *executableName =
  153. [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleExecutable"];
  154. NSError *error;
  155. NSString *result =
  156. [self
  157. findOrCreateDirectory:NSApplicationSupportDirectory
  158. inDomain:NSUserDomainMask
  159. appendPathComponent:executableName
  160. error:&error];
  161. if (!result)
  162. {
  163. NSLog(@"Unable to find or create application support directory:\n%@", error);
  164. }
  165. return result;
  166. }
  167. @end