2010-01-19 4 views
8

Le modèle d'utilisation UITableView typique consiste à faire en sorte que le principal UIViewController devienne une source de données cible et un délégué pour UITableView auquel il tient.Façon simple de séparer la source de données UITableview et déléguer de la classe principale UIViewController?

Existe-t-il des didacticiels simples et faciles à suivre qui pourraient m'aider à trouver le moyen de déplacer le code correspondant aux méthodes UITableViewDelegate et UITableViewDataSource dans une classe séparée et de l'accrocher à mon UIViewController? Idéalement, j'aimerais que le délégué et la source de données vivent dans la même classe.

Actuellement, je crée l'UITableView via Interface Builder et connecte sa sortie à ma classe de contrôleurs.

Code typique:

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

Je veux faire quelque chose comme ceci:

@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

duplication possible de [problème UITableView lors de l'utilisation séparée delegate/dataSource] (http://stackoverflow.com/questions/254354/uitableview-issue-when-using-separate-delegate-datasource) –

Répondre

0

Vous pouvez créer des classes separé (avec UITableViewDelegate, UITableViewDataSource) et les ajouter dans IB sous forme de fichiers externes et lier l'IBActions

+0

J'ai la classe séparée que implémente UITableViewDelegate, UITableViewDataSource dans MyController. Comment liez-vous ces instances en tant qu'IBActions? –

0

Dans IB, vous pouvez faire glisser un 'Objet externe' depuis Library-> Cocoa Touch-> Controllers dans votre fenêtre xib. Vous pouvez ensuite sélectionner cet objet, afficher l'inspecteur et définir la classe. Il est maintenant disponible pour servir en tant que délégué, etc.

+0

Est-ce que IB s'occupe de l'instanciation de cette classe? Ai-je besoin de faire quelque chose pour l'utiliser? J'ai essayé ceci mais mon application semble s'écraser en raison de 'EXC_BAD_ACCESS'. –

+0

Oui, vous avez raison. Je reçois la même chose maintenant que je peux la tester. J'ai refait ceci en faisant glisser un objet au lieu d'un objet externe. Ensuite, j'ai déclaré une IBOutlet typée au type de l'élément Object dans le contrôleur du propriétaire du fichier. J'ai ensuite lié le délégué du nouveau contrôle cible au nouvel objet, la vue du nouvel objet au nouveau contrôle, et le nouvel IBOutlet au nouvel objet ... et il s'exécute! – shawnwall

+0

FYI La raison de l'IBOutlet est que le nouveau contrôle doit être conservé après l'instanciation. Si vous ne le faites pas, il est immédiatement détruit et vous obtenez essentiellement une exception de pointeur nul. – shawnwall

2

Je passe 2 heures pour résoudre ce problème:

Il travaille pour moi

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

Première chose est si vous utilisez une sous-classe UITableViewController avec le constructeur d'interface que vous voulez déconnecter le Déléguer des points de vente et des sources de données déjà connectés par défaut. (Indice, regardez dans l'inspecteur des connexions). Vérifiez même si vous avez une tableView dans un viewController.

Deuxième créer vos classes et assurez-vous qu'ils sont conformes aux <UITableViewDelegate> et <UITableViewDataSource>. Vous devrez probablement déclarer ce contrat dans le fichier .h si vous utilisez objc.

Troisième, Dans votre contrôleur vue instancier cette classe ou deux classes séparées quelque part comme viewDidLoad, puis attribuer self.tableView.delegate = myCustomDelegateInstance et self.tableView.dataSource = myCustomDataSourceInstance. Maintenant, tous les appels provenant du contrôleur seront envoyés à vos gestionnaires personnalisés. Assez basique. La seule raison de faire ceci est si vous avez 1) un contrôleur très gonflé, ou 2) vous devez réutiliser les méthodes dataSource et déléguer ailleurs et vous voulez éviter la répétition de code. Sinon, il est probablement préférable de le laisser.

Questions connexes