2010-01-19 3 views
8

Типичный шаблон использования UITableView состоит в том, чтобы основной UIViewController стал целевым источником данных и делегировал его для UITableView, на который он держится.Простой способ отделить UITableview datasource и делегировать от основного класса UIViewController?

Есть ли простые и легкие в использовании учебные пособия, которые помогут мне разобраться, как переместить код, который относится к методам UITableViewDelegate и UITableViewDataSource, в отдельный класс и вместо этого подключить его к моему UIViewController? В идеале я бы хотел, чтобы и делегат, и источник данных жили в одном классе.

Прямо сейчас, я создаю UITableView через Interface Builder и подключая его выход к классу контроллера.

Типичный код:

@interface MyController : UIViewController <UITableViewDelegate, UITableViewDataSource> 
{ 
    IBOutlet UITableview *myTableview; 
} 

Я хочу сделать что-то больше, как это:

@interface MyController : UIViewController 
{ 
    IBOutlet UITableview *myTableview; 
} 
@end 

@interface MyTableSourceDelegate : NSObject<UITableViewDelegate, UITableViewDataSource> 
{ 
} 

@implementation MyTableSourceDelegate 
    // implement all of the UITableViewDelegate and methods in this class 
@end 
+0

Возможный дубликат [проблема UITableView при использовании отдельного делегата/источника данных] (http://stackoverflow.com/questions/254354/uitableview-issue-when-using-separate-delegate-datasource) –

ответ

0

Вы можете создать Separe классы (с UITableViewDelegate, UITableViewDataSource) и добавить их в IB в качестве внешних файлов и link IBActions

+0

У меня есть отдельный класс, который реализует UITableViewDelegate, UITableViewDataSource в MyController. Как вы связываете эти экземпляры как IBActions? –

0

В IB вы можете перетащить «Внешний объект» из библиотеки -> Cocoa Touch-> Controllers в ваше xib-окно. Затем вы можете выбрать этот объект, просмотреть инспектор и установить класс. Теперь она доступна, чтобы служить в качестве делегата и т.д.

+0

Занимается ли IB внедрением этого класса? Нужно ли мне что-то делать, чтобы использовать его? Я пробовал это, но мое приложение, похоже, сбой из-за «EXC_BAD_ACCESS». –

+0

Да, вы правы. Теперь я получаю то же самое, что могу проверить. Я переделал это, перетащив объект вместо внешнего объекта. Затем я объявил IBOutlet, введенный в тип объекта Object в контроллере владельца файла. Затем я связал делегата целевого нового элемента управления с новым объектом, представлением нового объекта с новым элементом управления и новым IBOutlet для нового объекта ... и он запускается! – shawnwall

+0

FYI причина для IBOutlet заключается в том, что новый элемент управления необходимо сохранить после создания экземпляра. Если вы этого не сделаете, это немедленно уничтожается, и вы получаете исключение нулевого указателя. – shawnwall

2

Я провожу 2 часа, чтобы решить эту проблему:

Это работает для меня

// GenreDataSource.h 

#import Foundation/Foundation.h 

    @interface GenreDataSource : NSObject <UITableViewDataSource> { 
     NSArray *dataSource; 
     CGSize cellSize; 
    } 

@property(nonatomic, assign) CGSize cellSize; 

@end 



// GenreDataSource.m 
#import "GenreDataSource.h" 

@implementation GenreDataSource 
@synthesize cellSize; 

-(id)init{ 

    self = [super init]; 
    if (self != nil) { 

     dataSource = [[NSArray alloc] initWithObjects:@"All",@"Folk",@"Disco",@"Blues",@"Rock",@"Dance",@"Hip-Hop",@"R&B",@"Soul",@"Lounge",@"Techno",@"Bubstep", nil]; 
    } 
    return self; 
} 

#pragma mark - UITableViewDataSource 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 
    return [dataSource count]; 
} 

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

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 

     cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero] autorelease]; 
     [cell setSelectionStyle:UITableViewCellSelectionStyleGray]; 

     //сконфигурируем структуру 
     FontLabel *fLabel= [[FontLabel alloc] initWithFrame:CGRectMake(30, 
                     5, 
                     cellSize.width-30, 
                     cellSize.height-5) 
                fontName:@"HelveticaNeueCondensedBlack" 
                pointSize:18.0f]; 
     [fLabel setTextColor:[UIColor darkTextColor]]; 
     [fLabel setTag:101]; 
     [fLabel setBackgroundColor:[UIColor clearColor]]; 
     [cell.contentView addSubview:fLabel]; 
     [fLabel release]; 
    } 

    FontLabel *fLabel = (FontLabel*)[cell viewWithTag:101]; 
    [fLabel setText:[dataSource objectAtIndex:indexPath.row]]; 

    return cell; 
} 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ 
    return 1; 
} 

@end 
2

Первая вещь, если вы используете подкласс UITableViewController с интерфейсом строитель вы хотите отсоединить делегатов и источников данных, которые уже подключены по умолчанию. (Подсказка, посмотрите в инспекторе соединений). Проверьте, даже если у вас есть tableView внутри viewController.

Второй создавать свои классы и убедиться, что они соответствуют <UITableViewDelegate> и <UITableViewDataSource>. Вероятно, вам придется объявить этот контракт в файле .h, если вы используете objc.

Третий, на ваш взгляд контроллера экземпляр этого класса или два отдельных класса где-то, как viewDidLoad, а затем назначить self.tableView.delegate = myCustomDelegateInstance и self.tableView.dataSource = myCustomDataSourceInstance.

Теперь любые вызовы, которые поступают через контроллер, будут отправляться вашим пользовательским обработчикам. Довольно простой.

Единственная причина, по которой на самом деле это сделать: 1) иметь очень раздутый контроллер или 2) вам нужно повторно использовать методы dataSource и делегировать где-то еще, и вы хотите избежать повторения кода. В противном случае, вероятно, лучше отказаться от этого.