问题:在监听可变数组的count属性时报错,网络上少有给出合适的解决方案的,即使给出了问题的关键点,也没有源码参考
目标:实现可变数组的监听,并给出参考代码
使用方法:git status 可以查看到构建这个源码的每个步骤,可以回退到之前版本查看
程序说明:
- 主视图为空列表,点击右上方’+’号,添加一行,点击左上方 ’undo’ 按钮删除最后一行。
-(IBAction)btnAddClick:(id)sender { AppDelegate* delegate=[UIApplication sharedApplication].delegate; // [delegate.dataTableView addObject:[NSString stringWithFormat:@"%lu",[delegate.dataTableView count]]]; [delegate addDataTableViewObject:[NSString stringWithFormat:@"%lu",[delegate.dataTableView count]]]; // [self.tableView reloadData]; } -(IBAction)btnRemoveClick:(id)sender { AppDelegate* delegate=[UIApplication sharedApplication].delegate; // [delegate.dataTableView removeLastObject]; if ([delegate countOfDataTableView]==0) { return; } [delegate removeDataTableViewObject:[delegate objectInDataTableViewAtIndex:[delegate countOfDataTableView]-1]]; // [self.tableView reloadData]; }
- 主视图列表的数据源为Appdelegate的属性 @property (strong, nonatomic) NSMutableArray *dataTableView;
#pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { //#warning Potentially incomplete method implementation. // Return the number of sections. return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. return [[self aryData] count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellId" forIndexPath:indexPath]; cell.textLabel.text=[NSString stringWithFormat:@"%@",[[self aryData] objectAtIndex:[indexPath row]]]; // Configure the cell... return cell; } -(NSMutableArray*)aryData { AppDelegate* delegate=[UIApplication sharedApplication].delegate; return [delegate dataTableView]; }
- 主视图控制器监听数据源dataTableView条目数量变化,当其发生变化时更新tableview
-(void)InitKVO { AppDelegate* delegate=[UIApplication sharedApplication].delegate; // [delegate.dataTableView addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew context:NULL]; // [delegate addObserver:self forKeyPath:@"dataTableView.count" options:NSKeyValueObservingOptionNew context:NULL]; [delegate addObserver:self forKeyPath:@"countOfDataTableView" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil]; } -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { NSLog(@"keypath:::%@",keyPath); NSLog(@"object:::%@",NSStringFromClass([object class])); NSLog(@"change:::%@",change); if([keyPath isEqualToString:@"countOfDataTableView"]) { [self.tableView reloadData]; } // if([super respondsToSelector:@selector(observeValueForKeyPath:ofObject:change:context:)]) // { // [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; // } }
- AppDelegate实现KVC方法,并符合KVO规范
#pragma mark--key-value coding -(NSMutableArray*)dataTableView { return _dataTableView; } -(NSInteger)countOfDataTableView { return [self.dataTableView count]; } -(id)objectInDataTableViewAtIndex:(NSUInteger)index { return [self.dataTableView objectAtIndex:index]; } -(void)addDataTableViewObject:(id)object { [self willChangeValueForKey:@"countOfDataTableView"]; [self.dataTableView addObject:object]; [self didChangeValueForKey:@"countOfDataTableView"]; } -(void)removeDataTableViewObject:(id)object { [self willChangeValueForKey:@"countOfDataTableView"]; [self.dataTableView removeObject:object]; [self didChangeValueForKey:@"countOfDataTableView"]; } -(void)insertDataTableView:(NSArray *)array atIndexes:(NSIndexSet *)indexes { // [self will] [self.dataTableView insertObjects:array atIndexes:indexes]; } #pragma mark--manual change notification + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey { BOOL automatic = NO; if ([theKey isEqualToString:@"countOfDataTableView"]) { automatic = NO; } else { automatic = [super automaticallyNotifiesObserversForKey:theKey]; } return automatic; }
- 总结:
-
- 想理解key-value observing 首先要理解 key-value coding
-