web-dev-qa-db-fra.com

Méthode d'appel dans le contrôleur de vue actuel à partir du délégué App dans iOS

J'ai deux contrôleurs de vue (BuildingsViewController et RoomsViewController) qui utilisent tous les deux une fonction dans le délégué d'application appelée upload. La fonction de téléchargement effectue essentiellement une requête HTTP et, si elle aboutit ou non, déclenche une vue uialert. Cela fonctionne bien.

La partie avec laquelle je me bats provient de la méthode connectionDidFinishLoading du délégué de l'application. Je dois pouvoir fondamentalement actualiser le contrôleur de vue actuel via peut-être la méthode viewWillAppear de ce contrôleur de vue. Dans la fonction viewWillAppear de chaque contrôleur de vue, j'ai un code qui détermine les boutons de la barre d'outils inférieure. 

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

J'ai essayé de faire [viewController viewWillAppear:YES] à partir de la méthode connectionDidFinishLoading du délégué de l'application, mais celle-ci n'est jamais appelée.

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

Merci.

37
yupyupyup

Pour actualiser la vue, n'appelez pas viewWillAppear si la vue est déjà affichée. Ce que vous voulez faire est le suivant:

Lorsque la méthode ConnectionDidFinishLoading est déclenchée, publier une notification

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

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

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

Maintenant, implémentez la méthode -(void)refreshView:(NSNotification *) notification dans votre viewController pour gérer votre vue à votre guise.

86
Cyprian

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

[window.rootViewController viewWillAppear];

Si vous souhaitez que votre application s'exécute sur des versions antérieures à iOS 4.0, vous pouvez ajouter une variable d'instance au délégué de l'application pour mémoriser le contrôleur de vue appelé méthode upload, le contrôleur s'envoyant lui-même en tant que 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 pouvez alors appeler cette méthode depuis viewWillAppear.

3
ughoavgfhw

É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éclarez l'ivar comme une propriété:

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

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

@synthesize delegate;

Dans le fichier App Delegate .m, sur connectionDidFinishLoading, procédez comme suit:

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

Dans le fichier .h de votre viewcontroller, implémentez AppConnectionDelegate en important une référence dans le fichier délégué de l'application:

#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 d'interface, faites:

@interface AppDelegate_iPhone : AppDelegate_Shared <AppConnectionDelegate>

Déclarez ivars en conséquence:

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

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

Si iPhone;

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

Si iPad:

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

Définissez ensuite le contrôleur de vue comme délégué dans viewDidLoad () en procédant comme suit:

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.
}

Désormais, chaque fois que connectionDidFinishLoading de votre délégué d’application est appelé, le contrôleur de vue en est averti.

[Il est recommandé de définir appDelegate.delegate = nil si vous avez terminé d'utiliser le rappel connectionFinished]

Ceci est essayé et testé. Si vous avez des questions, laissez un commentaire ......

--MODIFIER--
Ceci est une alternative robuste à NSNotification. J'utilise les deux en fonction des besoins. Le processus que j'utilise pour décider d'utiliser NSNotification ou un rappel de délégué à l'aide d'un protocole est simplement: 

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 callbacks délégués utilisant des protocoles:
Un expéditeur, auditeurs limités (généralement 1).
Une référence entre l'expéditeur et l'auditeur est possible.
Les objets complexes/multiples doivent être envoyés (par exemple, les objets de réponse à envoyer)

Je sais qu’envoyer des objets est possible par notifications mais je préfère les protocoles pour cela .
--MODIFIER--

2
Sid

Pire encore, vous pouvez faire en sorte que les deux contrôleurs de vue adhèrent à un protocole simple à une méthode qui supprime ce bouton et actualise la vue. Ensuite, dans votre méthode connectionDidFinishLoading, puisque vous savez que votre contrôleur de vue doit adhérer à ce protocole, par votre conception, vous faites simplement quelque chose comme:

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