web-dev-qa-db-ja.com

iOS:「アプリケーションサポート」フォルダにファイルを保存できませんが、「ドキュメント」には保存できます

バイナリファイルをダウンロードして、「Documents」フォルダにカスタム名で完全に保存できます。

URLを「ドキュメント」フォルダではなく「アプリケーションサポート」フォルダに変更しただけでは、そのURLが存在しないというメッセージが表示されません。

URL構成コードは次のとおりです。

- ( 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 on Fileに関するものを読みましたが、これを修正できません-何が欠けていますか?

33

Documentsディレクトリとは異なり、Application Supportディレクトリは、デフォルトではアプリのサンドボックスに存在しません。使用する前に作成する必要があります。

そして、ディレクトリへの参照を取得するはるかに簡単な方法は次のとおりです。

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

誰かが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");
        }
    }
}
47
chrysAllwood

私は同じ問題に遭遇し、より簡潔なアプローチを使用することにしました:

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)
}

これは、createDirectoryAtURLwithIntermediateDirectories: trueを使用して存在しない場合にのみフォルダーを作成するため機能します。

7
csch

アプリケーションのサポートディレクトリにバイナリデータファイルを書き込める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
   }
4
RenniePet

1つのライナー-必要に応じて作成します。

[[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil]
2
RunLoop

Swift 4.2バージョン

    let fileManager = FileManager.default
    let urls = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask)
    if let applicationSupportURL = urls.last {
        do{
            try fileManager.createDirectory(at: applicationSupportURL, withIntermediateDirectories: true, attributes: nil)
        }
        catch{
            print(error)
        }
    }
0
Ozgur Sahin