NSMutableArray的监听问题及解决方案:[<__NSArrayM 0x4e17fd0 addObserver:forKeyPath:options:context] is not suppo

本文深入探讨了可变数组监听的关键概念,包括如何实现数据源的实时更新与视图的同步,通过引入KVO机制,实现主视图列表与数据源之间的动态交互,展示了具体的代码实现与应用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题:在监听可变数组的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 (strongnonatomicNSMutableArray *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
    •  

参考文档:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值