1

Mon problème consiste à obtenir les informations d'un contrôleur (qui se trouve être mon rootViewController) à une autre vue. En essayant d'y accéder via le délégué de l'application, je n'ai pas réussi à le faire fonctionner. J'ai trouvé comment faire ceci, mais cela a créé un autre problème d'obtenir la vue à l'intérieur d'un contrôleur de vue modale pour réellement afficher les données. Ci-dessous, j'ai posté à la fois les informations appDelegate, et un code de solution NSMutable Dictionary pour ceux qui pourraient avoir besoin d'aide aussi.AppDelegate Accès à partir de différentes classes, à partir de RootController.m

J'avais essayé pendant plus d'une semaine pour résoudre ce problème par moi-même. Mon problème a fini par être comment accéder à l'appDelegate, qui était la raison pour laquelle j'avais un problème avec le NSDictionary. Donc, à la fin, le problème n'était pas le NSDictionary, même si j'étais allé plus loin, cela aurait été un problème, j'en suis sûr. Tout d'abord, je tiens à remercier TechZen pour m'avoir aidé à voir que j'étais sur la programmation, et me diriger dans la bonne direction.

Voici ce que j'ai appris.

Affectez votre variable dans appDelegate.

AppDelegate.h

@interface AppDelegate : NSObject < UIApplicationDelegate, UINavigationControllerDelegate > 
{ 
    UIWindow *window; 
    UINavigationController *navController; 

    // Array to store the Makers Objects 
    NSMutableArray *makers; 

} 

@property (nonatomic, retain) IBOutlet UIWindow *window; 
@property (nonatomic, retain) IBOutlet UINavigationController *navController; 

@property (retain, nonatomic) NSMutableArray *makers; 
@end 

AppDelegate.m

- (void)applicationDidFinishLaunching:(UIApplication *)application 
{ 

    makers = [[NSMutableArray alloc] init] ; 
} 

Dans la ViewController.m assigner la variable à la appDelegate. Je l'ai fait dans une fonction tableView: didSelectRowAtIndexPath. Maintenant, dans votre vue Controller, vous voulez charger la variable à partir de appDelegate, configurez-la comme ceci.

#import <UIKit/UIKit.h> 

#import "AppDelegate.h" 
#import "Maker.h" 

@class AppDelegate; 

@interface DetailsViewController : UIViewController 
{ 

     AppDelegate *dappDelegate; 
    DetailsViewController *detailsView; 

    IBOutlet UITextView *makerDescription; 

} 

@property (retain, nonatomic) AppDelegate *dappDelegate; 

@property (nonatomic, retain) DetailsViewController *detailsView; 

@property (nonatomic, retain) IBOutlet UITextView *makerDescription; 

@end 

et dans le fichier viewController.m;

#import "DetailsViewController.h" 
#import "AppDelegate.h" 

@synthesize dappDelegate; 

- (void)viewWillAppear:(BOOL)animated // or ViewDidLoad not sure which is better. 

    dappDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate]; 
    NSString *newLocalVariable = [dappDelegate.makers description]; 

NSLog(@"newLocalVariable: %@", [dappDelegate.makers description]); 
// This is for verifying you have it loaded. 'description' is defined in the Maker NSObject, see below for those files, and above for where it was assigned originally 

... et de l'assigner à ce que vous voulez maintenant!

J'espère que cela aide tout le monde. Vous pouvez à ce moment déposer le NSArray à partir de là dans un NSDictionary, mais l'accès est maintenant avec des clés et des valeurs, donc un peu plus compliqué à ce stade pour accéder, mais bien sûr des avantages. Je n'arrive tout simplement pas encore à le comprendre et j'ai abandonné cette méthode pour utiliser un NSArray pour l'instant.

Vous trouverez ci-dessous un exemple de fichier Makers h et m à afficher également.

Maker.h 

@interface Maker : NSObject 
{ 
    NSString *name; 
    NSString *address; 
    NSString *city; 
    NSString *postalcode; 
    NSString *country; 
    NSString *phonenumber; 
    NSString *email; 
    NSString *description; 
    NSString *services; 
    NSString *website; 
} 

@property (nonatomic, copy) NSString *name; 
@property (nonatomic, copy) NSString *address; 
@property (nonatomic, copy) NSString *city; 
@property (nonatomic, copy) NSString *postalcode; 
@property (nonatomic, copy) NSString *country; 
@property (nonatomic, copy) NSString *phonenumber; 
@property (nonatomic, copy) NSString *email; 
@property (nonatomic, copy) NSString *description; 
@property (nonatomic, copy) NSString *services; 
@property (nonatomic, copy) NSString *website; 

- (id)initWithName:(NSString *)n address:(NSString *)a city:(NSString *)c postalcode:(NSString *)z country:(NSString *)o phonenumber:(NSString *)p email:(NSString *)e description:(NSString *)d services:(NSString *)s website:(NSString *)w; 

@end 

et son fichier Maker.m;

#import "ViolinMaker.h" 

@implementation Maker 
@synthesize name, address, city, postalcode, country, phonenumber, email, description, services, website; 

- (id)initWithName:(NSString *)n address:(NSString *)a city:(NSString *)c postalcode:(NSString *)z country:(NSString *)o phonenumber:(NSString *)p email:(NSString *)e description:(NSString *)d services:(NSString *)s website:(NSString *)w; 
{ 
    self.name = n; 
    self.address = a; 
    self.city = c; 
    self.postalcode = z; 
    self.country = o; 
    self.phonenumber = p; 
    self.email = e; 
    self.description = d; 
    self.services = s; 
    self.website = w; 
    return self; 
} 
@end 

J'espère que cela aide les autres à obtenir ce droit, car il m'a vraiment coûté beaucoup de temps et je l'espère, vous pouvez obtenir un peu de ce que j'appris.

Sincèrement, Kirk

+0

Quelle est la question? L'avez-vous édité? –

Répondre

2

Je ne vois aucun point où vous remplissez le selectedMaker Ivar dans le DetailsViewController avec les données de `la selectedMaker du délégué de l'application. Juste parce qu'ils ont le même nom ne signifie pas qu'ils partagent les mêmes données.

Vous devez affecter ou copier les valeurs du délégué de l'application au contrôleur de vue. La façon rapide et sale est de faire quelque chose comme:

@implementation DetailsViewController 

... 

-(void) viewDidLoad{ 
//selectedMaker=[[UIApplication sharedApplication] selectedMaker]; <-- this is wrong 
//Edit, this is the correct call to app delegate 
selectedMaker=[[[UIApplication sharedApplication] delegate] selectedMaker]; 
} 

Edit01:

Alors ... à la suggestion de TechZen je ai essayé de déplacer mon NSDictionary sur de mon RootViewController.

(1) Je ne sais pas pourquoi vous avez la classe SelectedMaker de ce qu'elle est supposée accomplir. Vous semblez avoir confondu la classe avec un NSMutableDictionary. La classe n'a aucune raison apparente de retourner un dictionnaire contenant les valeurs de ses propres iVars. C'est complètement redondant. Vous semblez déjà avoir une classe appelée ViolinMaker qui encapsule toutes les données de chaque enregistrement de lutherie.

(2) Les méthodes d'initialisation pour SelectedMaker ne sont pas implémentées correctement. Il semble que vous devez appeler -[SelectedMaker initWithsName:..] avant d'appeler le -[SelectedMaker init] sinon init n'a aucune idée de ce que sont les clés.

(3) Dans tous les cas, dans la méthode didSelectRow, vous n'initialisez pas réellement une instance de SelectedMaker. Cette ligne:

SelectedMaker *selectedMaker = [[[NSMutableDictionary alloc]retain] initWithObjects: objects forKeys: keys]; 

ne crée pas une instance de SelectedMaker mais plutôt un NSMutableDictionary et plus ou moins jeté à la classe SelectedMaker. C'est pourquoi vous obtenez l'avertissement du compilateur de la boucle for.

(4) Je ne vois aucun besoin de la classe SelectedMaker. Ces lignes:

ViolinMakerAppDelegate *appDelegate = (ViolinMakerAppDelegate *)[[UIApplication sharedApplication] delegate]; 
ViolinMaker *violinMaker = (ViolinMaker *)[appDelegate.violinMakers objectAtIndex:indexPath.row]; 
violinMaker = [self.filteredViolinMakers objectAtIndex:indexPath.row]; 

vous semblent fournir toutes les informations dont vous avez besoin pour remplir une ligne dans votre table ou votre vue détaillée. Vous pouvez utiliser ces trois lignes dans n'importe quelle vue dans laquelle vous devez accéder aux données dans appDelegate.violinMakers'. The violinMaker`object contient toutes les données dont vous avez besoin.

Je pense que vous rendez cela plus compliqué qu'il ne devrait l'être. Tout ce dont vous avez besoin est (A) une classe qui encapsule les données pour chaque enregistrement extrait de votre SQL. Dans ce cas, il semble que ViolinMaker le fasse. (B) Vous avez besoin d'un tableau (ou d'une autre collection) dans le délégué de l'application pour stocker les multiples instances de ViolinMaker. (C) Vous avez besoin de code dans chaque viewcontroller qui va accéder au tableau/collection dans le délégué de l'application afin que le viewcontroller puisse sélectionner les instances de ViolinMaker dont il a besoin.

Edit02:

non, je ne peux pas utiliser ces 3 lignes, comme 'objectAtIndex: indexPath.row' est seulement disponible à l'intérieur la fonction didSelectRow . Ce qui signifie que je devrais reconstruire la table et toutes ses données .

Vous ne définissez le dictionnaire qu'une seule fois en tant que variable d'instance dans votre délégué d'application. Donc, vous auriez un dictionnaire mutable où chaque valeur était ViolinMaker et chaque clé était un attribut d'un fabricant de violon tel que le nom. Appelons cela violinMakersDict.Ensuite, n'importe où dans votre application, vous accéderez au dictionnaire en appelant d'abord le délégué de l'application et l'accès au violinMakersDict.

Pour remplir une table, vous devez extraire les valeurs en tant que tableau. Très probablement, vous prendriez les clés qui sont les noms des fabricants de violon. Ensuite, vous trieriez le tableau par ordre alphabétique, puis vous rempliriez chaque ligne avec la valeur du tableau à la valeur index.row. De même, si vous devez ajouter des données dans une vue, vous pouvez écrire sur le violinMakersDict puis accéder à ces données à partir d'une autre vue en appelant à nouveau le délégué de l'application.

+0

Très cool, et c'est exactement ce que je demande, car je pensais instancier une nouvelle variable, et il avait juste le même nom ... Mais comment puis-je charger les valeurs dans l'appDelegate ?? désolé, je ne comprends pas comment charger ces valeurs dans l'Appdelegate? Merci beaucoup! Kirk – Digiguy

+0

Désolé, pas l'habitude de ce site, j'apprécie vraiment votre aide TechZen. Mon problème est que je charge le NSMuteableDictionary à partir du RootViewController (un UITableViewController, à l'intérieur de tableView didSelectRowAtIndexPath), pas à l'intérieur de l'appDelegate. Je peux charger avec des informations là-bas, je ne comprends pas comment l'obtenir dans une autre vue à partir de là. Je vois ce que vous dites là, mais il dit simplement un avertissement jaune 'UIApplication peut ne pas répondre au' sélectionneur ' – Digiguy

+0

Si les données sont dans le rootViewController vous devez assigner le tableau au sous-contrôleur avant de le placer dans la pile de navigation. (Je peux fournir un exemple plus tard si vous le demandez.) En règle générale, vous ne conservez pas de données dans un contrôleur de vue. Il devrait y avoir un objet séparé qui contient les données. Cela est particulièrement vrai si plus d'un contrôleur doit accéder aux données. Le délégué de l'application est généralement le meilleur endroit pour le garer. Lisez le modèle de conception Model-View-Controller. Il est très important de comprendre comment fonctionnent toutes les API basées sur l'objectif c. – TechZen