Storing data to NSUserDefaults

倾然丶 夕夏残阳落幕 提交于 2019-11-27 04:40:13

You cannot use NSUserDefaults for a custom class. From the documentation:

The NSUserDefaults class provides convenience methods for accessing common types such as floats, doubles, integers, Booleans, and URLs. A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any other type of object, you should typically archive it to create an instance of NSData.

Try using NSData. For example, to load custom objects into an array, you can do

NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:@"savedArray"];
if (dataRepresentingSavedArray != nil)
{
        NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
        if (oldSavedArray != nil)
                objectArray = [[NSMutableArray alloc] initWithArray:oldSavedArray];
        else
                objectArray = [[NSMutableArray alloc] init];
}

To archive the data, use:

[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:objectArray] forKey:@"savedArray"];

This will all work so long as your custom object complies with the NSCoding protocol:

- (void)encodeWithCoder:(NSCoder *)coder;
{
    [coder encodeObject:label forKey:@"label"];
    [coder encodeInteger:numberID forKey:@"numberID"];
}

- (id)initWithCoder:(NSCoder *)coder;
{
    self = [[CustomObject alloc] init];
    if (self != nil)
    {
        label = [coder decodeObjectForKey:@"label"];
        numberID = [coder decodeIntegerForKey:@"numberID"];
    }   
    return self;
}

ABRecord is an opaque C type, so it's not an object in the sense of Objective-C. That means you can not extend it, you can not add a category on it, you can not message it. The only thing you can do is call functions described in ABRecord Reference with the ABRecord as a parameter.

You could do two things to be able to keep the information referenced by the ABRecord around:

  1. Get the ABRecords id by ABRecordGetRecordID(). The ABRecordID is defined as int32_t so you can cast it to an NSInteger and store it wherever you like. You can later get the record back from ABAddressBookGetPersonWithRecordID() or ABAddressBookGetGroupWithRecordID(). However, the record could be changed or even deleted by the user or another app meanwhile.

  2. Copy all values inside the record to a standard NSObject subclass and use NSCoding as discussed above to store it. You will then, of course, not benefit from changes or additions to the record the user could have made.

Well, Apple's recommendation is to store the record identifier, the first name, and the last name. You can then try retrieving the contact from the address book by the identifier and, if the record isn't found or if it's not the right person, try retrieving by first and last name (since record identifiers may change depending on the source of your address book data).

This may or may not be what you want, depending on why you're storing the data. But, you could pretty easily put those three values into an NSDictionary and write the dictionary to NSUserDefaults.

ABRecordRef appears to be a const void *, so store it in NSUserDefaults, you have to wrap it in NSData : NSData *d = [[NSData alloc] initWithBytes:thePointer length:sizeof(ABRecordRef)];.

You can store it actually using conversion to vCard representation, which is CFStringRef, that can be easily used as NSString.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!