2013-04-02 2 views
0

그래서 NS 코딩을 구현 한 객체가 있습니다. 나는 하루 종일 내 머리를 깨뜨 렸어. 내가 이해 한대로, NSCoding을 구현했기 때문에 배열 자체에 아카이브/아카이브 해제 메소드가 호출 될 때 배열의 인덱스를 인코딩하고 디코딩해야합니다. 그래서 그것이 어떻게 작동하는지에 대한 나의 이해가 꺼져 있거나 구현에 약간의 오류가 있습니다.iOS 직렬화/직렬화가 제대로 작동하지 않습니다.

파일이 쓰여지고 배열이 deserialized되고 그 안에 개체가 있음을 보여줍니다. 그러나 배열의 클래스에는 데이터가 없습니다.

이 인코딩은 다음과 같습니다
#pragma mark NSCoding 

#define kTitle    @"Title" 
#define kDescription  @"Description" 
#define kIsCompleted  @"IsCompleted" 
#define kDate    @"Date" 
#define kImage    @"Image" 

-(id)initWithCoder:(NSCoder *)decoder 
{ 
    [super init]; 
    title = [decoder decodeObjectForKey:kTitle]; 
    description = [decoder decodeObjectForKey:kDescription]; 
    isCompleted = [decoder decodeBoolForKey:kIsCompleted]; 
    date = [decoder decodeObjectForKey:kDate]; 
    image = [decoder decodeObjectForKey:kImage]; 

    return self; 
} 

-(void) encodeWithCoder:(NSCoder *) encoder 
{ 
    [encoder encodeObject:title forKey:kTitle]; 
    [encoder encodeObject:description forKey:kDescription]; 
    [encoder encodeBool:isCompleted forKey:kIsCompleted]; 
    [encoder encodeObject:date forKey:kDate]; 
    [encoder encodeObject:image forKey:kImage]; 
} 

@end 

, 몇 가지 문제 해결이 변경되었습니다이 ':

-(void) writeFile 
{ 
    NSData *encodedObject; 
    encodedObject = [NSKeyedArchiver archivedDataWithRootObject: bucketItems]; 
    //NSFileHandle *file; 
    // file = [NSFileHandle fileHandleForWritingAtPath:filePath]; 

    //if(true)//file == nil) 
    //{ 
     //NSLog(@"Failed to open a file handle for writing. Attempting to create a file."); 
     //[[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil]; 
     //file = [NSFileHandle fileHandleForWritingAtPath:filePath]; 
     //if(file == nil) 
     //{ 
     // NSLog(@"Unable to create new file."); 
     // } 
    //} 

    [encodedObject writeToFile:self.filePath atomically:YES]; 
    //[file writeData: encodedObject]; 
    //[file closeFile]; 
} 

다음 디코딩이 여기에서 발생, 프로그램이 시작, 검사

구현은 다음과 같습니다 저장된 데이터가 있고로드하는 경우

NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:filePath]; 
     NSData *fileData; 
     fileData = [file readDataToEndOfFile]; 
     bucketItems = [NSKeyedUnarchiver unarchiveObjectWithData:fileData]; 
     NSLog(@"Data file found: loading"); 
     [file closeFile]; 
+0

initWithCoder가 호출되는 중 ?? – Rob

+0

예 .. 그게 .. 내가 확인하지 않았고 필드가 디코딩되고있는 것처럼 보입니다. 이제 배열이 제대로 초기화 된 객체를 보지 못합니다. –

+0

그래서 bucketItems는 각 항목이있는 동일한 배열이됩니다. 올바른 속성 ?? 당신이 끝났다는 소리 ?? (로거 중단 점을 사용하여 콘솔을 아카이브 해제 한 직후에 덤프하십시오.) – Rob

답변

1

내에서 initWithCoder: 메서드를 사용하면 결과가 으로 할당되고 인스턴스 변수에 직접 할당 된 모든 객체가 유지되거나 복사되는 두 가지가 누락되었습니다. [super init]을 자기에게 할당하지 않고 도망 갈 수는 있지만 인스턴스 변수를 유지하면 재앙이 될 수 없습니다.

수동 참조 계산 환경에서 소유권을 이전하는 메소드가 호출되지 않는 한 객체는 인스턴스 변수에 할당 된 값의 소유권을 가져 가지 않습니다. 그 방법은 new, alloc, retaincopy/mutableCopy (또한 Core Foundation 작성 및 복사 기능)입니다. NARC라는 약자를 니모닉 장치로 사용하십시오. ivars (NSKeyedUnarchiver)에 할당 된 객체를 생성 한 객체 나 객체 자체를 소유하지 않으므로 할당되지 않습니다. 이를 방지하려면 ivars에 지정한 오브젝트를 유지하거나 복사하십시오. 할당 된 객체가 변경 가능하고 다른 객체에 의해 변형 될 수 있다고 의심되는 경우 원치 않는 변형을 방지하기 위해 복사를 수행해야합니다. 그렇지 않으면 값을 유지하십시오. 마지막으로 releasedealloc으로 호출하거나 개체를 더 할당하기 전에 (합성 또는 수동 구현 된 설정 메서드로 수행해야 함) 해당 개체의 소유권을 양도해야합니다.

마지막 한가지 - 당신은 NSKeyedArchiverNSKeyedUnarchiver 방법 archiveRootObject:toFile: 대신 파일 핸들러와 NSFileManager 다루는 unarchiveObjectWithFile:를 사용할 수 있습니다. 이것은 오류보고가 좋지 않지만 간단한 경우에는 잘 작동합니다.

관련 문제