【发布时间】:2009-03-19 10:34:27
【问题描述】:
我在类 loginController 的实现中创建了一个 NSMutableArray。可变数组包含一组字符串。我想将可变数组及其对象传递给我的可可项目中的其他类。传递数组的最佳方式是什么?
【问题讨论】:
标签: cocoa arrays import mutable
我在类 loginController 的实现中创建了一个 NSMutableArray。可变数组包含一组字符串。我想将可变数组及其对象传递给我的可可项目中的其他类。传递数组的最佳方式是什么?
【问题讨论】:
标签: cocoa arrays import mutable
最基本的情况是您的登录控制器只是将阵列的快照交给另一个控制器。在这种情况下,您的登录控制器将需要引用其他类的实例,并将这些实例的某些属性设置为数组。请记住使用 copy 属性声明属性,这样接收者就不会保留您的私有可变数组。
如果您希望其他控制器能够修改数组,不要让他们拥有您的可变数组——这会招致难以发现的错误。
相反,您需要在登录控制器上实现一个属性,而不是在每个其他控制器上实现一个属性。登录控制器的属性应该至少有一个 getter 和 setter(可以@synthesize),但为了提高效率,你可以实现more specific accessor methods。
一旦你有了这个属性,其他控制器应该以符合 KVO 的方式访问这个属性。如果您实现特定的访问器,他们就可以使用它们。否则,他们需要将mutableArrayValueForKey: 发送到登录控制器。当他们访问代理数组的内容时,他们真正访问了登录控制器的数组;当他们改变代理数组时,他们会依次改变登录控制器的数组。
接下来是实际的 KVO 部分。您会希望其他控制器知道其中一个控制器(或登录控制器)何时更改属性。让每个控制器(除了登录控制器)将自己添加为登录控制器属性的观察者。请记住让他们在-dealloc(或-finalize)方法中删除自己。
为了发布正确的通知,所有内容都需要使用访问器或mutableArrayValueForKey:。登录控制器本身也是如此——它应该在改变数组时使用自己的访问器,而不是直接向数组发送消息。唯一的例外是在init 和dealloc 中(因为访问器消息将是发送到half-inited/deallocked 对象的消息,如果你让访问器变得花哨*,这将是一个问题)。
顺便说一句,听起来您的控制器可能太多了。看看您是否不能将某些逻辑移到模型对象中。这极大地简化了您的代码,因为 Cocoa 旨在与模型层一起使用。繁重的控制器正在与框架作斗争,这会为您带来更多的工作。
*我所说的“花哨”是指在给定访问器方法的正常行为之外或之外做的事情。例如,insertObject:in<Foo>AtIndex: 通常只是尾调用 [<foo> insertObject:atIndex:];如果您将对象插入或存储在实例变量中的数组以外的位置,或者如果您在同一方法中执行其他操作(例如告诉视图它需要显示),那么您的访问器方法很漂亮。
【讨论】:
可能不是最佳做法的简短回答:
[otherObject giveArray:[NSArray arrayWithArray:theMutableArray]];
【讨论】:
这个问题很好,但并不完整……你只需要传递一个字符串数组还是你传递的类需要修改数组?
一般来说,简单地传递一个 NSMutableArray* 不是问题,但是你需要小心,因为你只是传递一个指针(所以如果你将它保留在某个地方,你需要知道所有者或一些其他类可能会修改数组)。 一般来说,您会希望使用 NSMutableArray 动态构建对象数组,当您需要共享它们时,制作一个非可变副本并将其传递。
NSMutableArray* myArr = [NSMutableArray arrayWithObjects:@"1",@"2",@"3",@"four",nil];
// maybe modify the array here...
NSArray* nonMut = [[myArr copy] autorelease];
[someObject doWork:nonMut];
|K
【讨论】:
我认为最适合您的情况的模式是委托。您的LoginController 不必知道它将这些数据发送到哪个类。相反,您将实现 LoginControllerDelegate 协议
@protocol LoginControllerDelegate <NSObject>
@optional
- (void)loginController:(LoginController *)loginController didReceiveLoginIDs:(NSArray *)ids;
@end
然后,在您的 LoginController 类中,您将像这样实现 delegate 属性:
@property (nonatomic, assign) id <LoginControllerDelegate> delegate;
然后,当您实际上有一些事情要与代表交流时,您会这样写:
if ([self.delegate respondsToSelector:@selector(loginController:didReceiveLoginIDs:])
[self.delegate loginController:self didReceiveLoginIDs:[NSArray arrayWithArray:loginIDs]];
应该接收登录 ID 的对象将包含 LoginControllerDelegate 协议,如下所示:
@interface SomeOtherClass : NSObject <LoginControllerDelegate>
您将在SomeOtherClass 中实现loginController:didReceiveIDs: 方法。
这样,您的LoginController 不需要对项目中的其他类有深入的了解,您只需建立一种机制,在数据可用时将该数据发送到任何对其感兴趣的对象。如果您稍后更改应接收登录 ID 的对象,则只需选择不同的委托。
【讨论】: