我经常遇到这样的设计选择并且有点挣扎;我正在寻找其他一些观点。
我经常想要保留列表,或者传递基本上只是值集的状态块。值往往是原始类型:浮点数,NSTimeIntervals,CGPoints等。
我的第一个倾向通常是为这些属性集创建C结构,例如
typedef struct _STATE {
float foo;
NSTimeInterval elapsed;
CGPoint point;
} STATE;
等
但是C结构与本机Cocoa集合类(NSArray
,NSSet
,NSDictionary
)不能很好地结合使用,并且使用过多的结构来跟踪大量的状态感觉就像它运行我的Cocoa友好代码的其余部分 - 我最终拥有并直接管理结构数组,并在消息中传递结构指针等。
另一方面,由于原始性能不一定是关键,我可以将这些值编码为NSDictionary,将它们全部包含在NSValue
或NSNumber
中,但结果语法几乎不简洁,并且有点脆弱,在运行时要求插入和查找的类型和名称正确性:
[stateDict setObject:[NSNumber numberWithFloat:foo] forKey:@"bar"];
...
float something = [[stateDict objectForKey:@"bar"] floatValue];
和某些类型,如NSTimeInterval,只能与一些(可论证的)hackery一起使用(在这种情况下类型转换为double)。
最后,我可以使用私有成员数据创建仅限数据的容器对象,并且只创建getter / setter。 (这些在Java中被称为“bean”。)这些比字典更容易访问,更多Cocoa而不是结构,但对我来说感觉有点过分,特别是如果我只需要它们作为用于状态管理的“内部类”单个对象类型的内部。
如何,伟大的Cocoa编程公众,这样做?
答案 0 :(得分:14)
根据具体情况,我使用NSDictionary类运行任意数据,或者我创建容器类(Objective C中的@ property / synthesize标签使这非常简单)。通过使用ObjC作为头文件:
@interface StateObject : NSObject {
NSNumber *foo;
NSTimeInterval *elapsed;
CGPoint point;
}
@property (retain) NSNumber *foo;
@property (retain) NSTimeInterval *elapsed;
@property (copy) CGPoint point;
@end
然后可以在.m文件中使用@synthesize <variable>
来自动创建setter / getter。然后,虽然匿名NSNumbers仍然是ornery,你可以这样做:
myStateObject.foo = [NSNumber numberWithFloat:7.0];
这应该可以消除大部分的痛苦,让你使用Cocoa集合类来更好地改变数据。
答案 1 :(得分:2)
不一定认可这种方法是“最好的”,但是你的提议之间存在中间立场:创建C结构来保存信息,然后在需要将它们放入NSValue
对象时将结构包装起来Cocoa数据结构。你可以看到UIKit在某些情况下使用CGPoint
这样的结构通知(我确信AppKit也可以这样做)。
有关详情,请参阅Number and Value Programming Topics for Cocoa中的“使用值”。