2010-01-19 3 views
8

Das typische UITableView-Verwendungsmuster besteht darin, dass der Haupt-UIViewController eine Zieldatenquelle und Delegat für die UITableView wird, an der er sich befindet.Einfache Möglichkeit, UITableview-Datenquelle und Delegate von der UIViewController-Hauptklasse zu trennen?

Gibt es einfache und leicht zu befolgende Lernprogramme, die mir helfen würden, herauszufinden, wie der Code für die Methoden UITableViewDelegate und UITableViewDataSource in eine separate Klasse verschoben und stattdessen an meinen UIViewController angehängt werden kann? Ich möchte idealerweise sowohl den Delegierten als auch die Datenquelle in derselben Klasse leben lassen.

Momentan erstelle ich das UITableView über den Interface Builder und verbinde seinen Ausgang mit meiner Controller-Klasse.

Typische Code:

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

Ich möchte so etwas mehr tun:

@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

mögliche Duplikate von [UITableView Problem bei der Verwendung separaten Delegate/dataSource] (http://StackOverflow.com/questions/254354/uitableview-issue-when-using-separate-delegate-datasource) –

Antwort

0

Sie können separe Klassen erstellen (mit UITableViewDelegate, UITableViewDataSource) und fügen Sie sie in IB als externe Dateien und Verbinden Sie die IBActions

+0

Ich habe die separate Klasse, die implementiert UITableViewDelegate, UITableViewDataSource in MyController. Wie verknüpfst du diese Instanzen als IBActions? –

0

In IB können Sie ein 'Externes Objekt' aus Bibliothek-> Cocoa Touch-> Controller in Ihr XIB-Fenster ziehen. Sie können dann das Objekt auswählen, den Inspektor anzeigen und die Klasse festlegen. Es ist jetzt verfügbar als Delegierter dienen usw.

+0

Kümmert sich IB um die Instanziierung dieser Klasse? Muss ich etwas tun, um es zu benutzen? Ich habe es versucht, aber meine App scheint wegen "EXC_BAD_ACCESS" zu stürzen. –

+0

Ja, du hast Recht. Ich bekomme jetzt dasselbe, dass ich es testen kann. Ich habe dies neu gemacht, indem ich ein Objekt anstelle eines externen Objekts gezogen habe. Als nächstes habe ich ein IBOutlet deklariert, das in den Objekt-Objekt-Typ im Eigentümer-Controller der Datei eingegeben wurde. Dann habe ich den Delegaten des Zielsteuerelements mit dem neuen Objekt, die Ansicht des neuen Objekts mit dem neuen Steuerelement und das neue IBOutlet mit dem neuen Objekt verknüpft ... und es läuft! – shawnwall

+0

FYI Der Grund für das IBOutlet ist, dass das neue Steuerelement nach der Instanziierung beibehalten werden muss. Wenn Sie dies nicht tun, wird es sofort zerstört und Sie erhalten eine Null-Zeiger-Ausnahme. – shawnwall

2

verbringe ich 2 Stunden, dieses Problem zu lösen:

Es funktioniert für mich ist

// 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

Erste Sache ist, wenn Sie eine UITableViewController Unterklasse mit Interface Builder verwenden werden Sie wollen, dass die trennen Delegate- und Datenquellen-Outlets, die standardmäßig bereits verbunden sind. (Tipp, schau im Verbindungsinspektor nach). Überprüfen Sie, ob Sie ein TableView in einem ViewController haben.

Second Ihre Klassen erstellen und sicherstellen, dass sie entsprechen <UITableViewDelegate> und <UITableViewDataSource>. Wahrscheinlich müssen Sie diesen Vertrag in der .h-Datei deklarieren, wenn Sie objc verwenden.

Dritte, aus Ihrer Sicht Controller instantiate diese Klasse oder zwei getrennte Klassen irgendwo wie viewDidLoad und weisen dann self.tableView.delegate = myCustomDelegateInstance und self.tableView.dataSource = myCustomDataSourceInstance.

Nun werden alle Anrufe, die über den Controller eingehen, an Ihre benutzerdefinierten Handler gesendet. Ziemlich einfach.

Der einzige Grund, dies wirklich zu tun, ist, wenn Sie 1) einen sehr aufgeblähten Controller haben oder 2) Sie die dataSource wiederverwenden und Methoden an anderer Stelle delegieren müssen und Sie Codewiederholung vermeiden möchten. Ansonsten ist es wahrscheinlich besser, es zu verlassen.

Verwandte Themen