Iphone 为什么只有我的一个属性<;NSCoding>;对象是否正确写入文件?

Iphone 为什么只有我的一个属性<;NSCoding>;对象是否正确写入文件?,iphone,objective-c,nscoding,Iphone,Objective C,Nscoding,因此,我尝试在应用程序终止时将自定义对象的NSMutableArray(一个“课程”表示课程规划器应用程序的大学课程)写入一个文件,然后将该数组从该文件读取到相关的ViewController中,应用程序启动时将使用该数据 以下是相关代码: 课程AppDelegate.m: - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

因此,我尝试在应用程序终止时将自定义对象的NSMutableArray(一个“课程”表示课程规划器应用程序的大学课程)写入一个文件,然后将该数组从该文件读取到相关的ViewController中,应用程序启动时将使用该数据

以下是相关代码:

课程AppDelegate.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]];
}
课程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
[coursesViewController courses]是保存课程对象的NSMutableArray。我知道一个事实,它持有有效的数据

所以问题是,, 1:应用程序仅在我从xcode运行时保存到data.plist(即在xcode中单击“编译并运行”)。 2:它从plist加载数据,但保存的只是课程名称以及成绩和总权重的默认值(-1和0)。因此,实际上,它们被保存,就好像首先对它们调用initWithName一样

这是我第一次真正深入研究一个相当高级的iOS应用程序,所以作为一个新手,我可能遗漏了一些重要信息。如果是这样,请让我知道,我会更新问题

谢谢! -HT


p、 如果相关,我已将info.plist中的donotrunningbackground设置为true。

您正在尝试在初始化对象之前设置对象中的值。然后初始化将重置您的值

-(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;
}
在Cocoa中,init方法可能会返回不同的对象,然后是已分配的对象。因此,您必须将self分配给super的init

因此,您的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

您试图在对象初始化之前设置其值。然后初始化将重置您的值

-(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;
}
在Cocoa中,init方法可能会返回不同的对象,然后是已分配的对象。因此,您必须将self分配给super的init

因此,您的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*)编码器

Wow。我照你说的做了,然后在我的另外两门课上得到了一个不响应选择器错误的成绩:类别(表示课程的“块”,如作业或考试)和项目(表示实际的评分项目)。我让这2个也实现了NSCoding,很低,看,它工作了!这似乎解决了我的两个问题,您还指出了我的编码风格(如何编写init)中的一个可怕缺陷,对此我万分感激。无论如何,非常感谢!哇!我照你说的做了,然后在我的另外两门课上得到了一个不响应选择器错误的成绩:类别(表示课程的“块”,如作业或考试)和项目(表示实际的评分项目)。我让这2个也实现了NSCoding,很低,看,它工作了!这似乎解决了我的两个问题,您还指出了我的编码风格(如何编写init)中的一个可怕缺陷,对此我万分感激。无论如何,非常感谢!