web-dev-qa-db-fra.com

Détecter lorsque le bouton d'accueil est enfoncé iOS

J'ai plusieurs applications iOS qui utilisent toutes le même port pour écouter une balise réseau. Sur la vue principale, j'utilise viewWillDisappear pour fermer le port lorsqu'une autre vue est ouverte, ce qui fonctionnait très bien. Ensuite, j'ai remarqué que si j'appuyais sur le bouton d'accueil du contrôleur de vue principal sans ouvrir une autre vue pour fermer le port, le port reste ouvert et aucune de mes autres applications ne peut plus écouter sur ce port. J'ai ensuite essayé d'utiliser viewWillUnload, mais cela ne semble pas être appelé lorsque j'appuie sur le bouton d'accueil.

-(void)viewWillUnload
{
    //[super viewWillUnload];
    NSLog(@"View will unload");
    [udpSocket close];
    udpSocket = nil;
}

View will unload n'est jamais affiché dans la console, ce qui m'amène à croire que la méthode n'est jamais appelée.

Existe-t-il un moyen de détecter le moment où le bouton d'accueil est enfoncé pour que je puisse fermer mon port?

26
nick

Ce sont vos options

Dans votre délégué d'application:

- (void)applicationWillResignActive:(UIApplication *)application
{
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
44
Mick MacCallum

En cas de Swift User

tu peux l'écrire comme ça

override func viewDidLoad() {
    super.viewDidLoad()

    // code here...

    NSNotificationCenter.defaultCenter().addObserver(
        self,
        selector: "applicationWillResignActive:",
        name: UIApplicationWillResignActiveNotification,
        object: nil)
}

func applicationWillResignActive(notification: NSNotification) {
    print("I'm out of focus!")
}

aussi, n'oubliez pas de le fermer lorsque votre application se termine

deinit {

    // code here...

    NSNotificationCenter.defaultCenter().removeObserver(self)
}
10
Sruit A.Suk

viewWillUnload n'est généralement pas appelé sauf en cas de mémoire insuffisante. Utilisez-les à la place:

Dans votre délégué d'application:

- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

Ou si vous souhaitez utiliser du code dans votre contrôleur de vue:

- (void)viewDidDisappear:(BOOL)animated
{
//Put code here
}

- (void)viewWillDisappear:(BOOL)animated
{
//Put code here
}
5
DGund

viewWillUnload n'est souvent pas appelé sauf en cas de mémoire insuffisante. Vous feriez mieux d'implémenter les méthodes de délégué d'applicationapplicationDidEnterBackground: ou applicationWillTerminate: et y effectuer le travail ou envoyer une notification à la partie de votre application qui sait comment gérer le processus de nettoyage.

5
warrenm

Mieux vaut utiliser UIApplicationWillResignActive et UIApplicationDidBecomeActive car ils capturent "l'événement de capture et de libération du rectangle supérieur". Je suggère d'utiliser cette classe racine:

class VBase: UIViewController {
    fileprivate var listenersActivated = false
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        onStart()
    }
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        onStop()
        removeListeners()
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
        onStop()
        removeListeners()
    }

    internal func iniListeners() {
        if (!listenersActivated) {
            NotificationCenter.default.addObserver(self, selector: #selector(onStop), name: NSNotification.Name.UIApplicationWillResignActive, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(onStart), name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil)
            listenersActivated = true
        } else {

        }
    }
    internal func removeListeners() {
        NotificationCenter.default.removeObserver(self)
        listenersActivated = false
    }
    internal func onStop() {

    }
    internal func onStart() {
        iniListeners()
    }

}

Remplacez onStop() et onStart() à l'intérieur de l'enfant pour capturer toute apparence/disparition de la vue

C'est,

class SomeViewController: VBase {

...
    override func onStart() {
        super.onStart()
        someFunctionToInitialize()
    }
    override func onStop() {
        super.onStop()
        stopTimer()
        someFunctionToDesctruction()
    }
}
4
Vyacheslav