将数据存储到 NSUserDefaults

发布于 2024-11-19 23:34:03 字数 220 浏览 3 评论 0原文

在我的 iPhone 应用程序中,我有一个名为 Contact 的类,它由一个 ABRecordRef 组成,用作对特定联系人的引用。

我需要将这些联系人组存储在 NSUserDefaults 中,但由于 Contact 是一个自定义类,所以事情并没有那么顺利。

在这种情况下有什么想法吗?

In my iPhone app, I have a class called Contact which consists of an ABRecordRef to serve as a reference to a particular contact.

I need to store groups of these contacts in NSUserDefaults, but things aren't working out so well since Contact is a custom class.

Any ideas of what to do in this case?

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

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

发布评论

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

评论(4

灯角 2024-11-26 23:34:03

您不能将 NSUserDefaults 用于自定义类。从文档中:

NSUserDefaults 类提供了方便的访问方法
常见类型,例如浮点数、双精度数、整数、布尔值和 URL。一个
默认对象必须是属性列表,即(或
对于集合实例的组合):NSDataNSString
NSNumberNSDateNSArrayNSDictionary。如果你想存储任何
其他类型的对象,您通常应该将其存档以创建
NSData 的实例。

尝试使用 NSData。例如,要将自定义对象加载到数组中,您可以执行以下操作:

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];
}

要归档数据,请使用:

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

只要您的自定义对象符合 NSCoding 协议,这一切都可以工作:

- (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 是一种不透明的 C 类型,因此它不是 Objective-C 意义上的对象。这意味着您无法扩展它,无法在其上添加类别,也无法向其发送消息。您唯一能做的就是使用 ABRecord 作为参数来调用 ABRecord 参考中描述的函数。

您可以做两件事来保留 ABRecord 引用的信息:

  1. 通过 获取 ABRecordid >ABRecordGetRecordID()ABRecordID 定义为 int32_t,因此您可以将其转换为 NSInteger 并将其存储在您喜欢的任何位置。您稍后可以从 ABAddressBookGetPersonWithRecordID()ABAddressBookGetGroupWithRecordID() 取回记录。但是,该记录可能会被用户或其他应用程序更改甚至删除。

  2. 将记录内的所有值复制到标准 NSObject 子类,并使用上面讨论的 NSCoding 来存储它。当然,您将无法从用户对记录所做的更改或添加中受益。

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.

抠脚大汉 2024-11-26 23:34:03

好吧,Apple 的建议 是存储记录标识符、名字和姓氏。然后,您可以尝试通过标识符从地址簿中检索联系人,如果未找到记录或者该记录不是正确的人,请尝试通过名字和姓氏进行检索(因为记录标识符可能会根据您的记录来源而改变)地址簿数据)。

这可能是您想要的,也可能不是,具体取决于您存储数据的原因。但是,您可以很容易地将这三个值放入 NSDictionary 并将字典写入 NSUserDefaults

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.

玩世 2024-11-26 23:34:03

ABRecordRef 似乎是一个 const void * ,因此将其存储在 NSUserDefaults 中,您必须将其包装在 NSData 中: NSData *d = [[NSData alloc] initWithBytes:thePointer length:sizeof(ABRecordRef)];

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)];.

阳光①夏 2024-11-26 23:34:03

您可以使用转换为 vCard 表示形式实际存储它,即 CFStringRef,可以轻松用作 NSString。

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

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