2012-10-16 27 views
9

Tôi đang sử dụng NSFileWrapper cho tài liệu gói của mình. Đôi khi, khi tôi yêu cầu dữ liệu của một tệp bên trong gói, tôi nhận được nil.NSFileWrapper trả về nil, đôi khi

Đây là cách tôi truy vấn dữ liệu của một tập tin bên trong gói:

- (NSData*) dataOfFile(NSString*)filename { 
    NSFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename]; 
    return fileWrapper.regularFileContents; // This returns nil sometimes. Why? 
} 

Phương pháp này cuối cùng bắt đầu trở về con số không đối với một số file (không phải tất cả). Đáng buồn thay, tôi đã không quản lý được vấn đề một cách nhất quán.

Trong trường hợp nó giúp, đây là cách tôi mở gói:

- (BOOL) readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError { 
    self.documentFileWrapper = fileWrapper; 
    return YES; 
} 

Đây là cách tôi cập nhật dữ liệu của một tập tin bên trong gói:

- (void) updateFile:(NSString*)filename withData:(NSData*)data { 
    SBFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename]; 
    if (fileWrapper) { 
     [self.documentFileWrapper removeFileWrapper:fileWrapper]; 
    } 
    NSFileWrapper *fileWrapper = [[SBFileWrapper alloc] initRegularFileWithContents:data ]; 
    fileWrapper.preferredFilename = filename; 
    [self.documentFileWrapper addFileWrapper:fileWrapper]; 
} 

Đây là cách tôi lưu gói:

- (NSFileWrapper*) fileWrapperOfType:(NSString *)typeName error:(NSError *__autoreleasing *)outError { 
    return self.documentFileWrapper; 
} 

Tại sao điều này có thể xảy ra? Có cách nào để ngăn chặn nó không?

Các tài liệu của regularFileContents xuất hiện để nói về vấn đề này:

This method may return nil if the user modifies the file after you call readFromURL:options:error: or initWithURL:options:error: but before NSFileWrapper has read the contents of the file. Use the NSFileWrapperReadingImmediate reading option to reduce the likelihood of that problem.

Nhưng tôi không hiểu những gì đã được thay đổi trong đoạn code trên để ngăn chặn tình trạng này.

Experiments Không

tôi đã cố gắng tiết kiệm tài liệu nếu regularFileContents trở lại con số không nhưng nó vẫn trả về nil sau đó. Như thế này:

- (NSData*) dataOfFile(NSString*)filename { 
    NSFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename]; 
    NSData *data = fileWrapper.regularFileContents; 
    if (!data) { 
      [self saveDocument:nil]; 
      fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename]; 
      data = fileWrapper.regularFileContents; 
    } 
    return data; 
} 
+0

Đây là một dự đoán điên rồ, nhưng tôi tự hỏi liệu đèn chiếu có sửa đổi các thuộc tính tệp sau khi bạn lưu (giống như nó reindexes tệp hay gì đó) không? Tôi là một chút tò mò lý do tại sao bạn đang tiết kiệm sau khi nó không thành công; tại sao không mở lại nó? Chỉ cần đoán để thử và cung cấp cho bạn một số ý tưởng. – Dad

+0

Đoán hoang dã, nhưng tôi nghĩ rằng đối tượng của bạn được phát hành. Có thể đã xảy ra sự cố với phân bổ. Bạn đã thử phân tích chưa? Hãy cẩn thận với phân bổ & init (và tự. + Autorelease và phát hành). – Roger

Trả lời

3

Không có đủ mã để xem điều gì đang thực sự xảy ra. Tuy nhiên nguyên nhân gốc là NSFileWrapper chỉ là tên của nó ngụ ý: một đối tượng mà đại diện cho một tệp hoặc thư mục. Vì vậy, các tập tin thực tế hoặc thư mục có thể dễ dàng nhận được "ra khỏi đồng bộ" với đối tượng, mà sống trong bộ nhớ. Bất cứ khi nào NSFileWrapper xác định rằng điều này đã xảy ra, nó trả về nil cho các hoạt động nhất định. Giải pháp là làm cho các đối tượng NSFileWrapper tồn tại trong thời gian ngắn. Tạo và mở ngay khi bạn cần chúng và sau đó lưu và đóng càng sớm càng tốt.

Cụ thể, có vẻ như mã của bạn đang giữ con trỏ đến trình bao bọc thư mục gói trong một thời gian dài và giả sử rằng nó luôn hợp lệ. Nếu thư mục thay đổi vì bất kỳ lý do nào thì đây không phải là trường hợp. Recode để bạn có được một wrapper thư mục gói mới mỗi khi bạn cần nó, và vấn đề nên biến mất.

0

Nếu tệp thay đổi trên đĩa thì bạn sẽ nhận được nil (như @Gene nói). Tuy nhiên, bạn có thể kiểm tra điều này bằng cách sử dụng phương pháp matchesContentsOfURL: đó:

determines whether a disk representation may have changed, based on the file attributes stored the last time the file was read or written. If the file wrapper’s modification time or access permissions are different from those of the file on disk, this method returns YES. You can then use readFromURL:options:error:

này từ Working with File Wrappers tài liệu hướng dẫn của Apple.

Chú giải này từ giới thiệu đến phần đó:

Because the purpose of a file wrapper is to represent files in memory, it’s very loosely coupled to any disk representation. A file wrapper doesn’t record the path to the disk representation of its contents. This allows you to save the same file wrapper with different URLs, but it also requires you to record those URLs if you want to update the file wrapper from disk later.

Vì vậy, bạn sẽ phải lưu url đến tập tin ban đầu nếu bạn muốn/cần phải đọc lại nó.

Thú vị khi nghe những gì matchesContentsofURL: trả lại khi bạn thấy kết quả không.

Các vấn đề liên quan