diff --git a/EWCacheManager.xcodeproj/project.pbxproj b/EWCacheManager.xcodeproj/project.pbxproj index e49d8c0..ae0e4ec 100644 --- a/EWCacheManager.xcodeproj/project.pbxproj +++ b/EWCacheManager.xcodeproj/project.pbxproj @@ -30,6 +30,7 @@ 075FAE951862546C00248796 /* libEWCacheManager.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 075FAE7D1862546C00248796 /* libEWCacheManager.a */; }; 075FAE9B1862546C00248796 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 075FAE991862546C00248796 /* InfoPlist.strings */; }; 075FAE9D1862546C00248796 /* EWCacheManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 075FAE9C1862546C00248796 /* EWCacheManagerTests.m */; }; + 07D5AF48188DF5D000C46D88 /* NSFileManager+DirectoryLocations.m in Sources */ = {isa = PBXBuildFile; fileRef = 07D5AF47188DF5D000C46D88 /* NSFileManager+DirectoryLocations.m */; }; D3682E884C5640F2AE01FE6D /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3630EA26D21847648CD89AFD /* libPods.a */; }; /* End PBXBuildFile section */ @@ -70,6 +71,8 @@ 075FAE9C1862546C00248796 /* EWCacheManagerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EWCacheManagerTests.m; sourceTree = ""; }; 07B6CC241862552300EB1FA7 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; 07B6CC261862552700EB1FA7 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; + 07D5AF46188DF5D000C46D88 /* NSFileManager+DirectoryLocations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSFileManager+DirectoryLocations.h"; sourceTree = ""; }; + 07D5AF47188DF5D000C46D88 /* NSFileManager+DirectoryLocations.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSFileManager+DirectoryLocations.m"; sourceTree = ""; }; 3630EA26D21847648CD89AFD /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; CF7F32F65DCC42E2ABECEDF3 /* Pods.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.xcconfig; path = ../Pods/Pods.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ @@ -101,11 +104,12 @@ 075FAE741862546C00248796 = { isa = PBXGroup; children = ( + 07D5AF49188DF5D400C46D88 /* Categories */, 075FAE821862546C00248796 /* EWCacheManager */, 075FAE961862546C00248796 /* EWCacheManagerTests */, 075FAE7F1862546C00248796 /* Frameworks */, - 075FAE7E1862546C00248796 /* Products */, CF7F32F65DCC42E2ABECEDF3 /* Pods.xcconfig */, + 075FAE7E1862546C00248796 /* Products */, ); sourceTree = ""; }; @@ -167,6 +171,15 @@ name = "Supporting Files"; sourceTree = ""; }; + 07D5AF49188DF5D400C46D88 /* Categories */ = { + isa = PBXGroup; + children = ( + 07D5AF46188DF5D000C46D88 /* NSFileManager+DirectoryLocations.h */, + 07D5AF47188DF5D000C46D88 /* NSFileManager+DirectoryLocations.m */, + ); + name = Categories; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -298,6 +311,7 @@ buildActionMask = 2147483647; files = ( 075FAE881862546C00248796 /* EWCacheManager.m in Sources */, + 07D5AF48188DF5D000C46D88 /* NSFileManager+DirectoryLocations.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/NSFileManager+DirectoryLocations.h b/NSFileManager+DirectoryLocations.h new file mode 100644 index 0000000..2ffd42a --- /dev/null +++ b/NSFileManager+DirectoryLocations.h @@ -0,0 +1,36 @@ +// +// NSFileManager+DirectoryLocations.h +// +// Created by Matt Gallagher on 06 May 2010 +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. Permission is granted to anyone to +// use this software for any purpose, including commercial applications, and to +// alter it and redistribute it freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#import + +// +// DirectoryLocations is a set of global methods for finding the fixed location +// directoriess. +// +@interface NSFileManager (DirectoryLocations) + +- (NSString *)findOrCreateDirectory:(NSSearchPathDirectory)searchPathDirectory + inDomain:(NSSearchPathDomainMask)domainMask + appendPathComponent:(NSString *)appendComponent + error:(NSError **)errorOut; +- (NSString *)applicationSupportDirectory; + +@end diff --git a/NSFileManager+DirectoryLocations.m b/NSFileManager+DirectoryLocations.m new file mode 100644 index 0000000..4de2c36 --- /dev/null +++ b/NSFileManager+DirectoryLocations.m @@ -0,0 +1,155 @@ +// +// NSFileManager+DirectoryLocations.m +// +// Created by Matt Gallagher on 06 May 2010 +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. Permission is granted to anyone to +// use this software for any purpose, including commercial applications, and to +// alter it and redistribute it freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#import "NSFileManager+DirectoryLocations.h" + +enum +{ + DirectoryLocationErrorNoPathFound, + DirectoryLocationErrorFileExistsAtLocation +}; + +NSString * const DirectoryLocationDomain = @"DirectoryLocationDomain"; + +@implementation NSFileManager (DirectoryLocations) + +// +// findOrCreateDirectory:inDomain:appendPathComponent:error: +// +// Method to tie together the steps of: +// 1) Locate a standard directory by search path and domain mask +// 2) Select the first path in the results +// 3) Append a subdirectory to that path +// 4) Create the directory and intermediate directories if needed +// 5) Handle errors by emitting a proper NSError object +// +// Parameters: +// searchPathDirectory - the search path passed to NSSearchPathForDirectoriesInDomains +// domainMask - the domain mask passed to NSSearchPathForDirectoriesInDomains +// appendComponent - the subdirectory appended +// errorOut - any error from file operations +// +// returns the path to the directory (if path found and exists), nil otherwise +// +- (NSString *)findOrCreateDirectory:(NSSearchPathDirectory)searchPathDirectory + inDomain:(NSSearchPathDomainMask)domainMask + appendPathComponent:(NSString *)appendComponent + error:(NSError **)errorOut +{ + // + // Search for the path + // + NSArray* paths = NSSearchPathForDirectoriesInDomains( + searchPathDirectory, + domainMask, + YES); + if ([paths count] == 0) + { + if (errorOut) + { + NSDictionary *userInfo = + [NSDictionary dictionaryWithObjectsAndKeys: + NSLocalizedStringFromTable( + @"No path found for directory in domain.", + @"Errors", + nil), + NSLocalizedDescriptionKey, + [NSNumber numberWithInteger:searchPathDirectory], + @"NSSearchPathDirectory", + [NSNumber numberWithInteger:domainMask], + @"NSSearchPathDomainMask", + nil]; + *errorOut = + [NSError + errorWithDomain:DirectoryLocationDomain + code:DirectoryLocationErrorNoPathFound + userInfo:userInfo]; + } + return nil; + } + + // + // Normally only need the first path returned + // + NSString *resolvedPath = [paths objectAtIndex:0]; + + // + // Append the extra path component + // + if (appendComponent) + { + resolvedPath = [resolvedPath + stringByAppendingPathComponent:appendComponent]; + } + + // + // Create the path if it doesn't exist + // + NSError *error = nil; + BOOL success = [self + createDirectoryAtPath:resolvedPath + withIntermediateDirectories:YES + attributes:nil + error:&error]; + if (!success) + { + if (errorOut) + { + *errorOut = error; + } + return nil; + } + + // + // If we've made it this far, we have a success + // + if (errorOut) + { + *errorOut = nil; + } + return resolvedPath; +} + +// +// applicationSupportDirectory +// +// Returns the path to the applicationSupportDirectory (creating it if it doesn't +// exist). +// +- (NSString *)applicationSupportDirectory +{ + NSString *executableName = + [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleExecutable"]; + NSError *error; + NSString *result = + [self + findOrCreateDirectory:NSApplicationSupportDirectory + inDomain:NSUserDomainMask + appendPathComponent:executableName + error:&error]; + if (!result) + { + NSLog(@"Unable to find or create application support directory:\n%@", error); + } + return result; +} + +@end