valueForKey:在打包结构上?
Posted
技术标签:
【中文标题】valueForKey:在打包结构上?【英文标题】:valueForKey: on packed struct? 【发布时间】:2013-01-24 10:25:35 【问题描述】:给定以下打包结构:
typedef struct __attribute__((packed))
BOOL flag;
int x;
Foo;
还有以下类:
@interface Obj : NSObject
@property (nonatomic) Foo foo;
@end
@implementation Obj
@end
尝试在具有打包结构类型的属性上调用 valueForKey:
:
Obj *obj = [Obj new];
id boo = [obj valueForKey:@"foo"];
导致valueForKey:
内部崩溃(实际上它不是在valueForKey:
内部崩溃,而是在随机位置取决于月球大小,我猜是内存损坏)。
如果我删除 __attribute__((packed))
它工作正常。
有没有可能在不崩溃的情况下获取结构的数据?是苹果的bug吗?
PS。我确实需要在运行时这样做,即我不能直接调用.foo
,我在运行时只有@"foo"
字符串。 (我实际上想要实现的是递归打印对象内容)。
【问题讨论】:
"是苹果的bug吗?"这听起来很有可能。 【参考方案1】:在您的用例中避免使用 KVO,并坚持使用方便的花花公子 <objc/runtime.h>
标头。您可以使用这种自省来重新实现 KVO 的基本部分。结构打包主要用于确保编译器没有正确对齐内部字段,因此 CPU 在执行期间不需要在硬件级别处理它。在这个时代,最好让编译器为你处理事情。
如果您真的更喜欢这种结构打包(如您所说,在网络传输场景中),我需要更多信息来确定问题所在。也许尝试将@property (nonatomic) Foo foo;
更改为@property (nonatomic) NSValue *foo;
然后将其装箱并自己拆箱?这样,异常/错误将在您的应用程序的域中。
【讨论】:
“在这个时代,最好让编译器为你处理事情。” — 不幸的是我不能;)。我正在从/向网络获取/发送这些结构,因此它们应该被精细打包以匹配网络协议...... @ivanzoid 仅仅因为这是wire 上使用的数据结构,并不意味着您需要在程序中使用该结构。您应该使用编组将内部表示转换为外部表示,特别是如果您关心 endianness(移植到大端系统时会这样做)。 @***foe 这将为我增加更多的工作:D 幸运的是我们的网络协议字节序匹配 ios 字节序(所以,小字节序)【参考方案2】:我不知道这是否可以通过属性实现,但如果可以,我认为您使用的语法不正确。
你有没有尝试过改变
id boo = [obj valueForKey:@"foo"];
阅读
Foo boo = obj.foo;
?
Foo 不是也永远不会是id
。 valueForKey:
返回 id,运行时可能会试图将 struct Foo
压缩到 NSValue
中。
如果您出于某种原因需要使用valueForKey:
,则您的访问权限需要看起来像。
Foo myFoo = FooFactory();
Object *myObj = [Object new];
[myObj setValue:@( myFoo ) forKey:@"foo"];
Foo myFooOut;
[[myObj valueForKey:@"foo"] getValue:&myFooOut];
//I bet `getValue:` is where things are barfing.
在这种情况下,如果NSValue
的机器确实无法处理打包的结构,你只需要用老式的方式编写访问器:-<key>
和 -set:`。
PS:永远不要将类命名为“Object”,实际上在某些 SDK 中存在一个 Object
NSObject
继承自。我认为这只是在您的示例中。
【讨论】:
“我敢打赌getValue:
是最糟糕的地方。” — 不,我真的什至不碰从valueForKey:
返回的对象。我已经更新了代码,现在是重现崩溃的完整代码(valueForKey:
部分可以从模板 iOS 项目中的viewDidLoad
调用)。以上是关于valueForKey:在打包结构上?的主要内容,如果未能解决你的问题,请参考以下文章
IOS开发之——objectForKey与valueForKey在NSDictionary中的差异
有没有办法在 UITest 中使用 valueForKey 和 NSPredicate?