2014-09-11 1 views
0

코드를 더 재사용 할 수 있도록 UITableview의 데이터 소스를 분리하는 방법에 대한 온라인 예제를 발견했습니다. 그러나이 코드에서는 델리게이트 대신 블록을 사용하여 셀을 업데이트합니다. 지금까지는 프로젝트에서 대리인을 사용하여 일관성을 유지하면서이 방법을 그대로 유지하여 누군가가 더 나은 블록을 설명하고 아래 예제 코드를 리팩터링하여 블록 대신 delegates을 포함시킬 수있게 도와 주시면 감사하겠습니다. 사용중인 예제는 http://www.objc.io/issue-1/lighter-view-controllers.html입니다.델리게이트 대 블록 이해. (블록 대신 위임을 사용하는 리팩토링 코드)

// 
// ArrayDataSource.h 
// objc.io example project (issue #1) 
// 

#import <Foundation/Foundation.h> 


typedef void (^TableViewCellConfigureBlock)(id cell, id item); 


@interface ArrayDataSource : NSObject <UITableViewDataSource> 

- (id)initWithItems:(NSArray *)anItems 
cellIdentifier:(NSString *)aCellIdentifier 
configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock; 

- (id)itemAtIndexPath:(NSIndexPath *)indexPath; 

@end 
하는 .m

// 
// ArrayDataSource.h 
// objc.io example project (issue #1) 
// 

#import "ArrayDataSource.h" 


@interface ArrayDataSource() 

@property (nonatomic, strong) NSArray *items; 
@property (nonatomic, copy) NSString *cellIdentifier; 
@property (nonatomic, copy) TableViewCellConfigureBlock configureCellBlock; 

@end 


@implementation ArrayDataSource 

- (id)init 
{ 
    return nil; 
} 

- (id)initWithItems:(NSArray *)anItems 
cellIdentifier:(NSString *)aCellIdentifier 
configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock 
{ 
    self = [super init]; 
    if (self) { 
     self.items = anItems; 
     self.cellIdentifier = aCellIdentifier; 
     self.configureCellBlock = [aConfigureCellBlock copy]; 
    } 
    return self; 
} 

- (id)itemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    return self.items[(NSUInteger) indexPath.row]; 
} 


#pragma mark UITableViewDataSource 

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier 
                 forIndexPath:indexPath]; 
    id item = [self itemAtIndexPath:indexPath]; 
    self.configureCellBlock(cell, item); 
    return cell; 
} 

@end 

그리고 UIViewController에서의 사용은 될 것이다;

void (^configureCell)(PhotoCell*, Photo*) = ^(PhotoCell* cell, Photo* photo) { 
cell.label.text = photo.name; 
}; 
photosArrayDataSource = [[ArrayDataSource alloc] initWithItems:photos 
              cellIdentifier:PhotoCellIdentifier 
             configureCellBlock:configureCell]; 
self.tableView.dataSource = photosArrayDataSource; 

나는 매일 새로운 것을 배우려고 노력하며 누군가 도움을 주면 좋을 것입니다. 언젠가 한 번에 개발자로서 개선하기를 희망합니다 :

데이터 소스의 분리를 이해하지만 위임자 대신 블록을 사용하는 것이 나에게 새롭습니다.

답변

2

실제로 예제에서 ArrayDataSource 클래스는 모든 UITableView의 데이터 소스에 사용되는 "일반"클래스입니다.

ArrayDataSource (ArrayDataSource.m)의 구현을 자세히 살펴보면 UITableViewDatasource (numberOfRowsInSection:, cellForRowAtIndexPath: ...)의 고전적인 메서드를 호출하는 것을 볼 수 있습니다. 그러나 일반 클래스가 특정 indexPath에 대한 셀의 내용을 구성해야 할 경우 id item을 사용하여 수행 할 작업을 알지 못하므로 특정 블록 (self.configureCellBlock(cell, item);)을 호출하여 제네릭 클래스에서이 동작을 외부화합니다.

블록 개념은 함수 포인터와 비슷합니다. 일반적인 ArrayDatasource 클래스에만 말하고 있습니다. 셀의 내용을 줄에 배열 할 때 호출 할 함수는 self.configureCellBlock(cell, item);입니다. 귀하의 경우 셀에 사진의 이름 (cell.label.text = photo.name;)이 표시됩니다. (... 등등 heightForRowAtIndexPath:을 구현하기 추천하고)

그래서,이 경우, 당신은 여전히 ​​ArrayDatasource 클래스의 jQuery과의 데이터 소스의 개념을 사용하고, 당신은 ArrayDataSource.m에 기본 UITableViewDatasource에 대한 귀하의 모든 요구를 넣을 수 있습니다 , 귀하의 모든 tableView의 데이터 소스에 대한 복사 붙여 넣기를 방지하기 위해 (애플 리케이션의 경우 많은 UITableView있다). 여기 블록의 목적은 데이터 소스 개념을 대체하는 것이 아니라 일반적인 클래스에 무엇을 할지를 알리는 더 편리한 방법입니다 ...

나는 분명하지만 그러한 개념을 설명하는 것이 쉽지는 않을 것입니다. ! :)

+0

대단히 감사합니다. 이것은 매우 도움이됩니다. :) – DevC