简体   繁体   English

NSUserDefaults、NSCoder、自定义 Class - iPhone 应用问题

[英]NSUserDefaults, NSCoder, Custom Class - iPhone app question

I'm having an error and I guess I'm doing something wrong in the following process.我有一个错误,我想我在下面的过程中做错了什么。 Firstly, I have a class Contacts:首先,我有一个 class 联系人:

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

And in Contact's implementation, I have:在 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;
}

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.但是,在 NSLog(@"got contact %@",c); 行上,我的程序停止运行。 It prints everything fine, and even prints that the object's class is "Contact".它打印一切都很好,甚至打印出对象的 class 是“联系人”。 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.看起来可能有错误,但在左侧,我只在左侧错误区域的 XCode 4 中的“按线程”选项下看到问号。

So what am I doing wrong?那么我做错了什么?

在此处输入图像描述

First, your init should look like this:首先,您的 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;
}

In encodeWithCoder you encode first twice, you probably wanted phoneNumber in the second one.encodeWithCoder ,您first编码两次,您可能希望在第二次中使用phoneNumber

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).也许我错过了您创建新Contact对象的位置,但您可能需要一个标准的init方法来最初创建联系人(我相信initWithCoder仅在您从数据或文件解码时初始化)。 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.确保你有一个释放所有 class 成员的dealloc

Hm.嗯。 Turned out if I added a retain on the decode method, everything worked.事实证明,如果我在解码方法上添加了保留,一切正常。 I mean, retain all the objects.我的意思是,保留所有对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM