将KVO添加到UITableViewCell

Z S*_*Z S 12 core-data objective-c key-value-observing uitableview

我有一个自定义的UITableViewCell,它显示了Person对象的各种属性(由Core Data支持)......一些标签,图像等.我目前强制整个tableview在任何属性更改时重新加载,这显然效率不高.我知道KVO,我应该能够在单元格中的标签中添加一个监听器,以监听Person属性的变化.但我不确定如何实现它,也找不到任何例子.

这是我在UITableView的cellForRowAtIndexPath中通常做的事情:

    - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath
    {
        static NSString *simple = @"CustomCellId";

        CustomCell *cell = (CustomCell *) [tableView dequeueReusableCellWithIdentifier:simple];

        if (cell == nil)
        {
            NSArray *nib =  [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];

            for (id findCell in nib )
            {
                if ( [findCell isKindOfClass: [CustomCell class]])
                {
                    cell = findCell;
                }    
            }
         }
         Person *managedObject = [self.someArray objectAtIndex: indexPath.row];
         cell.namelabel.text =  managedObject.displayName;
         return cell;
}
Run Code Online (Sandbox Code Playgroud)

细胞连接在IB中.我想检测displayName更改的时间,并只更新名称标签.谢谢

Rob*_*arl 18

上面的答案非常适合静态细胞.使用KVO UITableViewCell仍可用于单元重用.在单元格即将出现时添加所需的观察者,并在不再显示单元格时将其删除.唯一的诀窍是Apple似乎与发送didEndDisplayingCell:不一致,因此需要在iOS 6.1上的两个地方删除观察者

@implementation MyTableViewCell

@property MyTableViewController * __weak parentTVC;

- (UITableViewCell *)tableView:(UITableView *)tableView 
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ((MyTableViewCell *)cell).parentTVC = self;
    // Don't add observers, or the app may crash later when cells are recycled
}


- (void)tableView:(UITableView *)tableView 
  willDisplayCell:(HKTimelineCell *)cell 
forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Add observers
}

- (void)tableView:(UITableView *)tableView 
didEndDisplayingCell:(UITableViewCell *)cell 
forRowAtIndexPath:(NSIndexPath *)indexPath
{
    [self removeMyKVOObservers];
}

- (void)viewWillDisappear:(BOOL)animated
{
    for (MyTableViewCell *cell in self.visibleCells) {
        // note! didEndDisplayingCell: isn't sent when the entire controller is going away! 
        [self removeMyKVOObservers];
    }
}
Run Code Online (Sandbox Code Playgroud)

如果未清理观察者,则会发生以下情况.观察者可能会尝试通知该内存位置的任何对象,甚至可能不存在.

<NSKeyValueObservationInfo 0x1d6e4860> ( <NSKeyValueObservance 0x1d4ea9f0: Observer: 0x1d6c9540, Key path: someKeyPath, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, Property: 0x1c5c7e60> <NSKeyValueObservance 0x1d1bff10: Observer: 0x1d6c9540, Key path: someOtherKeyPath, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, Property: 0x1c588290>)


Bor*_*aut 5

对于背景,您可能希望阅读键值观察和键值编码指南(如果尚未阅读).然后查看NSKeyValueObserving类别方法.

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Protocols/NSKeyValueObserving_Protocol/Reference/Reference.html

简而言之,您需要仔细管理向观察对象的观察对象列表添加和删除观察对象(原谅该语句的看似冗余).您不希望观察者仍然注册,或者您收到投诉和其他可能的问题.

也就是说,您使用-addObserver:keyPath:options:context添加对象作为观察者.Context应该是静态声明的字符串.options参数控制您在观察方法中获得的数据(见下文).keyPath是从观察对象到被观察属性的属性名称的路径(这可以遍历多个对象,并且将在中间对象更改时更新,而不仅仅在叶属性更改时更新).

在您的情况下,您可以观察标签,并使用textkeyPath或单元格,并使用nameLabel.text密钥路径.如果表视图类的设计不同,您可能会观察整个单元格数组,但UITableView上没有这样的属性.观察单元格的问题是表视图可能随时删除它(如果您的设计在可变长度列表中使用多个单元用于相同的目的).如果你知道你的细胞是静止的,你可以毫无顾虑地观察它们.

一旦注册了观察者,该观察者必须实现 -observeValueForKeyPath:ofObject:change:context:,确认上下文匹配(只需将指针值与静态字符串的地址进行比较;否则,调用super的实现),然后查看更改字典中的所需数据(或者只是直接询问对象)并使用它来根据需要更新模型.

在示例代码中有许多KVO示例,包括Apple的开发人员站点,以及作为Malcolm Crawford(mmalc)网站上的绑定示例的一部分,但大多数是针对Mac OS X,而不是iOS.