2010-12-08 2 views
1

그래서 내 응용 프로그램이 종료되고 해당 배열을 파일에서 관련 ViewController로 읽어 들일 때 파일에 커스텀 객체 (Course Planner 응용 프로그램을위한 대학 과정을 나타내는 "Course") NSMutableArray를 작성하려고합니다. 응용 프로그램이 시작될 때 데이터를 사용하십시오.내 <NSCoding> 개체의 속성 중 하나만 파일에 제대로 기록되는 이유는 무엇입니까?

CoursesAppDelegate.m :

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  

    // Override point for customization after application launch. 
    coursesViewController = [[SampleHomeScreen alloc] initWithNibName:@"SampleHomeScreen" bundle:nil]; 

    NSString *filePath = [self dataFilePath]; 
    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) { 
     [coursesViewController setCourses:[NSKeyedUnarchiver unarchiveObjectWithFile: filePath]]; 
    } 

    UIApplication *app = [UIApplication sharedApplication]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:)name:UIApplicationWillTerminateNotification object:app]; 

    [window addSubview:coursesViewController.view]; 
    [window makeKeyAndVisible]; 

    return YES; 
} 

- (NSString *)dataFilePath { 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"data.plist"]; 
    NSLog(@"%@", path); 
    return path; 
} 

/** 
applicationWillTerminate: saves changes in the application's managed object context before the application terminates. 
*/ 
- (void)applicationWillTerminate:(UIApplication *)application { 
    NSLog(@"%@", [coursesViewController courses]); 
    [NSKeyedArchiver archiveRootObject:[coursesViewController courses] toFile:[self dataFilePath]]; 
} 

Course.h :

@interface Course : NSObject <NSCoding> { 
    NSString *name; //e.g. ECS 189H 
    double grade, totalWeight; //course grade in % 
    NSMutableArray *list; 
} 

@property (nonatomic, retain) NSString *name; 
@property (nonatomic) double grade, totalWeight; 
@property (nonatomic, retain) NSMutableArray *list; 

-(Course *)initWithName:(NSString *)courseName; 

@end 

Course.m :

@implementation Course 

@synthesize name, grade, totalWeight, list; 

-(Course *)initWithName:(NSString *)courseName { 
    name = [courseName retain]; 
    grade = -1.0; 
    totalWeight = 0.0; 
    list = [[NSMutableArray alloc] init]; 
    [super init]; 
    return self; 
} 

-(Course *)initWithCoder:(NSCoder *)aDecoder { 
    self.name = [aDecoder decodeObjectForKey:@"name"]; 
    self.grade = [aDecoder decodeDoubleForKey:@"grade"]; 
    self.totalWeight = [aDecoder decodeDoubleForKey:@"totalWeight"]; 
    self.list = [aDecoder decodeObjectForKey:@"list"]; 
    [super init]; 
    return self; 
} 

- (void) encodeWithCoder: (NSCoder *)coder 
{ 
    [coder encodeObject:name forKey:@"name"]; 
    [coder encodeDouble:grade forKey:@"grade"]; 
    [coder encodeDouble:totalWeight forKey:@"totalWeight"]; 
    [coder encodeObject:list forKey:@"list"]; 
} 

-(void)dealloc { 
    [name release]; 
    [list release]; 
    [super dealloc]; 
} 

@end 

[coursesViewController 과정 여기

는 관련 코드 ]는 NSMuta입니다. course 객체를 보유하고있는 bleArray입니다. 나는 그것이 유효한 데이터를 가지고 있다는 사실을 안다.

그래서 문제가 있습니다 : 1 : xcode에서 실행 (xcode에서 "컴파일 및 실행"클릭) 할 때만 응용 프로그램이 data.plist에 저장합니다. 2 : plist에서 데이터를로드하지만 저장되는 것은 모두 코스 이름과 grade 및 totalWeight (각각 -1 및 0)의 기본값입니다. 그래서 실제로 initWithName이 먼저 호출 된 것처럼 저장됩니다.

이것은 상당히 진보 된 iOS 응용 프로그램에 대한 나의 진정한 탐구입니다. 그래서 나는 이것에 초보자로서, 중요한 정보를 생략했을 것입니다. 이 경우 알려 주시면 질문을 업데이트하겠습니다.

감사합니다. -HT

p.s. 관련이 있다면 info.plist에서 doNotRunInBackground를 true로 설정했습니다.

답변

1

개체가 초기화되기 전에 값을 설정하려고합니다. 그런 다음 초기화하면 값이 재설정됩니다.

-(Course *)initWithName:(NSString *)courseName { 
    name = [courseName retain];    // <- Accessing ivar before self is initialized 
    grade = -1.0;       // <- Accessing ivar before self is initialized 
    totalWeight = 0.0;      // <- Accessing ivar before self is initialized 
    list = [[NSMutableArray alloc] init]; // <- Accessing ivar before self is initialized 
    [super init];       // initialization resets your values !!!! 
    return self; 
} 

은 또한 당신은 모든 경우의 좋은 98 %를 작동 슈퍼의 init 반환 값을 무시하고 있지만 나는 항상가 적절한 초기화 방식 사용 에게 추천 : 코코아는 init에서

- (id)init { 
    if (self = [super init]) { 
     // It's save to access ivars here 
    } 
    return self 
} 

을 메서드는 다른 객체를 반환 한 다음 할당 된 객체를 반환 할 수 있습니다. 따라서 이어야합니다. super의 init에 자신을 지정하십시오.

-(Course *)initWithName:(NSString *)courseName { 
    if (self = [super init]) { 
     name = [courseName retain]; 
     grade = -1.0; 
     totalWeight = 0.0; 
     list = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 

같은이 initWithCoder:(NSCoder *)coder에 적용처럼

그래서, 당신의 초기화가 보일 것입니다.

+0

와우. 나는 당신이 말한대로, 다음 두 개의 다른 클래스에서 선택자 오류에 응답하지 않음으로써 진행 상황을 만들었습니다 : 범주 (과제 또는 시험과 같은 코스의 "청크"를 나타냄) 및 항목 (실제 채점 된 항목을 나타냄) . 나는이 2를 NSCoding을 구현하도록 만들었고, 낮게 보았다. 내 문제가 해결 된 것처럼 보였고, 코딩 스타일의 끔찍한 결함 (내가 어떻게 내 글을 쓰는지)을 지적했습니다. 나는 영원히 감사 드리고 있습니다. 어쨌든, 고마워! – HTR

관련 문제