Tengo un objetivo de la clase C de. En ella, he creado un método init y establecer un NSNotification en ella

//Set up NSNotification
[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(getData)
                                             name:@"Answer Submitted"
                                           object:nil];

Donde puedo configurar el [[NSNotificationCenter defaultCenter] removeObserver:self] en esta clase? Sé que para un UIViewController, puedo agregar que en el viewDidUnload método de Manera que lo que se necesita hacer si he creado un objetivo de la Clase c?

  • Lo puse en el método dealloc.
  • El método dealloc no fue creado automáticamente para mí cuando he creado el objetivo de la clase c, así que me parece bien para agregar?
  • Sí, usted puede implementar -(void)dealloc y, a continuación, agregue removeObserser:self en ella. Esta es la forma más recomendable poner removeObservers:self
  • Es todavía bien, poner en el dealloc método en iOS 6?
  • Sí, está bien usar dealloc en ARCO proyectos mientras no se llama [super dealloc] (obtendrá un error de compilación si se llama [super dealloc]). Y sí, definitivamente, usted puede poner su removeObserver en dealloc.
  • Dealloc todavía existe, pero no es el lugar para esto, el dealloc nunca será llamada por la notificationcenter referencias a su objeto
  • ¿qué te ofrecen cuando NotificationCenter referencias a un objeto?
  • Ese comentario de mina es realmente malo. NotificationCentre no se mantienen fuertes referencias a objetos.

InformationsquelleAutor Zhen | 2011-06-24

14 Comentarios

  1. 112

    El genérico respuesta sería «tan pronto como usted ya no necesita las notificaciones». Obviamente, esto no es una respuesta satisfactoria.

    Me gustaría recomendar, que agrega una llamada [notificationCenter removeObserver: self] en el método dealloc de esas clases, que se va a utilizar como observadores, ya que es la última oportunidad para cancelar el registro de un observador limpiamente. Esto, sin embargo, sólo protegen contra los accidentes debido a que el centro de notificaciones notifica muerto objetos. No puede proteger su código contra la recepción de las notificaciones, cuando los objetos no son todavía/no en un estado en el que se puede manejar adecuadamente la notificación. Para este… Ver más arriba.

    Editar (ya que la respuesta parece apoyarse más comentarios de lo que yo hubiera pensado) Todo lo que estoy tratando de decir aquí es: es realmente difícil dar consejo general respecto a cuándo es el mejor para quitar el observador desde el centro de notificaciones, ya que depende:

    • En su caso de uso (Que las notificaciones se observan? Cuando no se enviar?)
    • La aplicación del observador (Cuando está listo para recibir notificaciones? Cuando ya no es listo?)
    • La intención de tiempo de vida de el observador (Está atada a algún otro objeto, por ejemplo, una vista o controlador de vista?)

    Así, el mejor consejo que se me ocurre: para proteger su aplicación. en contra de al menos una a un posible fracaso, hacer el removeObserver: danza en dealloc, ya que es el último punto en el objeto de la vida), donde usted puede hacer que limpiamente. Lo que no significa es: «sólo aplazar la eliminación de hasta dealloc se llama, y todo va a estar bien». En su lugar, quite el observador tan pronto como el objeto ya no está listo (o necesarios) para recibir notificaciones. Que es el justo momento. Por desgracia, no saber las respuestas a las preguntas mencionadas anteriormente, no puedo adivinar aún, cuando ese momento.

    Siempre se puede de manera segura removeObserver: un objeto varias veces (y todos, pero la primera llamada con un observador dado será nops). Así: pensar en hacer (de nuevo) en dealloc sólo para estar seguro, pero lo primero y más importante: hacerlo en el momento apropiado (que es determinado por el caso de uso).

    • Esto no es seguro con ARCO y potencialmente podría causar una fuga. Ver este discsussion: cocoabuilder.com/archive/cocoa/311831-arc-and-dealloc.html
    • El artículo que enlaza a la que parece hacer mi punto. Lo que me estoy perdiendo ?
    • Supongo que se debe señalar en que uno debe quitar observador en algún otro que dealloc. Por ejemplo, viewwilldisappear
    • sí. Espero, que ese es el punto que estoy recibiendo a través de mi respuesta. Extracción de la calidad de observador en dealloc es sólo una última línea de defensa contra estrellarse la aplicación debido a un posterior acceso a un decallocated objeto. Pero el lugar adecuado para anular el registro de un observador es generalmente en algún otro lugar (y, a menudo, mucho antes, en el objeto del ciclo de vida). No estoy tratando de decir, «Hey, acabo de hacerlo en dealloc y todo va a estar bien».
    • ejemplo, viewWillDisappear» El problema con la entrega de un hormigón es asesorar, que realmente depende de qué tipo de objeto que registrarse como observador para qué tipo de evento. Se mayo la mejor solución para anular el registro de un observador en viewWillDisappear (o viewDidUnload) para UIViewControllers, pero que realmente depende del caso de uso.
    • Sí, creo que no entendí tu respuesta. Creo que yo significaba para ponerlo en la respuesta de abajo, lo siento por eso
    • ARCO forbits llamadas explícitas a dealloc, por ejemplo, [super dealloc]. Esto no funciona para iOS 6.
    • Esto hará que las fugas! Dealloc nunca será llamado porque el notificationCenter aún se mantiene referencias a su objeto
    • no, el NSNotificationCenter no retener los objetos agregados con addObserver:selector:name:object:. No especifica explícitamente en la documentación, pero se puede inferir que a partir de frases como «asegúrate de invocar removeObserver: o removeObserver:nombre:objeto: antes de notificationObserver o cualquier objeto especificado en addObserver:selector:nombre:objeto: se cancela la asignación.» (o puede ejecutar un pequeño programa de prueba y verificar el comportamiento, como acabo de hacer para estar seguros).
    • Por desgracia, la respuesta está usted a favor de sólo tendrán sentido para UIViewControllers. Si estamos hablando de una aplicación arbitraria de las clases definidas (como el OP explícitamente hace), usted simplemente no puede dar consejo general respecto a cuándo es el mejor para quitar un observador desde el centro de notificaciones. Y aun en el caso de un UIViewController descendiente, no sé, en general, si viewWillAppear:/viewWillDisappear: es realmente apropiado.
    • Tienes razón, mi texto para el comentario anterior no fue lo suficientemente exacta, lo siento. 🙂 Lo que traté de estado es que: Cuando se trabaja con ViewControllers, iOS7 y el ARCO (como muchos de nosotros hacemos hoy en día), podría ser mejor que hacer, por ejemplo, como se sugiere en RickiG la respuesta de que el uso de dealloc.

  2. 38

    Desde iOS 9 ya no es necesario quitar los observadores.

    En OS X 10.11 y iOS 9.0 NSNotificationCenter y
    NSDistributedNotificationCenter dejará de enviar notificaciones a
    registrado observadores que pueden ser desasignado.

    https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/index.html#10_11NotificationCenter

    • Puede ser que no enviará mensajes a los observadores, pero creo que va a mantener una fuerte referencia a ellos como yo lo entiendo. En ese caso, todos los observadores permanecerá en la memoria y producir una fuga. Me corrija si estoy equivocado.
    • La documentación vinculada entra en detalles acerca de eso. TL;DR: es una referencia débil.
    • pero, por supuesto, todavía es necesario en caso de que usted mantenga el objeto de hacer referencia a ellas de todo y simplemente no quieren escuchar las notificaciones más
  3. 38

    Nota : Esto ha sido probado y funcionando al 100% por ciento

    Swift

    override func viewWillDisappear(animated: Bool){
        super.viewWillDisappear(animated)
    
        if self.navigationController!.viewControllers.contains(self) == false  //any other hierarchy compare if it contains self or not
        {
            //the view has been removed from the navigation stack or hierarchy, back is probably the cause
            //this will be slow with a large stack however.
    
            NSNotificationCenter.defaultCenter().removeObserver(self)
        }
    }

    PresentedViewController

    override func viewWillDisappear(animated: Bool){
        super.viewWillDisappear(animated)
    
        if self.isBeingDismissed()  //presented view controller
        {
            //remove observer here
            NSNotificationCenter.defaultCenter().removeObserver(self)
        }
    }

    Objective-C

    En iOS 6.0 > version , su mejor para eliminar observador en viewWillDisappear como viewDidUnload método está en desuso.

     [[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];

    Hay muchas veces que su mejor remove observer cuando la vista se ha quitado de la navigation stack or hierarchy.

    - (void)viewWillDisappear:(BOOL)animated{
     if (![[self.navigationController viewControllers] containsObject: self]) //any other hierarchy compare if it contains self or not
        {
            //the view has been removed from the navigation stack or hierarchy, back is probably the cause
            //this will be slow with a large stack however.
    
            [[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
        }
    }

    PresentedViewController

    - (void)viewWillDisappear:(BOOL)animated{
        if ([self isBeingDismissed] == YES) ///presented view controller
        {
            //remove observer here
            [[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
        }
    }
    • A excepción de un controlador posible que aún desea recibir notificaciones cuando su opinión es no mostrando (por ejemplo, para cargar un formato tableview).
    • automáticamente recargar/actualizar en viewWillAppear:
    • puede usted explicar por qué viewWillDisapper mejor dealloc? así que hemos añadido observador a sí mismo, así que cuando el auto se bajó de la memoria que se llame dealloc y, a continuación, todos los observadores serán eliminados, no es esto una buena lógica.
    • Llamar removeObserver:self en cualquiera de los UIViewController eventos del ciclo de vida es casi seguro que a la ruina de su semana. Leer más: subjective-objective-c.blogspot.com/2011/04/…
    • Poner el removeObserver llamadas en viewWillDisappear como se indica es definitivamente el camino a seguir si el controlador está siendo presentado a través de pushViewController. Si se les pone en dealloc lugar, a continuación, dealloc nunca será llamada; en mi experiencia de al menos…
    • cómo hacer lo mismo en swift sin tipo de fundición [auto.navigationController viewControllers] para NSArray ??
    • La EDICIÓN de lo que sugiere la comprobación de la jerarquía de navegación para el controlador es la solución perfecta para @wcochran punto. Muy útil

  4. 25

    Si el observador se agrega a una controlador de vista de, recomiendo agregarlo en viewWillAppear y la eliminación en viewWillDisappear.

    • Tengo curiosidad, @RickiG: ¿por qué recomienda el uso de viewWillAppear y viewWillDisappear para viewControllers?
    • un par de razones: la configuración de seguridad de código (por ejemplo. loadView y viewDidLoad) podría causar las notificaciones a ser despedido y su controlador necesario pensar que antes de la muestra. Si se hace así, hay algunos de los beneficios. En el momento en que decidió «dejar» el controlador no se preocupan por las notificaciones y que no se hará hacer de la lógica, mientras que el controlador está siendo empujado fuera de la pantalla, etc. Hay casos especiales en los que el controlador debe recibir notificaciones cuando está fuera de la pantalla, supongo que no se puede hacer esto. Pero eventos como el que probablemente debería estar en su modelo.
    • también con ARCO sería raro para implementar dealloc para anular la suscripción a las notificaciones.
    • De aquellos que lo he intentado, con iOS7 esta es la mejor manera de registrar o quitar los observadores cuando se trabaja con UIViewControllers. El único inconveniente es que, en muchos casos, usted no desea que el observador a ser eliminado cuando el uso de UINavigationController y empujar a otro UIViewController a la pila. Solución: puede verificar si la VC es que se hizo estallar en viewWillDisappear llamando a [auto isBeingDismissed].
    • Hacer estallar el controlador de vista de la navegación controlador no puede causar dealloc a ser llamado inmediatamente. Volviendo a la vista controlador, puede ocurrir que varias notificaciones si el observador se agrega en los comandos de inicialización.
  5. 19
    -(void) dealloc {
          [[NSNotificationCenter defaultCenter] removeObserver:self];
          [super dealloc];
    }
    • Me gustaría gire el orden de estas instrucciones de alrededor de… el Uso de self después de [super dealloc] me pone nervioso… (incluso si el receptor es improbable que el hecho de eliminar el puntero en cualquier forma, bueno, nunca se sabe, cómo se implementa NSNotificationCenter)
    • Hm. se ha trabajado para mí. ¿Ha notado algún comportamiento inusual ?
    • Nope. Esto fue sólo una observación general. Se siente como el uso de una malloc ed puntero después de la llamada a free a mí…
    • Dirk es correcto-esto es incorrecto. [super dealloc] debe estar siempre en el última declaración de su dealloc método. Destruye su objeto; después de que se ejecuta, usted no tiene una validez self más. /cc @Dirk
    • Hey dude. Así que usted está seguro acerca de esto ? Así que usted está diciendo que todos los dealloc declaraciones no funcionan (o) no significa nada, si lo hago de esta manera ?
    • Se puede trabajar la mayoría del tiempo, pero no están seguros.
    • Bueno, sí. Ellos han trabajado para mí hasta ahora. Permítanme tratar de cambiar las cosas en tu camino. Pueden ser estas fueron las razones de la memory leaks
    • Si el uso del ARCO en iOS 5+, creo que [super dealloc] ya no es necesaria
    • más fuerte, no está permitido bajo el ARCO para llamar a [super dealloc]
    • Por lo tanto, es todavía necesario para removeObserver en dealloc el uso de ARCO ?
    • Su ok para poner allí. Usted necesita básicamente lugar en la que se basa en el ciclo de vida de la VC. viewDidDisappear es un buen lugar.
    • su hasta usted. usted puede quitar en viewWillDisapper o en viewDidDisapper métodos.
    • Es mejor aún, para quitar observador en dealloc, pero sin la llamada a super obviamente (se realiza de forma automática por ARCO).

  6. 7

    En swift uso deinit porque dealloc no está disponible:

    deinit {
        ...
    }

    Documentación de Swift:

    Un deinitializer se llama inmediatamente antes de una instancia de una clase es
    desasignado. Escribir deinitializers con el deinit palabra clave, similar
    cómo intializers se escriben con el inicio de la palabra clave. Deinitializers
    sólo están disponibles en los tipos de clase.

    Normalmente no es necesario realizar el manual de limpieza cuando su
    las instancias se cancela la asignación. Sin embargo, cuando estás trabajando con tu propio
    recursos, usted puede ser que necesite para realizar algunas adicional de limpieza
    a ti mismo. Por ejemplo, si crea una clase personalizada para abrir un archivo y
    escribir algunos datos, usted puede ser que necesite para cerrar el archivo antes de la
    instancia de la clase se cancela la asignación.

  7. 5

    *editar: Este consejo se aplica a iOS <= 5 (incluso no se debe añadir en viewWillAppear y extracción en viewWillDisappear – sin embargo, el consejo se aplica si por alguna razón se le ha añadido el observador en viewDidLoad)

    Si has añadido el observador en viewDidLoad usted debe eliminar lo tanto dealloc y viewDidUnload. Lo contrario va a terminar la adición de dos veces cuando viewDidLoad se llama después de que viewDidUnload (esto ocurrirá después de una advertencia memoria). Esto no es necesario en iOS 6, donde viewDidUnload es obsoleto y no será llamado (debido a las vistas son ya no descarga automáticamente).

    • Bienvenido a StackOverflow. Por favor, compra la Rebaja FAQ (preguntas-ícono de la marca junto a la pregunta/respuesta de edición). El uso de Markdwon va a mejorar la usabilidad de tu respuesta.
  8. 5

    En mi opinión, el siguiente código no tiene sentido en el ARCO:

    - (void)dealloc
    {
          [[NSNotificationCenter defaultCenter] removeObserver:self];
          [super dealloc];
    }

    En iOS 6, además no hay sentido en la eliminación de los observadores en viewDidUnload, porque se ha quedado obsoleto ahora.

    Para resumir, siempre lo hago en viewDidDisappear. Sin embargo, depende de sus necesidades también, al igual que @Dirk dijo.

    • Hay mucha gente que se sigue escribiendo código para las versiones anteriores de iOS de iOS6…. 🙂
    • En el ARCO que usted puede utilizar este código pero sin la línea [super dealloc]; puedes ver más aquí: developer.apple.com/library/ios/#releasenotes/ObjectiveC/…
    • ¿Qué pasa si usted tenía un regular NSObject ser el observador de una notificación? Se debe utilizar el dealloc en este caso?
  9. 4

    Creo que he encontrado una respuesta fiable! Tuve, como las respuestas anteriores son ambiguos y parecen contradecirse. Miré a través de Libros de cocina y Guías de Programación.

    Primer lugar, el estilo de addObserver: en viewWillAppear: y removeObserver: en viewWillDisappear: no me funciona (lo he comprobado) porque estoy publicando una notificación en un niño de controlador de vista de ejecutar código en la vista principal del controlador. Yo sólo uso este estilo si yo estaba publicando y escuchando la notificación dentro del mismo controlador de vista.

    La respuesta voy a confiar en la mayoría de los encontré en la Programación en iOS: Big Nerd Ranch Guía de 4º. Confío en que el BNR los chicos porque ellos tienen iOS centros de formación y que no sólo escribir otro libro de cocina. Probablemente es en su mejor interés para ser exactos.

    BNR ejemplo uno: addObserver: en init:, removeObserver: en dealloc:

    BNR ejemplo dos: addObserver: en awakeFromNib:, removeObserver: en dealloc:

    …cuando la eliminación de observador en dealloc: no uso [super dealloc];

    Espero que esto ayude a la siguiente persona…

    Estoy actualizando este post debido a que Apple tiene ahora casi desaparecido por completo con los Storyboards para las arriba mencionadas pueden no aplicarse a todas las situaciones. Lo importante (y la razón por la que he añadido este post en primer lugar) es prestar atención si su viewWillDisappear: está recibiendo la llamada. No era para mí cuando la aplicación se entró en el fondo.

    • Es difícil decir si esto es correcto, el contexto es importante. Se menciona un par de veces ya, pero dealloc tiene poco sentido en un ARCO de contexto (que es el único contexto por ahora). Tampoco es predecible cuando dealloc se llama – viewWillDisappear es más fácil de controlar. Nota: Si su hijo necesita comunicar algo a su padre el patrón de delegado suena como una mejor opción.
  10. 2

    La aceptada respuesta no es seguro y podría causar una fuga de memoria. Por favor, deje el unregister en dealloc pero también darse de baja en viewWillDisappear (que es, por supuesto, si usted se registra en viewWillAppear)….ESO ES LO QUE HIZO DE TODOS MODOS Y FUNCIONA MUY BIEN! 🙂

    • Estoy de acuerdo con esta respuesta. Tengo la experiencia de la memoria de las advertencias y de las fugas que conducen a los accidentes después de un uso intensivo de la aplicación, si no me quite los observadores en viewWillDisappear.
  11. 2

    Es importante también notar que viewWillDisappear se llama también cuando el controlador de vista de presentar un nuevo UIView. Este delegado, simplemente indicar que el controlador de vista de principal punto de vista no es visible en la pantalla.

    En este caso, la cancelación de la asignación de la notificación del viewWillDisappear puede ser un inconveniente si estamos usando la notificación para permitir que el UIview a comunicarse con los padres de controlador de vista.

    Como solución me suele quitar el observador en uno de estos dos métodos:

    - (void)viewWillDisappear:(BOOL)animated {
        NSLog(@"viewController will disappear");
        if ([self isBeingDismissed]) {
            NSLog(@"viewController is being dismissed");
            [[NSNotificationCenter defaultCenter] removeObserver:self name:@"actionCompleted" object:nil];
        }
    }
    
    -(void)dealloc {
        NSLog(@"viewController is being deallocated");
        [[NSNotificationCenter defaultCenter] removeObserver:self name:@"actionCompleted" object:nil];
    }

    Por razones similares, cuando me emitir la notificación en el primer tiempo, es necesario tener en cuenta el hecho de que en cualquier momento una vista con aparecer por encima de la controladora viewWillAppear método es despedido. Esto a su vez generar varias copias de la misma notificación. Puesto que no hay una forma de comprobar si una notificación ya está activo, me obviar el problema mediante la eliminación de la notificación antes de añadir:

    - (void)viewWillAppear:(BOOL)animated {
        NSLog(@"viewController will appear");
        //Add observers
        [[NSNotificationCenter defaultCenter] removeObserver:self name:@"imageGenerated" object:nil]; //This is added to avoid duplicate notifications when the view is presented again
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedImageFromCameraOrPhotolibraryMethodOnListener:) name:@"actionCompleted" object:nil];
    
    }
  12. -1

    SWIFT 3

    Hay dos casos de uso de notificaciones:
    – ellos sólo son necesarios cuando el controlador de vista está en la pantalla;
    – son necesarios siempre, incluso si el usuario abre otra pantalla más actual.

    Para el primer caso el lugar correcto para agregar y quitar observador son:

    ///Add observers
    ///
    ///- Parameter animated: the animation flag
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        NotificationCenter.default.addObserver(...)
    }
    
    ///Remove observers
    ///
    ///- Parameter animated: the animation flag
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        NotificationCenter.default.removeObserver(self)
    }

    para el segundo caso, la forma correcta es:

    ///Add observers
    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(...)
    }
    
    ///Remove observers
    ///
    ///- Parameter animated: the animation flag
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        if self.isBeingDismissed //remove only when view controller is removed disappear forever
        || !(self.navigationController?.viewControllers.contains(self) ?? true) {
            NotificationCenter.default.removeObserver(self)
        }
    }

    Y nunca poner removeObserver en deinit{ ... } – es un ERROR!

  13. -1
    override func viewDidLoad() {   //add observer
      super.viewDidLoad()
      NotificationCenter.default.addObserver(self, selector:#selector(Yourclassname.method), name: NSNotification.Name(rawValue: "NotificationIdentifier"), object: nil)
    }
    
    override func viewWillDisappear(_ animated: Bool) {    //remove observer
        super.viewWillDisappear(true)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "NotificationIdentifier"), object: nil)
    }

Dejar respuesta

Please enter your comment!
Please enter your name here