2012-04-25 13 views
25

Tengo varias aplicaciones de iOS que usan el mismo puerto para escuchar una señal de red. En la vista principal, uso viewWillDisappear para cerrar el puerto cuando se abre otra vista, que funcionaba muy bien. Luego noté que si presionaba el botón de inicio desde el controlador de vista principal sin abrir otra vista para cerrar el puerto, entonces el puerto permanece abierto y ninguna de mis otras aplicaciones puede seguir escuchando en ese puerto. Luego intenté usar viewWillUnload, pero parece que no se llama cuando presiono el botón de inicio.Detectar cuando se presiona el botón de inicio iOS

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

Ver descargará nunca se muestra en la consola, lo que me lleva a creer que el método no está recibiendo llamadas.

¿Hay alguna forma de detectar cuándo se presiona el botón de inicio para poder cerrar el puerto?

+3

intenta utilizar el método "applicationWillTerminate" .:-) –

+1

El método "applicationWillTerminate" no existe. Sin embargo, las subclases pueden registrarse para UIApplicationWillTerminateNotification y luego hacer su propia limpieza o cierre. –

Respuesta

39

Estos son sus opciones

En delegado de la aplicación:

- (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:. 
} 
+0

Como obviamente estoy de acuerdo, +1 – DGund

+2

tenía el código para cerrar el puerto en viewWillDisappear y no parecía que se llamara. El puerto permanecería abierto y las demás aplicaciones que usaban el puerto fallarían. Configuré un método de clase para cerrar el puerto y llamarlo desde applicationDidEnterBackground y funciona muy bien – nick

+7

'viewWillDisappear' o' viewDidDisappear' no se llama cuando se presiona el botón Inicio o la aplicación finaliza. La mejor solución es usar la notificación 'UIApplicationWillResignActiveNotification' – Sam

5

viewWillUnload menudo no se llama, excepto en el caso de la memoria baja. Es mejor que implemente el application delegate methodsapplicationDidEnterBackground: o applicationWillTerminate: y haga el trabajo allí o envíe una notificación a la parte de su aplicación que sepa cómo manejar el proceso de limpieza.

5

viewWillUnload generalmente no se llama excepto en el caso de poca memoria. uso estos en su lugar:

en su aplicación Delegado:

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

O si desea utilizar el código en el controlador de vista:

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

- (void)viewWillDisappear:(BOOL)animated 
{ 
//Put code here 
} 
+0

viewWill/DidDisappear llamará cuando se cierre la aplicación. No cuando se presionó el botón de inicio para minimizar las aplicaciones al centro de control. – khunshan

31

La forma más fácil de manejar esto es registrarse para recibir la notificación UIApplicationWillResignActiveNotification en su controlador de vista.

El evento se emite en un botón de inicio de prensa, bloqueo y sobre una llamada telefónica

- (void) applicationWillResign{ 
    NSLog(@"About to lose focus"); 
} 

- (void) myVcInitMethod { 
    [[NSNotificationCenter defaultCenter] 
     addObserver:self 
     selector:@selector(applicationWillResign) 
     name:UIApplicationWillResignActiveNotification 
     object:nil]; 
} 
+3

¿Por qué pasar NULL en lugar de nil? – mszaro

+1

Edité el código para usar nil. – PeterPurple

+8

En realidad, la notificación 'applicationWillResignActive' _no es siempre la mejor manera de hacerlo, ya que resignar activo también incluye (accidentalmente) deslice hacia abajo el menú superior, o el nuevo menú deslizable hacia arriba en ios 7.' applicationDidEnterBackground' significa que su aplicación fue "minimizada" , y está disponible en iOS 4. – bobobobo

10

En caso de Swift usuario

se puede escribir como esto

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!") 
} 

también , No olvide cerrarlo cuando su aplicación finalice

deinit { 

    // code here... 

    NSNotificationCenter.defaultCenter().removeObserver(self) 
} 
+0

Si usas iOS 9 o posterior, puedes olvidarte de eliminar observadores en el método de deinit. Pero, solo si no planea soportar iOS 8 o anterior. Y, como dijo @bobobobo, debe usar applicationDidEnterBackground –

2

Es mejor usar UIApplicationWillResignActive y UIApplicationDidBecomeActive debido a que atrapan 'captura de rectángulo superior y evento de liberación'. sugeriría a utilizar esta clase raíz:

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() 
    } 

} 

Anulación onStop() y onStart() del niño dentro de atrapar todas las vistas aparición/desaparición

Es decir,

class SomeViewController: VBase { 

... 
    override func onStart() { 
     super.onStart() 
     someFunctionToInitialize() 
    } 
    override func onStop() { 
     super.onStop() 
     stopTimer() 
     someFunctionToDesctruction() 
    } 
} 
Cuestiones relacionadas