重构 iOS7 和 iOS8 的 UITableView 委托

Refactoring UITableView delegates for iOS7 and iOS8

作为这个问题的跟进:,我正在尝试在 iOS7 和 iOS8.[=27 中为我的 UITableView 实现单独的委托=]

因此,作为第一步,我在 MyTableViewControllerviewDidLoad 中添加了以下代码:

if ([[[UIDevice currentDevice] systemVersion] compare: @"8.0" options: NSNumericSearch] != NSOrderedAscending)
{
    [self.tableView setDelegate: [[MyTVDelegate alloc] initWithIdentifier: myTVCellIdentifier]];
}
else
{
    [self.tableView setDelegate: [[MyTVDelegate7 alloc] initWithIdentifier: myTVCellIdentifier]];
}

我正在添加一个标识符,因为我必须将它应用于多个视图控制器(或者我可能刚刚为每台电视创建了一个委托 class,我还没有弄清楚) .

我正在使用 CoreData,所以我的数据源是 NSFetchedResultsController

然后,我为 MyTVDelegate/myTVDelegate7 准备了以下内容:

#import "MyTVDelegate.h"

@implementation MyTVDelegate

- (instancetype)initWithIdentifier: (NSString *) identifier
{
    if ([super init])
    {
        self.identifier = identifier;
    }

    return self;
}

@end

@implementation MyTVDelegate7

- (CGFloat)tableView: (UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath
{
    return 44;
}

- (CGFloat)tableView: (UITableView *)tableView estimatedHeightForRowAtIndexPath: (NSIndexPath *)indexPath
{
    return UITableViewAutomaticDimension;
}

@end

如果我 运行 这个,我会在 iOS7 中收到以下 运行 时间错误:

2015-01-18 10:42:51.894  -[__NSArrayI tableView:estimatedHeightForRowAtIndexPath:]: unrecognized selector sent to instance 0x7b9dd220
2015-01-18 10:42:57.731  *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI tableView:estimatedHeightForRowAtIndexPath:]: unrecognized selector sent to instance 0x7b9dd220'

在 iOS8,没有崩溃。

实例 0x7b9dd220 是一个 NSArray。我的预感是它崩溃了,因为 indexPath 无效,因为 delegate 和 'dataSource' 现在是分开的?

我尝试将对 performFetch 的调用移动到设置委托之前或之后,但我遇到了同样的错误。

我该如何解决这个问题,例如我是否应该将所有 NSFetchedResultsController 代码也移至新委托 class?

self.tableView setDelegate: 分配一个 weak 引用;如果您没有自己对该对象的引用,它将被收集。这就是您看到崩溃的原因。系统已收集分配给您的代表的内存,然后将内存重新分配给 NSArray。您的 table 尝试调用委托的方法但不能,因为 NSArray 没有响应它们。

除了 self.tableView 属性 定义之外,定义另一个 属性:

@property (strong) id<UITableViewDelegate> myTableViewDelegate;