可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I guess this is a beginner's problem, but I was trying to check if a directory exists in my Documents folder on the iPhone. I read the documentation and came up with this code which unfortunately crashed with EXC_BAD_ACCESS in the BOOL fileExists line:
-(void)checkIfDirectoryAlreadyExists:(NSString *)name { NSFileManager *fileManager = [[NSFileManager alloc] init]; NSString *path = [[self documentsDirectory] stringByAppendingPathComponent:name]; BOOL fileExists = [fileManager fileExistsAtPath:path isDirectory:YES]; if (fileExists) { NSLog(@"Folder already exists..."); } }
I don't understand what I've done wrong? It looks all perfect to me and it certainly complies with the docs, not? Any revelations as to where I went wrong would be highly appreciated! Thanks.
UPDATED:
Still not working...
-(void)checkIfDirectoryAlreadyExists:(NSString *)name { NSFileManager *fileManager = [[NSFileManager alloc] init]; NSString *path = [[self documentsDirectory] stringByAppendingPathComponent:name]; BOOL isDir; BOOL fileExists = [fileManager fileExistsAtPath:path isDirectory:&isDir]; if (fileExists) { if (isDir) { NSLog(@"Folder already exists..."); } } }
回答1:
Take a look in the documentation for this method signature:
- (BOOL)fileExistsAtPath:(NSString *)path isDirectory:(BOOL *)isDirectory
You need a pointer to a BOOL var as argument, not a BOOL itself. NSFileManager will record if the file is a directory or not in that variable. For example:
BOOL isDir; BOOL exists = [fm fileExistsAtPath:path isDirectory:&isDir]; if (exists) { /* file exists */ if (isDir) { /* file is a directory */ } }
回答2:
Just in case somebody needs a getter, that creates a folder in Documents, if it doesn't exist:
- (NSString *)folderPath { if (! _folderPath) { NSString *folderName = @"YourFolderName"; NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectoryPath = [documentPaths objectAtIndex:0]; _folderPath = [documentsDirectoryPath stringByAppendingPathComponent:folderName]; // if folder doesn't exist, create it NSError *error = nil; NSFileManager *fileManager = [NSFileManager defaultManager]; BOOL isDir; if (! [fileManager fileExistsAtPath:_folderPath isDirectory:&isDir]) { BOOL success = [fileManager createDirectoryAtPath:_folderPath withIntermediateDirectories:NO attributes:nil error:&error]; if (!success || error) { NSLog(@"Error: %@", [error localizedDescription]); } NSAssert(success, @"Failed to create folder at path:%@", _folderPath); } } return _folderPath; }
回答3:
I have a Utility singleton class that I use for things like this. Since I can’t update my database if it remains in Documents, I copy my .sqlite files from Documents to /Library/Private Documents using this code. The first method finds the Library. The second creates the Private Documents folder if it doesn’t exist and returns the location as a string. The second method uses the same file manager method that @wzboson used.
+ (NSString *)applicationLibraryDirectory { return [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject]; } + (NSString *)applicationLibraryPrivateDocumentsDirectory { NSError *error; NSString *PrivateDocumentsDirectory = [[self applicationLibraryDirectory] stringByAppendingPathComponent:@"Private Documents"]; BOOL isDir; if (! [[NSFileManager defaultManager] fileExistsAtPath:PrivateDocumentsDirectory isDirectory:&isDir]) { if (![[NSFileManager defaultManager] createDirectoryAtPath:PrivateDocumentsDirectory withIntermediateDirectories:NO attributes:nil error:&error]) { NSLog(@"Create directory error: %@", error); } } return PrivateDocumentsDirectory; }
I use it like this in my persistent store coordinator initialization. The same principal applies to any files though.
NSString *libraryDirectory = [Utilities applicationLibraryPrivateDocumentsDirectory]; NSString *sourcePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:sqliteName]; NSString *destinationPath = [libraryDirectory stringByAppendingPathComponent:sqliteName];