Comment gérer les classs de templates dans l'application iOS

Je suis un débutant dans le développement d'applications iOS, mais j'essaie d'apprendre comment faire face à Cocoa de la meilleure façon.

Je me suis coincé en essayant de comprendre comment garder et referencer correctement les objects du model.

  1. beaucoup disent d'écrire une propriété de délégué d'application pour contenir le model, puis le referencer par les methods de commodité pour le délégué de l'application singleton.
  2. d'autres disent "injecter" dans le controller de vue seulement la partie de model dont il a besoin (ou ses besoins de sous-vues), mais je ne comprends pas comment faire cela. Via une propriété? Via une méthode initWithModel: (et dans ce cas, comment puis-je dire à IB d'utiliser cette méthode?)
  3. d'autres encore disent que le model devrait être un singleton
  4. et encore, d'autres disent d'utiliser des variables globales (!)

Pourriez-vous s'il vous plaît me donner un indice (et des échantillons de code)? Je voudrais apprendre les choses de la bonne manière, count tenu du fait que je vais bientôt passer à Core Data.

Résumé : J'ai lu attentivement le sujet Où placer le "Core Data Stack" dans une application Cocoa / Cocoa Touch proposée par Brad Larson et j'ai écrit une solution possible sur la façon de traiter un model et différents controllers de vue. La solution n'utilise pas datatables de base, mais je crois que la même design peut être appliquée aux applications de database.

Scénario : considérons une application simple qui stocke des informations sur les produits, telles que le nom, la description et le prix / unité. Une fois lancée, l'application affiche une list de produits (avec un UITableView); Lorsque l'user appuie sur un nom de produit, l'application présente les détails du produit dans une autre vue, mettant à jour la barre de navigation avec le nom du produit.

Architecture Le model est assez simple ici: un tableau d'objects Product, chacun avec un nom, une description et une propriété price.

L'application a trois vues principales, principalement créées par le template de navigation de Xcode: une UINavigationView (gérée par UINavigationController, instanciée dans le délégué de l'application), l'UITableView par défaut (gérée par RootViewController et qui est la première vue affichée par UINavigationController) et un DetailView (géré par la class DetailViewController que nous devons écrire).

Voyons voir quel est le grand plan du sharepoint vue du model:

  1. Le model est instancié / chargé par le délégué de l'application sous la forme d'un object NSMutableArray des objects Product;
  2. Le pointeur vers le model est maintenant transmis au premier controller de vue de notre hiérarchie, UITableViewController, via une propriété. En fait, on pourrait argumenter que le premier controller dans la hiérarchie est le UINavigationController, donc nous devrions passer la reference à celui-ci et à UITableViewController mais … Apple dit que UINavigationController ne devrait pas être sous-classé, donc nous ne pouvons pas append de propriété /méthode. Et en fait, cela a du sens, car la responsabilité d'un UINavigationController est toujours juste la gestion de la visualisation, pas la manipulation du model.
  3. Lorsque l'user sélectionne UITableCell, UITableViewController crée un nouveau DetailViewController (avec la vue DetailView associée), passe le produit sélectionné unique en tant que propriété et pousse le détail en haut de la stack UINavigation.

Voici quelques extraits de code:

Création du model:

// SimpleModelAppDelegate.m - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // products is a protected ivar products = [[NSMutableArray alloc] init]; Product *p1 = [[Product alloc] initWithName:@"Gold" andDescription:@"Expensive metal" andUnitPrice:100]; Product *p2 = [[Product alloc] initWithName:@"Wood" andDescription:@"Inexpensive building material" andUnitPrice:10]; [products addObject:p1]; [products addObject:p2]; [p1 release]; [p2 release]; // Passing the model reference to the first shown controller RootViewController *a = (RootViewController*)[self.navigationController.viewControllers objectAtIndex:0]; a.products = products; // Add the navigation controller's view to the window and display self.window.rootViewController = self.navigationController; [self.window makeKeyAndVisible]; return YES; } - (void)dealloc { // The app delegate is the owner of the model so it has to release it. [products release]; [_window release]; [_navigationController release]; [super dealloc]; } 

Le RootViewController peut recevoir la reference du model, car il possède une propriété NSMutableArray:

 // RootViewController.h #import <UIKit/UIKit.h> @interface RootViewController : UITableViewController @property (nonatomic, retain) NSMutableArray *products; @end 

Lorsque l'user tape sur un nom de produit, le RootViewController instancie un nouveau DetailViewController et lui renvoie la reference au produit unique en utilisant à nouveau une propriété.

 // RootViewController.m - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil]; // Passing the model reference... detailViewController.product = [products objectAtIndex:indexPath.row]; [self.navigationController pushViewController:detailViewController animated:YES]; [detailViewController release]; } 

Et, à la fin, le DetailViewController montre les informations de model définissant ses sockets dans la méthode viewDidLoad.

 // DetailViewController.m - (void)viewDidLoad { [super viewDidLoad]; self.navigationItem.title = product.name; self.descriptionLabel.text = product.description; self.priceLabel.text = [NSSsortingng ssortingngWithFormat:@"%.2f eur", product.unitPrice]; } 

Vous pouvez download le projet complet ici: http://dl.dropbox.com/u/1232650/linked/stackoverflow/SimpleModel.zip

J'apprécierai vraiment n'importe quel commentaire à ma solution, j'ai hâte d'apprendre;)

Des collègues plus expérimentés recommandnt d'avoir une propriété pertinente dans AppDelegate. IMO il est préférable d'utiliser un set spécifique de templates dans un controller spécifique.

Je suis un noob aussi mais voici ce que j'ai fait. C'est plus comme # 2.

Dans applicationDidFinishLaunching, le délégué de l'application crée une instance du model.

Mes controllers de vue déclarent une propriété pointant vers le model, mais le type est un protocole (dans mon cas, id <GameModel> .) Beaucoup de propriétés dans le protocole sont déclarées comme étant readonly.

Dans applicationDidFinishLaunching, le délégué de l'application définit la propriété pour qu'elle pointe sur le model qu'elle a créé.

Ce que je n'aime pas:

Un. Vos controllers de vue ne devraient pas avoir à connaître la structure de votre délégué d'application. Vous pouvez réutiliser le même controller de vue dans une autre application, avec un type de délégué d'application différent. Vous pouvez apporter des modifications simples au code de votre controller de vue pour le corriger, ou il existe d'autres moyens de contourner le problème, mais pourquoi le rendre difficile?

Trois. Je ne suis pas aussi friands de singletons que la plupart des gens. Le problème est qu'ils sont célibataires. Que faire si vous voulez charger plusieurs templates?

Quatre. ?!?!