2012-10-16 4 views
9

내 패키지 문서에 NSFileWrapper을 사용하고 있습니다. 때로는 패키지 안에있는 파일의 데이터를 요청하면 nil이됩니다.NSFileWrapper가 nil을 반환하는 경우가 있음

이 내가 패키지 내부의 파일의 데이터를 쿼리하는 방법입니다

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

이 방법은 결국 일부 파일 (모든)에 대한 무기 호를 반환 시작합니다. 슬프게도 문제를 일관되게 재현 할 수 없었습니다.

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

이 내가 패키지 내부의 파일의 데이터를 업데이트하는 방법은 다음과 같습니다 :

- (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]; 
} 

이 내가 저장하는 방법입니다 그것이 도움이 경우

이 내가 패키지를 열고 어떻게 패키지 :

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

왜 이런 일이 벌어 질 수 있습니까? 그것을 막을 수있는 방법이 있습니까?

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.

그러나 나는 이러한 상황을 방지하기 위해 위의 코드를 변경해야하는 것을 이해하지 않습니다

regularFileContents의 문서는이 문제에 대해 얘기를 나타납니다.

실패 실험

나는 regularFileContents 반환 전무는하지만 여전히 이후 nil을 반환하는 경우 문서를 저장했습니다. 이와 같이 :

- (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

이것은 미친 생각이지만 파일을 다시 색인하는 것처럼 저장 후 스포트라이트가 파일 속성을 수정하고 있는지 궁금합니다. 나는 실패한 후에 왜 절약하고 있는지 약간 궁금하다. 대신 왜 다시 열지 않으시겠습니까? 그냥 당신에게 몇 가지 아이디어를 줄 추측. – Dad

+0

짐작 하겠지만, 당신의 물건이 풀려나는 것 같아요. 어쩌면 alloc에 ​​문제가 생길 수 있습니다. 분석을 시도 했습니까? alloc & init (와 self. + autorelease와 release)에주의하라. – Roger

답변

3

실제 진행 상황을 확인할 수있는 코드가 충분하지 않습니다. 그러나 근본 원인은 NSFileWrapper이 그 이름에서 알 수있는 바로 그 것입니다. 이 나타내는 파일은입니다. 따라서 실제 파일이나 디렉터리는 메모리에있는 개체와 "동기화되지"않습니다. NSFileWrapper은 이것이 _ 생한 것으로 판별 할 때마다 특정 조작에 대해 nil을 리턴합니다. 해결 방법은 NSFileWrapper 개체의 수명을 단축하는 것입니다. 필요한 때에 작성하여 열고 가능한 한 빨리 저장하고 닫으십시오.

특히 코드는 패키지 디렉토리 래퍼에 대한 포인터를 오랫동안 보관하고 있으며 항상 유효하다고 가정합니다. 디렉토리가 어떤 이유로 든 변경된 경우에는 그렇지 않습니다. 당신이 필요로 할 때마다 새로운 패키지 디렉토리 래퍼를 얻을 수 있도록 코드를 다시 작성하십시오. 문제는 사라져야합니다.

0

파일이 디스크에서 변경되면 nil이 발생합니다 (@Gene의 말처럼). 그러나 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:

Working with File Wrappers에서 애플 문서를. 해당 섹션에 소개에서

참고이 :

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.

그래서 당신은 당신이 원하는 경우/필요성을 다시 읽어 그것은에 원본 파일에 대한 URL을 저장해야합니다.

아무런 결과가 표시되지 않을 때 matchesContentsofURL:이 무엇을 듣고 있는지 재미 있습니다.