Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/98.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么NSUserDefaults无法在iOS中保存NSMutableDictionary?_Ios_Objective C_Cocoa Touch_Nsuserdefaults_Nscoding - Fatal编程技术网

为什么NSUserDefaults无法在iOS中保存NSMutableDictionary?

为什么NSUserDefaults无法在iOS中保存NSMutableDictionary?,ios,objective-c,cocoa-touch,nsuserdefaults,nscoding,Ios,Objective C,Cocoa Touch,Nsuserdefaults,Nscoding,我想在NSUserDefaults中保存一个NSMutableDictionary对象。NSMutableDictionary中的键类型是NSString,值类型是NSArray,其中包含实现NSCoding的对象列表。每个文档,NSString和NSArray都符合NSCoding 我得到这个错误: [NSUserDefaults setObject:forKey:]:尝试插入非属性值。。。。属于小说类的 您的所有键都在字典NSStrings中吗?我认为它们必须是这样才能将字典保存到属性列表中

我想在
NSUserDefaults
中保存一个
NSMutableDictionary
对象。
NSMutableDictionary
中的键类型是
NSString
,值类型是
NSArray
,其中包含实现
NSCoding
的对象列表。每个文档,
NSString
NSArray
都符合
NSCoding

我得到这个错误:

[NSUserDefaults setObject:forKey:]:尝试插入非属性值。。。。属于小说类的


您的所有键都在字典
NSString
s中吗?我认为它们必须是这样才能将字典保存到属性列表中。

如果要以用户默认值保存对象,则所有对象(递归地,一直向下)都必须是属性列表对象。遵守NSCoding在这里并不意味着什么--
NSUserDefaults
不会自动将它们编码到
NSData
,您必须自己这样做。如果“实现
NSCoding
的对象列表”指的是不是属性列表对象的对象,那么在保存为用户默认值之前,您必须对它们进行处理


仅供参考,属性列表类包括
NSDictionary
NSArray
NSString
NSDate
NSData
NSNumber
。您可以将可变子类(如
NSMutableDictionary
)写入用户首选项,但您读取的对象始终是不可变的。

我找到了一个备选方案,在保存之前,我使用
NSKeyedArchiver
对根对象(
NSArray
对象)进行编码,该编码以
NSData
结尾。然后使用UserDefaults保存
NSData

需要数据时,我读取
NSData
,并使用
NSKeyedUnarchiver
NSData
转换回对象

这有点麻烦,因为我每次都需要转换成NSData,但它可以正常工作

以下是每个请求的一个示例:

保存:

负载:

数组中的元素实现

@interface CommentItem : NSObject<NSCoding> {
    NSString *value;
}
谁有更好的解决办法


谢谢大家

没有更好的解决方案。另一种选择是只将编码的对象保存到磁盘上,但这是做同样的事情。它们都以NSData结束,当您想要返回时,它会被解码。

您是否考虑过实施
NSCoding
协议?这将允许您使用两种简单的方法在iPhone上进行编码和解码,这两种方法是通过
NSCoding
实现的。首先,您需要将
NSCoding
添加到类中

以下是一个例子:

这在.h文件中

@interface GameContent : NSObject <NSCoding>
有关更多信息,请查看NSCoder上的文档。这对于我的项目来说非常有用,在我的项目中,如果应用程序关闭,我需要在iPhone上保存应用程序的状态,然后在应用程序重新打开时将其恢复到原来的状态

关键是将协议添加到接口中,然后实现
NSCoding
中的两个方法


我希望这有帮助

最简单的答案:

NSString *key = [NSString stringWithFormat:@"%@",[dictionary valueForKey:@"Key"]];
NSDictionary
仅是plist对象,如果键是NSStrings。 因此,使用
stringWithFormat
键存储为
NSString


解决方案:

NSString *key = [NSString stringWithFormat:@"%@",[dictionary valueForKey:@"Key"]];

好处:

  • 它将添加字符串值
  • 当变量的值为
    NULL
    时,它将添加空值

  • 我还应该提到,如果键是NSString,NSDictionary只是一个属性列表对象。通常,您可以使用其他对象作为字典键,但在需要属性列表的情况下,键必须是字符串。当我想将NSURL作为对象存储在NSDictionary中并将其存储在NSUserDefaults中时,遇到了相同的问题。我不得不把它改成一个NSString,然后它就开始工作了。太棒了!在我的例子中,我尝试在用户默认设置中使用NSNumber作为NSDictionary的键。我必须将其转换为NSString。这种迟钝的行为导致没有经验的程序员将整个数据模型写成字典,而不是生成适当的数据对象?对于苹果来说,使用Obj-C有内省和照顾拳击和解体这一事实,对苹果来说是多么可怕的事情,关键是NSCORST。但是值是NSArray,它的元素是一个实现NSCoding的定制类。看来,解决方案不工作,因为用户默认只支持6类类,不考虑NSCODEL。你有一个代码示例,你可以分享,我一直试图做到这一点在邮政(537044),但没有喜悦这对我工作很好。我试图对NSDictionary对象的NSArray进行编码,其中一些键不是字符串。只需在NSArray上使用NSKeyedArchiver和Unarchiver,即可消除“尝试插入非属性值”错误。何时需要释放加载的对象?没有调用alloc,所以我假设它是自动弹性的?我们可能需要添加[defaults synchronize]来保存此处发布的解决方案可能会工作一段时间,但当您决定删除或更改该类时,您会发现自己陷入了混乱。更好的解决方案是让您的对象使用NSNUMBER、字符串等将其状态写入字典,然后将其存储。我有一个类似的问题:我的密钥是NSNumbers,这显然是plist字典密钥中不允许的。
    @interface GameContent : NSObject <NSCoding>
    
        - (id) initWithCoder: (NSCoder *)coder
        {
            if (self = [super init])
            {
                   [self setFoundHotSpots:[coder decodeObjectForKey:@"foundHotSpots"]];
            }
            return self;
        }
    
        - (void) encodeWithCoder: (NSCoder *)coder
        {
               [coder encodeObject:foundHotSpots forKey:@"foundHotSpots"];
        }
    
    NSString *key = [NSString stringWithFormat:@"%@",[dictionary valueForKey:@"Key"]];