NSUserDefaults、NSCoder、自定义类 - iPhone 应用程序问题

发布于 2024-11-23 19:43:59 字数 2676 浏览 2 评论 0原文

我遇到了错误,我想我在以下过程中做错了什么。首先,我有一个类 Contacts:

@interface Contact : NSObject<NSCoding> {
    @private
    ABRecordRef ref;
    NSString *first;
    NSString *last;
    bool selected;
    NSString *phoneNumber;
}

在 Contact 的实现中,我有:

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:first forKey:@"First"];
    [encoder encodeObject:last forKey:@"Last"];
    [encoder encodeObject:[NSNumber numberWithInteger: ABRecordGetRecordID(ref)] forKey:@"Ref"  ];
    [encoder encodeObject:first forKey:@"PhoneNumber"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    self = [[Contact alloc] init];
    first = [decoder decodeObjectForKey:@"First"];
    last = [decoder decodeObjectForKey:@"Last"];
    ABAddressBookRef addressBook = ABAddressBookCreate();
    NSNumber *num = [decoder decodeObjectForKey:@"Ref"];
    ref = ABAddressBookGetPersonWithRecordID(addressBook,(ABRecordID)num);
    phoneNumber = [decoder decodeObjectForKey:@"PhoneNumber"];

    return self;
}

当我在应用程序中创建所谓的“组”时,我执行以下操作:

+ (void)addGroupWithName:(NSString *)s contacts:(NSMutableArray *)arr {
    NSLog(@"added group name with name %@",s);
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr];
    [defaults setObject:data forKey:s];
    [defaults synchronize];
    //[UserData setDefaultWithName:s object:arr];
}

根据我所做的一些打印语句,它似乎工作正常。

然后,当应用程序启动时,我尝试打印我存储的那些对象:

+ (void)printGroups {
    NSMutableArray *arr = [UserData getGroupNames];
    NSLog(@"group names are %@",arr);
    for(int i = 0; i < [arr count]; i++) {
        NSString *name = [arr objectAtIndex:i];
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        NSData *data = [defaults objectForKey:name];
        NSArray *a = [NSKeyedUnarchiver unarchiveObjectWithData:data];
        NSLog(@"name = %@",name);
        NSLog(@"array count is %i",[a count]);
        for(int i = 0; i < [a count]; i++) {
            NSLog(@"on index %i",i);
            Contact *c = [a objectAtIndex:i];
            NSLog(@"got contact");
            if(c == nil)
                NSLog(@"it's nil!");    

            NSLog(@"class is %@", NSStringFromClass([c class]));
            NSLog(@"got contact %@",c);
        }
        NSLog(@"array = %@",a);
    }
}

但是,在 NSLog(@"got contact %@",c); 行上,我的程序停止运行。它打印一切正常,甚至打印该对象的类是“Contact”。但随后它就停止了。看起来可能有错误,但在左侧,我只在左侧错误区域的 XCode 4 中的“按线程”选项下看到问号。

那么我做错了什么?

在此处输入图像描述

I'm having an error and I guess I'm doing something wrong in the following process. Firstly, I have a class Contacts:

@interface Contact : NSObject<NSCoding> {
    @private
    ABRecordRef ref;
    NSString *first;
    NSString *last;
    bool selected;
    NSString *phoneNumber;
}

And in Contact's implementation, I have:

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:first forKey:@"First"];
    [encoder encodeObject:last forKey:@"Last"];
    [encoder encodeObject:[NSNumber numberWithInteger: ABRecordGetRecordID(ref)] forKey:@"Ref"  ];
    [encoder encodeObject:first forKey:@"PhoneNumber"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    self = [[Contact alloc] init];
    first = [decoder decodeObjectForKey:@"First"];
    last = [decoder decodeObjectForKey:@"Last"];
    ABAddressBookRef addressBook = ABAddressBookCreate();
    NSNumber *num = [decoder decodeObjectForKey:@"Ref"];
    ref = ABAddressBookGetPersonWithRecordID(addressBook,(ABRecordID)num);
    phoneNumber = [decoder decodeObjectForKey:@"PhoneNumber"];

    return self;
}

And when I create what I call a "group" in my app, I do the following:

+ (void)addGroupWithName:(NSString *)s contacts:(NSMutableArray *)arr {
    NSLog(@"added group name with name %@",s);
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr];
    [defaults setObject:data forKey:s];
    [defaults synchronize];
    //[UserData setDefaultWithName:s object:arr];
}

which, according to some print statements I make, seems to work fine.

Then, when the app launches, I try to print those objects I stored:

+ (void)printGroups {
    NSMutableArray *arr = [UserData getGroupNames];
    NSLog(@"group names are %@",arr);
    for(int i = 0; i < [arr count]; i++) {
        NSString *name = [arr objectAtIndex:i];
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        NSData *data = [defaults objectForKey:name];
        NSArray *a = [NSKeyedUnarchiver unarchiveObjectWithData:data];
        NSLog(@"name = %@",name);
        NSLog(@"array count is %i",[a count]);
        for(int i = 0; i < [a count]; i++) {
            NSLog(@"on index %i",i);
            Contact *c = [a objectAtIndex:i];
            NSLog(@"got contact");
            if(c == nil)
                NSLog(@"it's nil!");    

            NSLog(@"class is %@", NSStringFromClass([c class]));
            NSLog(@"got contact %@",c);
        }
        NSLog(@"array = %@",a);
    }
}

However, on the line NSLog(@"got contact %@",c);, my program stops running. It prints everything fine, and even prints that the object's class is "Contact". But then it stops. It looks like maybe there is an error but on the left hand side I just see question marks under the "By Thread" option in XCode 4 in the error area on the left.

So what am I doing wrong?

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

城歌 2024-11-30 19:43:59

首先,您的 init 应该如下所示:

- (id)initWithCoder:(NSCoder *)decoder 
{
    if(self = [super init])
    {
        first = [[decoder decodeObjectForKey:@"First"] retain];
        last = [[decoder decodeObjectForKey:@"Last"] retain];
        ABAddressBookRef addressBook = ABAddressBookCreate();
        NSNumber *num = [decoder decodeObjectForKey:@"Ref"];
        ref = ABAddressBookGetPersonWithRecordID(addressBook,(ABRecordID)num);
        phoneNumber = [[decoder decodeObjectForKey:@"PhoneNumber"] retain];
    }

    return self;
}

encodeWithCoder 中,您将 first 编码两次,您可能想要在第二个中使用 phoneNumber

也许我错过了您创建新的 Contact 对象的位置,但您可能需要一个标准的 init 方法来最初创建联系人(initWithCoder > 我相信,仅当您从数据或文件解码时才初始化)。这可能看起来像这样:

- (id)initWithFirst:(NSString *)firstIn last:(NSString *)lastIn phone:(NSString *)phoneIn 
{
    if(self = [super init])
    {
        first = [firstIn retain];
        last = [lastIn retain]; 
        phoneNumber = [phoneIn retain];
        selected = NO;
        ref = //however you generate a record reference
    }

    return self;
}

我不确定是否还有其他问题,但尝试更改这两件事,看看是否会产生影响。确保您有一个可以释放所有类成员的dealloc

First, your init should look like this:

- (id)initWithCoder:(NSCoder *)decoder 
{
    if(self = [super init])
    {
        first = [[decoder decodeObjectForKey:@"First"] retain];
        last = [[decoder decodeObjectForKey:@"Last"] retain];
        ABAddressBookRef addressBook = ABAddressBookCreate();
        NSNumber *num = [decoder decodeObjectForKey:@"Ref"];
        ref = ABAddressBookGetPersonWithRecordID(addressBook,(ABRecordID)num);
        phoneNumber = [[decoder decodeObjectForKey:@"PhoneNumber"] retain];
    }

    return self;
}

In encodeWithCoder you encode first twice, you probably wanted phoneNumber in the second one.

Maybe I'm missing where you're creating new Contact objects, but you will probably want a standard init method to create the contact initially (initWithCoder only initializes when you're decoding from data or a file, I believe). This would probably want to look something like:

- (id)initWithFirst:(NSString *)firstIn last:(NSString *)lastIn phone:(NSString *)phoneIn 
{
    if(self = [super init])
    {
        first = [firstIn retain];
        last = [lastIn retain]; 
        phoneNumber = [phoneIn retain];
        selected = NO;
        ref = //however you generate a record reference
    }

    return self;
}

I'm not sure if anything else is wrong, but try changing these two things and see if it makes a difference. Make sure you have a dealloc where you release all of your class members.

知你几分 2024-11-30 19:43:59

嗯。事实证明,如果我在解码方法上添加保留,一切都会正常。我的意思是,保留所有对象。

Hm. Turned out if I added a retain on the decode method, everything worked. I mean, retain all the objects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文