Mat*_*ewS 19 model-view-controller delegates key-value-observing nsnotificationcenter ios
在我的模型中,我有一个名为events的对象数组.我希望每当将新对象添加到事件时都会通知我的控制器.
我认为这样做的一个好方法是使用KVO模式在事件发生变化时收到通知(来自添加的新对象)
// AppDelegate
// events is a NSMutableArray @property/@synthesize etc...
[appDelagate addObserver:self
forKeyPath:@"events"
options:NSKeyValueObservingOptionNew
context:NULL];
Run Code Online (Sandbox Code Playgroud)
但是没有调用observeValueForKeyPath方法,我发现Arrays不符合KVO :-(
一种选择是通过为keyPath 调用willChangeValueForKey来手动触发该方法
// ViewController
[self willChangeValueForKey:@"events"];
[self.events addObject:event];
[self didChangeValueForKey:@"events"];
Run Code Online (Sandbox Code Playgroud)
但是这感觉很重,因为我应该跟踪事件数组的前后状态,以便可以从observeValueForKeyPath方法访问它.
一种方法可能是使用标准数组(而不是可变)并在每次我想要添加新对象时创建/设置新的事件实例,或者我可以创建一个单独的属性来跟踪有多少项在可变数组(我希望你能观察到@"events.count").
另一种选择是使用NSNotificationCenter.我还读了一些建议使用块的答案(但我不知道从哪里开始).
最后,我可以在我的代理中保留我的控制器实例并发送相关消息吗?
// Delegate
[myController eventsDidChange];
Run Code Online (Sandbox Code Playgroud)
从代表那里保持对控制器的引用是不是很奇怪?
我很难理解如何选择最佳使用方法,因此对性能,未来代码灵活性和最佳实践的任何建议都非常感谢!
Ryd*_*kay 18
您不应该为可变集合创建直接公共属性,以避免它们在您不知情的情况下发生变异.NSArray不是键值观察本身,但你的一对多属性 @"events"是.以下是如何观察它:
首先,为不可变集合声明一个公共属性:
@interface Model
@property (nonatomic, copy) NSArray *events;
@end
Run Code Online (Sandbox Code Playgroud)
然后在你的实现中用一个可变的ivar返回它:
@interface Model ()
{
NSMutableArray *_events;
}
@end
Run Code Online (Sandbox Code Playgroud)
并覆盖getter和setter:
@implementation Model
@synthesize events = _events;
- (NSArray *)events
{
return [_events copy];
}
- (void)setEvents:(NSArray *)events
{
if ([_events isEqualToArray:events] == NO)
{
_events = [events mutableCopy];
}
}
@end
Run Code Online (Sandbox Code Playgroud)
如果其他对象需要向模型添加事件,则可以通过调用获取可变代理对象-[Model mutableArrayValueForKey:@"events"].
NSMutableArray *events = [modelInstance mutableArrayValueForKey:@"events"];
[events addObject:newEvent];
Run Code Online (Sandbox Code Playgroud)
这将通过每次使用新集合设置属性来触发KVO通知.为了获得更好的性能和更精细的控制,请实现其余的数组访问器.
另请参阅:观察NSMutableArray以进行插入/删除.
| 归档时间: |
|
| 查看次数: |
16903 次 |
| 最近记录: |