2013-04-25 22 views
28

Tôi có thể tải xuống và lưu tệp nhị phân vào thư mục 'Tài liệu' với tên tùy chỉnh hoàn toàn tốt.iOS: Không thể lưu tệp vào thư mục 'Hỗ trợ Ứng dụng', nhưng có thể 'Tài liệu'

Nếu tôi chỉ thay đổi URL thành thư mục 'Hỗ trợ ứng dụng' thay vì thư mục 'Tài liệu', nó không ghi vào URL đó nói rằng nó không tồn tại.

Dưới đây là các mã xây dựng 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; 
} 

Dưới đây là mã tiết kiệm:

- (void) writeOutDataToFile:(NSData *)data 
{ 

    NSURL * finalURL = [self.rootPathURL URLByAppendingPathComponent:self.aFileName]; 

    [data writeToURL:finalURL atomically:YES]; 
} 

Nếu tôi thay đổi NSArray đến:

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

sau đó nó tiết kiệm tốt .

Tôi đã đọc Apple Tài liệu trên tệp và không thể sửa lỗi này - tôi thiếu gì?

+0

Tại sao bạn thêm id gói vào cuối đường dẫn? Thư mục đã là duy nhất cho ứng dụng của bạn. Việc thêm id gói là không cần thiết. – rmaddy

+0

Vì mã đó được sao chép TRỰC TIẾP từ Hướng dẫn lập trình hệ thống tệp của Apple (Liệt kê 2-1) làm cách chính xác để tạo URL cho một mục trong thư mục hỗ trợ ứng dụng. – iOSProgrammingIsFun

+2

Mã đó không có ý nghĩa đối với iOS. Nó vẫn ổn cho OS X. Trong iOS, thư mục 'Application Support' đã nằm trong sandbox của ứng dụng của bạn. Trong OS X, nó không phải. – rmaddy

Trả lời

41

Không giống như thư mục Documents, thư mục Application Support không tồn tại trong hộp cát của ứng dụng theo mặc định. Bạn cần phải tạo nó trước khi bạn có thể sử dụng nó.

Và một cách đơn giản hơn nhiều để có được một tham chiếu đến thư mục là:

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

Điều này không hoạt động. Lỗi tương tự - không thể tìm/mở tệp. – iOSProgrammingIsFun

+7

Bạn đã tạo thư mục như tôi đã nêu chưa? – rmaddy

43

Trong trường hợp bất cứ ai là không chắc chắn làm thế nào để làm những gì rmaddy mô tả:

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"); 
     } 
    } 
} 
+1

Cảm ơn bạn đã dành thời gian chia sẻ một ví dụ! – Doug

+0

@chrysallwood, hãy quan tâm chia sẻ phiên bản nhanh? –

+0

Không hoạt động cho tôi, thật không may – bgplaya

3

tôi đi qua cùng một vấn đề và quyết định sử dụng cách tiếp cận ngắn gọn hơn:

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

Điều này hoạt động vì createDirectoryAtURL sử dụng withIntermediateDirectories: true chỉ tạo thư mục nếu nó không tồn tại.

1

Dưới đây là một số mã Swift cho iOS có thể ghi tệp dữ liệu nhị phân vào thư mục hỗ trợ ứng dụng. Các phần này được lấy cảm hứng từ câu trả lời của 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 
    } 
Các vấn đề liên quan