2012-08-29 3 views
0

웹 서비스의 데이터를 초기화 한 다음 (NSCoding 및 NSKeyedUnarchiver 사용) 자체 파일을 저장하는 싱글 톤 클래스가 있으므로 웹에서 모든 데이터를 가져 오는 대신이 파일을 초기화 할 수 있습니다 다시. 저장되는 싱글 톤 인스턴스이기 때문에 평소처럼 싱글 톤 게터를 호출하고 아카이브 된 복사본이 있는지 확인하고 그렇지 않은 경우 데이터를 가져 와서 아카이브 할 수 있습니다. 보관은 정상적으로 작동하지만 sharedInstance가 초기화되기 전에 [[NSKeyedUnarchiver unarchiveObjectWithFile : filePath] retain]을 호출하려고하면 sharedInstance getter가 호출됩니다. 이로 인해 init가 호출되고 응용 프로그램은 모든 데이터를 다시 다운로드하여 이후에 unarchiver에 의해 덮어 씁니다.iOS NSKeyedUnarchiver 싱글 톤 게터를 호출합니다.

설치에 문제가 있습니까? 아니면이 데이터를 일련 화하는 다른 방법이 있습니까?

는 여기에 몇 가지 (간체) 코드입니다 :

@implementation Helmets 
@synthesize helmetList, helmetListVersion; 
//Class Fields 
static Helmets *sharedInstance = nil; 

// Get the shared instance and create it if necessary. 
+ (Helmets *)sharedInstance { 
    //if(sharedInstance == nil){ 
     //[Helmets unarchive];    //This does not work! Calls sharedInstance() again (recursion) 
     if(sharedInstance == nil){ 
      sharedInstance = [[super allocWithZone:NULL] init]; //Pull from web service 
      [Helmets archive]; //Save instance 
     //} 
    //} 
    return sharedInstance; 
} 

- (id)init { 
    self = [super init]; 
    if (self) { 
      helmetList = [[NSMutableArray alloc]init]; 

      //Get our data from the web service and save it (excluded) 
      } 
    } 
    return self; 
} 

//This works! 
+(void)archive{ 
    if([NSKeyedArchiver archiveRootObject:sharedInstance toFile:[Helmets getFilePath]]){ 
     NSLog(@"Archiving Successful"); 
    } 
    else{ 
     NSLog(@"Archiving Failed"); 
    } 
} 

//This works, but calls getInstance causing data to be downloaded anyways! 
+(void)unarchive{ 
    // Check if the file already exists 
    NSFileManager *filemgr = [NSFileManager defaultManager]; 
    NSString *filePath = [Helmets getFilePath]; 
    if ([filemgr fileExistsAtPath: filePath]) 
    { 
     sharedInstance = [[NSKeyedUnarchiver unarchiveObjectWithFile: filePath] retain]; 
    } 
    [filemgr release]; 
} 

인스턴스가 같은 초기화 :

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ 
    ... 
    [Helmets unarchive];  //This calls sharedInstance() too soon! 
    [Helmets sharedInstance]; 
} 

클래스는 .H에 NSCoding를 구현하고 initWithCoder와 encodeWithCoder을 무시 (보관이 작동).

미리 감사드립니다.

+1

'+ unarchive '가'+ sharedInstance'를 호출하여 어디에서 자세히 설명해 드릴 수 있습니까? –

+0

죄송합니다,'+ unarchive'는'+ sharedInstance'를 명시 적으로 호출하지 않습니다. '[[NSKeyedUnarchiver unarchiveObjectWithFile : filePath]가 유지 될 때]; '('+ unarchive '에서)'+ sharedInstance'가 우연히 호출됩니다. 나는이 동작을 NSKeyedUnarchiver에서 기대하지 않았다. – javajavajavajavajava

+0

'-retain'을 오버라이드 했습니까? –

답변

2

결국에는 공유 인스턴스를 설정하는 개인 메소드가 필요하며 구현에 대해 다시 다른 개인용 (init)이 필요합니다.

- (id)initAndFetch:(BOOL)fetch 
{ 
    if((self = [super init])) { 
     ... 

     if(fetch) { do the web fetch }; 
      ... 
    } 
} 

+ sharedInstance 메소드에서 YES를 전달합니다. 나는 그것이 다음과 같은 방법을 작동하도록 가지고있다

- (id)initWithCoder:(NSCoder *)decoder 
{ 
    if((self = [self initAndFetch:NO])) { 
     title = [decoder decodeObjectForKey:@"title"]; 
     ... 
     sharedInstance = self; 
    } 
    return self; 
} 
+0

David에게 감사드립니다. 이것은 잘 작동 할 것입니다. – javajavajavajavajava

1

: 같은

그런 다음 디코드 볼 것이다.

-(id)initWithCoder:(NSCoder *)aDecoder 
{ 
    self = [super init]; 
    if (!self) { 
     return nil; 
    } 
    UserInfo *user =[UserInfo sharedInstance]; 
    return user; 
} 

-(void)encodeWithCoder:(NSCoder *)aCoder 
{ 
    UserInfo *user =[UserInfo sharedInstance]; 
    [aCoder encodeObject: user.phoneNumber forKey:@"phoneNumber"]; 
} 



-(void)save 
{ 
    [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:[UserInfo sharedInstance]] forKey:@"USER_DATA"]; 
    [[NSUserDefaults standardUserDefaults]synchronize]; 

} 

-(UserInfo*)currentUser 
{ 
    NSData *data =[[NSUserDefaults standardUserDefaults] objectForKey:@"USER_DATA"]; 
    UserInfo *savedUser =[NSKeyedUnarchiver unarchiveObjectWithData:data]; 

    UserInfo *user =[UserInfo sharedInstance]; 
    return user; 
}