我在类 loginController 的实现中创建了一个 NSMutableArray。可变数组包含一组字符串。我想将可变数组及其对象传递给我的可可项目中的其他类。传递数组的最佳方法是什么?
4 回答
最基本的情况是您的登录控制器只是将阵列的快照交给另一个控制器。在这种情况下,您的登录控制器将需要引用其他类的实例,并将这些实例的某些属性设置为数组。请记住使用属性声明copy
属性,以便接收者不会保留您的私有可变数组。
如果您希望其他控制器能够修改数组,请不要让他们拥有您的可变数组——这会导致难以发现的错误。
相反,您需要在登录控制器上实现一个属性,而不是在每个其他控制器上实现一个属性。登录控制器的属性应该至少有一个 getter 和 setter(你可以@synthesize
),但你可以实现更具体的访问器方法以提高效率。
拥有此属性后,其他控制器应以符合 KVO 的方式访问该属性。如果您实现特定的访问器,他们就可以使用它们。否则,他们需要发送mutableArrayValueForKey:
到登录控制器。当他们访问代理数组的内容时,他们真正访问了登录控制器的数组;当他们改变代理数组时,他们依次改变登录控制器的数组。
接下来是实际的 KVO 部分。您希望其他控制器知道其中一个(或登录控制器)何时更改属性。让每个控制器(除了登录控制器)将自己添加为登录控制器属性的观察者。请记住让他们在他们的-dealloc
(或-finalize
)方法中删除自己。
为了发布正确的通知,一切都需要使用访问器或mutableArrayValueForKey:
. 登录控制器本身也是如此——它应该在改变数组时使用自己的访问器,而不是直接向数组发送消息。唯一的例外是 ininit
和dealloc
(因为访问器消息将是发送到 half init
-ed/ dealloc
ked 对象的消息,如果你让访问器变得花哨*,这将是一个问题)。
顺便说一句,听起来你可能有太多控制器。看看您是否不能将一些逻辑移到模型对象中。这极大地简化了您的代码,因为 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>
您将loginController:didReceiveIDs:
在SomeOtherClass
.
这样,您LoginController
无需深入了解项目中的其他类,只需建立一种机制,在数据可用时将该数据发送到任何对它感兴趣的对象。如果您稍后更改应接收登录 ID 的对象,则只需选择不同的委托。