【问题标题】:how do I serialize\deserialize NSLocale correctly?如何正确序列化\反序列化 NSLocale?
【发布时间】:2013-06-23 18:23:48
【问题描述】:

我正在尝试为我的一门课程实施协议<NSCoding>。 我在对此类的一个属性进行序列化\反序列化时遇到了一个问题。属性类型:NSLocale

这是我为了解NSLocale 的行为而编写的(猕猴桃)测试:

   NSLocale *locale = [NSLocale currentLocale];
   NSData *data = [NSKeyedArchiver archivedDataWithRootObject:locale];
   NSLocale *locale2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];

   NSLog(@"1) %@", [locale localeIdentifier]); //=> "en_US"
   NSLog(@"2) %@", [locale2 localeIdentifier]); //=> "en_US"
   [[locale should] equal:locale2]; //=>fail

   [[[NSLocale currentLocale] should] equal:[NSLocale currentLocale]]; //=> pass

测试失败。你们知道为什么吗?

【问题讨论】:

  • 我认为should equal== 的指针级别等价。您怎么能期望来自不同来源的两个对象具有相同的地址?
  • 对不起,shouldequal: 方法是什么?
  • 我猜他们来自 Kiwi 框架
  • @CodaFi 是什么让你这么认为?我认为equal 在对象上调用isEqual,而beIdenticalTo 比较指针
  • 是的。我确实使用了 kiwi,我认为 equal 调用 [object isEqual:object2]。我会验证并编辑问题

标签: ios objective-c foundation kiwi


【解决方案1】:

注意

根据下面的 CodaFi cmets,这似乎是NSLocale 的实施问题。

NSCoder 产生一个NSCFLocale 实例,而直接分配返回一个NSLocale

由于NSLocaleNSCFLocale 执行不同的相等性检查(前者似乎使用CFEqual(),后者使用isEqualToString:),这导致下面暴露的不一致。


原帖

这不完全是一个答案,因为我不知道发生了什么,但我无法将其放在评论中。这是一些测试的奇怪结果

如果您“手动”声明NSLocale 的实例,一切都会按预期工作

NSLocale * l1 = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:l1];
NSLocale *l2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSLog(@"%i", [l1 isEqual:l2]); // => 1, aka YES

但如果你将l1 声明为[NSLocale currentLocale],就会出错

NSLocale * l1 = [NSLocale currentLocale];    
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:l1];
NSLocale *l2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSLog(@"%i", [l1 isEqual:l2]); // => 0, aka NO

坦率地说,我和你一样困惑。


额外信息:

这是另一个测试的结果

NSLocale * l1 = [NSLocale currentLocale];
NSLocale * l3 = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:l1];
NSData *data1 = [NSKeyedArchiver archivedDataWithRootObject:l3];
NSLocale *l2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSLocale *l4 = [NSKeyedUnarchiver unarchiveObjectWithData:data1];

NSLog(@"\n%p\n%p", l1, l2);    // => 0x9849da0
NSLog(@"\n%p\n%p", l3, l4);    // => 0x9866770
NSLog(@"%i", [l1 isEqual:l2]); // => 0x9866770
NSLog(@"%i", [l3 isEqual:l4]); // => 0x9866770

令人惊讶的是,解压l1 后返回的实例与l3 相同!

【讨论】:

  • 从我在 CoreFoundation 中的 ASM 中可以看出,一些可怜的 Apple 工程师决定使用 CFEqual() 而不是 isEqualToString: 进行字符串等价。归档雷达。
  • 在哪个字符串上? localeIdentifier?
  • 问题是 NSLocale 和 NSCFLocale 对等价有两种不同的看法。 NSCoder 恰好使您成为 NSCFLocale,而直接分配使您成为 NSLocale。
  • 我明白了。您可以发布雷达的链接,以便其他人在阅读此问题时参考它
猜你喜欢
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 2011-04-06
  • 2015-01-04
  • 2021-01-22
  • 1970-01-01
  • 2020-08-24
  • 1970-01-01
相关资源
最近更新 更多