37 votes

Appel d'une méthode dans le contrôleur de vue actuel à partir d'un délégué d'application dans iOS

J'ai deux contrôleurs de vue (BuildingsViewController et RoomsViewController) qui utilisent tous deux une fonction dans le délégué d'application appelée upload. La fonction de téléchargement effectue une requête HTTP et, en cas de succès ou d'échec, déclenche une vue Uialert. Cela fonctionne bien.

La partie qui me pose problème se trouve dans le délégué de l'application. connectionDidFinishLoading méthode. J'ai besoin de pouvoir rafraîchir le contrôleur de vue actuel par le biais d'une méthode de type viewWillAppear de ce contrôleur de vue. À l'intérieur du viewWillAppear de chaque contrôleur de vue, j'ai du code qui détermine les boutons de la barre d'outils inférieure.

Je veux que le bouton "télécharger" dans la barre d'outils de chaque contrôleur de vue soit automatiquement supprimé lorsque le téléchargement est effectué par le délégué de l'application.

J'ai essayé de faire [viewController viewWillAppear:YES] de l'intérieur de la connectionDidFinishLoading du délégué de l'application, mais elle n'est jamais appelée.

J'espère que je suis assez clair. Toute aide est grandement appréciée.

Merci.

86voto

Cyprian Points 7158

Pour faire le rafraîchissement de la vue, ne pas appeler viewWillAppear si la vue est déjà affichée. Ce que vous voulez faire est le suivant :

Lorsque ConnectionDidFinishLoading est déclenchée après une notification

[[NSNotificationCenter defaultCenter] postNotificationName:@"refreshView" object:nil];

Dans votre viewController observer pour cette notification. Vous le faites en ajoutant ce code à votre init ou à votre viewDidLoad méthode

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshView:) name:@"refreshView" object:nil];

Maintenant, mettez en œuvre -(void)refreshView:(NSNotification *) notification dans votre viewController pour gérer votre vue à votre convenance.

3voto

ughoavgfhw Points 28400

Si vous ciblez iOS 4.0 et les versions ultérieures, vous pouvez utiliser la fenêtre rootViewController pour obtenir le contrôleur de vue actuel.

[window.rootViewController viewWillAppear];

Si vous souhaitez que votre application fonctionne sur des versions antérieures à iOS 4.0, vous pouvez ajouter une variable d'instance au délégué d'application pour vous souvenir du contrôleur de vue qui a appelé la fonction upload en faisant en sorte que le contrôleur s'envoie lui-même comme paramètre.

- (void)upload:(UIViewController *)viewController {
    self.uploadingViewController = viewController; // This is the property you add
    ...
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    [self.uploadingViewController viewWillAppear];
    self.uploadingViewController = nil;
}

Vous devriez également envisager d'utiliser une méthode différente pour recharger les boutons, quelque chose comme reloadButtons car elle n'est pas liée à la vue qui apparaît dans ce cas. Vous appelleriez alors cette méthode à partir de viewWillAppear .

2voto

Sid Points 6025

Étape 1 :

Dans votre fichier App Delegate .h, vous devez déclarer un protocole comme suit :

@protocol AppConnectionDelegate <NSObject>
@required
   -(void)connectionFinished:(NSObject*)outObject;
@end

Dans le même fichier, ajoutez un ivar comme suit :

id *delegate;

Déclarer l'ivar comme une propriété :

@property (nonatomic, assign) id<AppConnectionDelegate> delegate;

Dans le fichier .m de l'App Delegate, synthétiser l'ivar :

@synthesize delegate;

Dans le fichier .m de l'App Delegate, sur connectionDidFinishLoading faire :

if([self.delegate respondsToSelector:@selector(connectionFinished:)])
{
   [self.delegate connectionFinished:objectYouWantToSend];
}

Dans le fichier .h de votre viewcontroller, mettez en œuvre le délégué AppConnectionDelegate en important une référence au fichier du délégué App :

#import "AppDelegate_iPhone.h" //if using iPhone
#import "AppDelegate_iPad.h" //if using iPad

Dans le même fichier, à la fin de la première ligne de la déclaration de l'interface, faites :

@interface AppDelegate_iPhone : AppDelegate_Shared <AppConnectionDelegate>

Déclarez les ivars en conséquence :

AppDelegate_iPhone *appDelegate; //if using iPhone
AppDelegate_iPad *appDelegate; // if using iPad

Dans le fichier .m de votre viewcontroller, dans le viewDidLoad(), obtenez une référence à votre délégué d'application en utilisant :

Si iPhone ;

appDelegate = (AppDelegate_iPhone*)[[UIApplication sharedApplication] delegate];

Si iPad :

appDelegate = (AppDelegate_iPad*)[[UIApplication sharedApplication] delegate];

Ensuite, définissez le viewcontroller pour être le délégué dans viewDidLoad() en faisant :

appDelegate.delegate = self;

Maintenant, vous devez simplement implémenter la méthode connectionFinished dans le fichier .m :

- (void)connectionFinished:(NSObject*)incomingObject
{
//Do whatever you want here when the connection is finished. IncomingObject is the object that the app delegate sent.
}

Maintenant, chaque fois que la connexionDidFinishLoading de votre délégué d'application est appelée, le contrôleur de vue sera notifié.

[Une bonne pratique consiste à définir appDelegate.delegate = nil si vous avez fini d'utiliser le callback connectionFinished].

Cela a fait ses preuves. Si vous avez des questions, laissez un commentaire.......

--EDIT--
Il s'agit d'une alternative robuste à la NSNotification. J'utilise les deux en fonction des besoins. Le processus que j'utilise pour décider entre l'utilisation de la NSNotification ou d'un rappel de délégué utilisant un protocole est simple :

Pour les notifications :
Un expéditeur, plusieurs auditeurs.
Aucune référence possible entre l'expéditeur et l'auditeur.
Les objets complexes/multiples ne doivent pas être envoyés

Pour les appels de délégués utilisant des protocoles :
Un expéditeur, un nombre limité (généralement 1) d'auditeurs.
Une référence entre l'expéditeur et l'auditeur est possible.
Des objets complexes/multiples doivent être envoyés (par exemple, des objets de réponse qui doivent être envoyés)

Je sais que l'envoi d'objets est possible par le biais de notifications, mais je préfère les protocoles pour cela.
--EDIT--

0voto

Dan F Points 11380

Dans le pire des cas, vous pouvez faire en sorte que les deux contrôleurs de vue adhèrent à un simple protocole à une méthode qui supprimera ce bouton et rafraîchira la vue. Puis, dans votre méthode connectionDidFinishLoading, puisque vous savez que votre contrôleur de vue doit adhérer à ce protocole, vous faites simplement quelque chose comme suit

ViewController<MyProtocol> curView = (Get the current view controller somehow);
[curview refreshView];

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X