iOS:无法将文件保存到“应用程序支持”文件夹,但可以将“文档”

我可以使用自定义名称下载并保存二进制文件到“文档”文件夹中。

如果我只是将URL更改为“应用程序支持”文件夹,而不是“文档”文件夹,则无法写入该URL,表示该URL不存在。

以下是url构build代码:

- ( NSURL * ) getSaveFolder { NSURL * appSupportDir = nil; NSURL * appDirectory = nil; NSArray * possibleURLs = [[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSAllDomainsMask]; if ( [possibleURLs count] >= 1 ) { appSupportDir = [possibleURLs objectAtIndex:0]; } if ( appSupportDir != nil) { NSString * appBundleID = [[NSBundle mainBundle] bundleIdentifier]; appDirectory = [appSupportDir URLByAppendingPathComponent:appBundleID]; } return appSupportDir; } 

这是保存代码:

 - ( void ) writeOutDataToFile:( NSData * )data { NSURL * finalURL = [self.rootPathURL URLByAppendingPathComponent:self.aFileName]; [data writeToURL:finalURL atomically:YES]; } 

如果我将NSArray更改为:

 NSArray * possibleURLs = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; 

那么它可以保存好。

我已经阅读了关于文件的Apple Docs文件,无法解决这个问题 – 我错过了什么?

Documents目录不同,默认情况下Application Support目录不存在于应用程序的沙箱中。 您需要先创build它,然后才能使用它。

而一个更简单的方法来获得对该目录的引用是:

 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); NSString *appSupportDirectory = paths.firstObject; 

如果有人不确定如何做rmaddy描述:

 NSString *appSupportDir = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) lastObject]; //If there isn't an App Support Directory yet ... if (![[NSFileManager defaultManager] fileExistsAtPath:appSupportDir isDirectory:NULL]) { NSError *error = nil; //Create one if (![[NSFileManager defaultManager] createDirectoryAtPath:appSupportDir withIntermediateDirectories:YES attributes:nil error:&error]) { NSLog(@"%@", error.localizedDescription); } else { // *** OPTIONAL *** Mark the directory as excluded from iCloud backups NSURL *url = [NSURL fileURLWithPath:appSupportDir]; if (![url setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:&error]) { NSLog(@"Error excluding %@ from backup %@", url.lastPathComponent, error.localizedDescription); } else { NSLog(@"Yay"); } } } 

我遇到了同样的问题,并决定使用更简洁的方法:

 let fileManager = NSFileManager.defaultManager() let urls = fileManager.URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask) as! [NSURL] if let applicationSupportURL = urls.last { fileManager.createDirectoryAtURL(applicationSupportURL, withIntermediateDirectories: true, attributes: nil, error: nil) } 

这是withIntermediateDirectories: true因为createDirectoryAtURL使用withIntermediateDirectories: true只会在文件夹不存在的withIntermediateDirectories: true下创build。

下面是iOS的一些Swift代码,可以将二进制数据文件写入应用程序支持目录。 这部分是由chrysAllwood的答案启发。

  /// Method to write a file containing binary data to the "application support" directory. /// /// - Parameters: /// - fileName: Name of the file to be written. /// - dataBytes: File contents as a byte array. /// - optionalSubfolder: Subfolder to contain the file, in addition to the bundle ID subfolder. /// If this is omitted no extra subfolder is created/used. /// - iCloudBackupForFolder: Specify false to opt out from iCloud backup for whole folder or /// subfolder. This is only relevant if this method call results in /// creation of the folder or subfolder, otherwise it is ignored. /// - Returns: Nil if all OK, otherwise text for a couple of non-Error errors. /// - Throws: Various errors possible, probably of type NSError. public func writeBytesToApplicationSupportFile(_ fileName : String, _ dataBytes : [UInt8], optionalSubfolder : String? = nil, iCloudBackupForFolder : Bool = true) throws -> String? { let fileManager = FileManager.default // Get iOS directory for "application support" files let appSupportDirectory = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).first if appSupportDirectory == nil { return "Unable to determine iOS application support directory for this app." } // Add "bundle ID" as subfolder. This is recommended by Apple, although it is probably not // necessary. if Bundle.main.bundleIdentifier == nil { return "Unable to determine bundle ID for the app." } var mySupportDirectory = appSupportDirectory!.appendingPathComponent(Bundle.main.bundleIdentifier!) // Add an additional subfolder if that option was specified if optionalSubfolder != nil { mySupportDirectory = appSupportDirectory!.appendingPathComponent(optionalSubfolder!) } // Create the folder and subfolder(s) as needed if !fileManager.fileExists(atPath: mySupportDirectory.path) { try fileManager.createDirectory(atPath: mySupportDirectory.path, withIntermediateDirectories: true, attributes: nil) // Opt out from iCloud backup for this subfolder if requested if !iCloudBackupForFolder { var resourceValues : URLResourceValues = URLResourceValues() resourceValues.isExcludedFromBackup = true try mySupportDirectory.setResourceValues(resourceValues) } } // Create the file if necessary let mySupportFile = mySupportDirectory.appendingPathComponent(fileName) if !fileManager.fileExists(atPath: mySupportFile.path) { if !fileManager.createFile(atPath: mySupportFile.path, contents: nil, attributes: nil) { return "File creation failed." } } // Write the file (finally) let fileHandle = try FileHandle(forWritingTo: mySupportFile) fileHandle.write(NSData(bytes: UnsafePointer(dataBytes), length: dataBytes.count) as Data) fileHandle.closeFile() return nil }