记录今天遇到的问题,一个低级错误。。

今天在objc中国看了一篇文章,是关于如何让控制器代码更少的。文章地址

文章上介绍说,如果你的控制器有很多数据源方法,那么你可以把数据源方法的代码移植到一个单独的类中去,然后用 Block 来设置Cell 也可以用Delegate 。

于是我就按照上面的方法抽离了代码。

代码如下:

#import 

typedef void (^TableViewDataSourceBlock)(UITableViewCell *cell,id item);

@interface JKArrayDataSource : NSObject 

@property (nonatomic,strong) NSArray *items;

@property (nonatomic,copy) TableViewDataSourceBlock block;

-(instancetype)initArrayDataSourceWith:(NSArray *)anArrays Block:(TableViewDataSourceBlock)block;

@end

#import "JKArrayDataSource.h"

@implementation JKArrayDataSource

-(instancetype)initArrayDataSourceWith:(NSArray *)anArrays Block:(TableViewDataSourceBlock)block
{
    self = [super init];
    if (self) {
        self.items = anArrays;
        self.block = [block copy];
    }
    
    return self;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.items.count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    
    id item = self.items[indexPath.row];
    
    self.block(cell,item);
    
    return cell;
}

@end

控制器代码如下:

#import "JKViewController.h"
#import "JKArrayDataSource.h"

@interface JKViewController ()

@end

@implementation JKViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    NSArray *items = @[@"one",@"two",@"three"];
    
    JKArrayDataSource *dataSource = [[JKArrayDataSource alloc] initArrayDataSourceWith:items Block:^(UITableViewCell *cell, id item) {
        cell.textLabel.text = item;
    }];
    
    _tableView.dataSource = dataSource;
    _tableView.delegate = self;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"%ld",(long)indexPath.row);
}


@end

看上去很和谐,但是一运行很荣幸的出错了。。。

Xcode上也没显示明显错误,就显示一句 EXE_BAD_ACCESS , 于是我忽然想到,UITableView 的 delegate 是弱引用的,它不会为计数器 +1 ,一旦某个对象被销毁,该实例的引用计数就会 -1 ,也就变成 0 ,而 delegate 就会变成 nil ,这时候该实例就会被ARC机制销毁,这种设计是为了防止循环引用导致内存泄露。

那么这时UITableView要去问它的代理对象索取数据的时候就发现它的代理对象没了,那么就出错了。。

这是一个非常基础的小问题,记录下来是为了让以后重视这类问题。

只要把代码改成这样就没问题了

@interface JKViewController ()

@property (nonatomic,strong) JKArrayDataSource *dataSource;

@end

@implementation JKViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    NSArray *items = @[@"one",@"two",@"three"];
    
    _dataSource = [[JKArrayDataSource alloc] initArrayDataSourceWith:items Block:^(UITableViewCell *cell, id item) {
        cell.textLabel.text = item;
    }];
    
    _tableView.dataSource = _dataSource;
    _tableView.delegate = self;
}


你可能感兴趣的:(IOS开发)