¿Cómo puedo evitar esta advertencia en xcode. Aquí está el fragmento de código:

[player(AVPlayer object) addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(0.1, 100)
queue:nil usingBlock:^(CMTime time) {
    current+=1;

    if(current==60)
    {
        min+=(current/60);
        current = 0;
    }

    [timerDisp(UILabel) setText:[NSString stringWithFormat:@"%02d:%02d",min,current]];///warning occurs in this line
}];
  • Es timerDisp una propiedad en la clase?
  • Sí, @property(nonatomic,fuerte)UILabel *timerDisp;
  • ¿Qué es esta: player(AVPlayer object) y timerDisp(UILabel)?
  • AVPlayer *el jugador; UILabel *timerDisp;
  • La verdadera pregunta es cómo silenciar esta advertencia, sin la innecesaria referencia débil en el auto, cuando usted sabe la referencia circular se rompe (por ejemplo. si usted siempre es clara la referencia a la hora de una solicitud de red acabados).
InformationsquelleAutor user1845209 | 2013-01-28

7 Comentarios

  1. 508

    La captura de self aquí es llegar con su implícito de acceso a la propiedad de self.timerDisp – usted no puede referirse a self o propiedades en self desde dentro de un bloque que será fuertemente retenido por self.

    Usted puede evitar esto mediante la creación de una débil referencia a self antes de acceder a timerDisp en el interior de su bloque:

    __weak typeof(self) weakSelf = self;
    [player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(0.1, 100)
                                         queue:nil
                                    usingBlock:^(CMTime time) {
                                                    current+=1;
    
                                                    if(current==60)
                                                    {
                                                        min+=(current/60);
                                                        current = 0;
                                                    }
    
                                                     [weakSelf.timerDisp setText:[NSString stringWithFormat:@"%02d:%02d",min,current]];
                                                }];
    • __débiles typeof(auto) weakSelf = auto;…le está dando error «el actual despliegue de destino no admite automatizado __referencias débiles»…mi objetivo de implementación es de 4,3
    • Trate de usar __unsafe_unretained lugar.
    • Resuelto. el uso de este lugar: __inseguro_bien typeof(auto) weakSelf = auto; gracias fo la ayuda de @Tim
    • Buena respuesta, pero me tome pequeño problema con usted diciendo: «usted no puede referirse a sí mismo o a propiedades en auto desde dentro de un bloque que será fuertemente retenido por sí mismo.» Esto no es estrictamente cierto. Por favor vea mi respuesta a continuación. Mejor decir, «tú debe tener mucho cuidado si se refiere a sí mismo…»
    • No veo una retener ciclo en el OP del código. El bloque no es fuertemente retenido por self, es retenido por el principal despacho de la cola. Estoy equivocado?
    • Es necesario, incluso con ARCO?
    • no se equivoca. Yo interpreté la pregunta que se debe, principalmente, sobre el error de Xcode presenta («¿Cómo puedo evitar esta advertencia en xcode»), en lugar de hablar de la presencia actual de una retener ciclo. Usted está en lo correcto al decir que no retener el ciclo es evidente desde el fragmento de código de OP de siempre.
    • sí, esto es necesario en el ARCO.
    • Veo, gracias. El efecto neto es similar, mientras que el principal despacho de la cola mantiene el bloque de self no se puede cancelar. En el caso de addPeriodicTimeObserverWithTimeInterval:, es posible que un bloque que conserva self a estar en la cola de espera antes de que el bloque anterior, que conserva la self se ejecuta, la creación tanto de una retener ciclo, pero en un estado permanente de self que se conserva.
    • Si utilizo __débiles typeof(auto) weakSelf = auto; entonces todas las propiedades de este objeto será NULO.
    • Esto me ha ayudado a stackoverflow.com/questions/7205128/…
    • pregunta de seguimiento: stackoverflow.com/questions/18831460/…
    • Lo que si hizo typeof(self) strongSelf = self; fuera del bloque (en lugar de __débiles), a continuación, en el bloque, dijo strongSelf = nil; después de uso?
    • En mi proyecto de ejemplo, no se ve como que va a evitar esta advertencia. Tenga en cuenta, sin embargo, que todavía están temporalmente el establecimiento de una retener el ciclo desde su strongSelf es (como dicen ustedes) fuerte, self y el bloque de retener el uno al otro. Configuración de strongSelf a nil debe romper el ciclo, sin embargo. Si este método se aplica a su situación se deja a la discreción individual.
    • En la mayoría de los casos se debe usar sólo uno o un par de miembros de self en este bloque, más probable es que simplemente a la actualización de un control deslizante. Casting self es una exageración, mejor ser explícita (cast solo los objetos que realmente necesitan en el bloque. Por ejemplo, si es una instancia de UISlider*, dicen, _timeSlider, acaba de hacer el siguiente antes de que el bloque de declaración: UISlider* __weak slider = _timeSlider; utilice sólo slider dentro del bloque. Técnicamente esto es más precisos a medida que se reduce el potencial de retener el ciclo de sólo el objeto que necesitas, no todos los objetos dentro de self
    • Funciona. ios9.2
    • Usted puede utilizar esta así: __débiles __typeof(&*auto)weakSelf = auto;

  2. 52
    __weak MyClass *self_ = self; //that's enough
    self.loadingDidFinishHandler = ^(NSArray *receivedItems, NSError *error){
        if (!error) {
           [self_ showAlertWithError:error];
        } else {
           self_.items = [NSArray arrayWithArray:receivedItems];
           [self_.tableView reloadData];
        }
    };

    Y una cosa muy importante a recordar:
    no utilice variables de instancia directamente en el bloque, lo utiliza como una de las propiedades de la debilidad de objeto, ejemplo:

    self.loadingDidFinishHandler = ^(NSArray *receivedItems, NSError *error){
            if (!error) {
               [self_ showAlertWithError:error];
            } else {
               self_.items = [NSArray arrayWithArray:receivedItems];
               [_tableView reloadData]; //BAD! IT ALSO WILL BRING YOU TO RETAIN LOOP
            }
     };

    y no te olvides de hacer:

    - (void)dealloc {
        self.loadingCompletionHandler = NULL;
    }

    otro problema puede aparecer si usted va a pasar débil copia de la que no se conservan por cualquier objeto:

    MyViewController *vcToGo = [[MyViewCOntroller alloc] init];
    __weak MyViewController *vcToGo_ = vcToGo;
    self.loadingCompletion = ^{
        [vcToGo_ doSomePrecessing];
    };

    si vcToGo se cancela la asignación y, a continuación, en este bloque se despidió creo que obtendrá accidente con desconocidos selector de basura que contiene vcToGo_ variable de ahora. Tratar de controlarlo.

    • Esta sería una respuesta más fuerte si usted también lo explican.
  3. 41

    Mejor versión

    __strong typeof(self) strongSelf = weakSelf;

    Crear una fuerte referencia a la versión débil como la primera línea en su bloque. Si el auto todavía existe cuando el bloque se empieza a ejecutar y no ha vuelto a cero, esta línea asegura que persiste a lo largo del bloque de la ejecución de toda la vida.

    Así que todo sería como este:

    //Establish the weak self reference
    __weak typeof(self) weakSelf = self;
    
    [player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(0.1, 100)
                                     queue:nil
                                usingBlock:^(CMTime time) {
    
        //Establish the strong self reference
        __strong typeof(self) strongSelf = weakSelf;
    
        if (strongSelf) {
            [strongSelf.timerDisp setText:[NSString stringWithFormat:@"%02d:%02d",min,current]];
        } else {
            //self doesn't exist
        }
    }];

    He leído este artículo muchas veces. Este es un excelente artículo por Erica Sadun en
    Cómo Evitar Problemas Al Usar Bloques Y NSNotificationCenter


    Swift actualización:

    Por ejemplo, en swift un método sencillo con éxito bloque sería:

    func doSomeThingWithSuccessBlock(success: () -> ()) {
        success()
    }

    Cuando llamamos a este método y la necesidad de utilizar self en el éxito de bloque. Vamos a utilizar el [weak self] y guard let características.

        doSomeThingWithSuccessBlock { [weak self] () -> () in
            guard let strongSelf = self else { return }
            strongSelf.gridCollectionView.reloadData()
        }

    Este llamado fuerte-débil baile es utilizado por el popular proyecto de código abierto Alamofire.

    Para obtener más información, echa un vistazo swift-estilo-guía

    • Lo que si hizo typeof(self) strongSelf = self; fuera del bloque (en lugar de __débiles), a continuación, en el bloque, dijo strongSelf = nil; después de uso? No veo la manera de que su ejemplo se asegura de que weakSelf no es nulo en el momento en que el bloque se ejecuta.
    • Para evitar la posible retener ciclos, de establecer una débil auto de referencia fuera de cualquier bloque que utiliza el auto en su código. En ur manera, la u tiene que asegurarse de que el bloque se ejecuta. Otro bloque de código de ur es ahora responsable de liberar ur previamente retenidas de la memoria.
    • el propósito de este ejemplo no es hacer el weakSelf retenido. El propósito es, si el weakSelf no es nil, hacer una referencia fuerte en el interior del bloque. Así que una vez que el bloque comienza a ejecutar con el auto, el auto no se convierta en nulo en el interior del bloque.
  4. 15

    En otra respuesta, Tim dijo:

    usted no puede referirse a sí mismo o a propiedades en auto desde dentro de un bloque que será fuertemente retenido por sí mismo.

    Esto no es del todo cierto. Está bien para que usted pueda hacer esto tan largo como romper el ciclo en algún momento. Por ejemplo, digamos que usted tiene un temporizador que se activa que tiene un bloque que conserva auto y también mantener una fuerte referencia para el temporizador de auto. Esto está perfectamente bien si usted siempre sabe que va a destruir el temporizador en algún momento y romper el ciclo.

    En mi caso ahora mismo, yo tenía esta advertencia para el código que hice:

    [x setY:^{ [x doSomething]; }];

    Ahora, sé que sonar sólo producirá esta advertencia si detecta el método comienza con «set» (y un otro caso especial que no voy a mencionar aquí). Para mí, sé que no hay peligro de que hay una retener bucle, así que he cambiado el nombre del método a «useY:» por supuesto, que no puede ser apropiado en todos los casos y por lo general, usted querrá usar una referencia débil, pero he pensado que vale la pena destacar que mi solución en caso de que ayuda a los demás.

  5. 3

    Muchas veces, esto no es en realidad una retener ciclo.

    Si usted sabe que no, usted no necesita traer infructuoso weakSelves en el mundo.

    De Apple, incluso de las fuerzas de estas advertencias sobre nosotros con la API para su UIPageViewController, que incluye un método de juego de (lo que desencadena estas advertencias–como se menciona en otra parte–de pensar que eres el establecimiento de un valor a una ivar que es un bloque) y un controlador de finalización de bloque (en el que sin duda va a referirse a sí mismo).

    He aquí algunas directivas de compilador para quitar la advertencia de que una línea de código:

    #pragma GCC diagnostic push
    #pragma clang diagnostic ignored "-Warc-retain-cycles"
        [self.pageViewController setViewControllers:@[newViewController] direction:navigationDirection animated:YES completion:^(BOOL finished) {
            //this warning is caused because "setViewControllers" starts with "set…", it's not a problem
            [self doTheThingsIGottaDo:finished touchThePuppetHead:YES];
        }];
    #pragma GCC diagnostic pop
  6. 1

    La adición de dos centavos en la mejora de la precisión y estilo. En la mayoría de los casos se debe usar sólo uno o un par de miembros de self en este bloque, más probable es que simplemente a la actualización de un control deslizante. Casting self es una exageración. En su lugar, es mejor ser explícita (cast sólo los objetos que usted realmente necesita en el interior del bloque. Por ejemplo, si es una instancia de UISlider*, dicen, _timeSlider, acaba de hacer el siguiente antes de que el bloque de declaración:

    UISlider* __weak slider = _timeSlider;

    Utilice sólo slider dentro del bloque. Técnicamente esto es más precisos a medida que se reduce el potencial de retener el ciclo de sólo el objeto que usted necesita, no todos los objetos dentro de self.

    Ejemplo completo:

    UISlider* __weak slider = _timeSlider;
    [_embeddedPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 1)
         queue:nil
         usingBlock:^(CMTime time){
            slider.value = time.value/time.timescale;
         }
    ];

    Además, más probable es que el objeto de ser arrojado a un débil puntero es ya un débil puntero dentro de self así minimizar o eliminar por completo la probabilidad de retener el ciclo. En el ejemplo anterior, _timeSlider es en realidad una propiedad almacena como una referencia débil, e.g:

    @property (nonatomic, weak) IBOutlet UISlider* timeSlider;

    En términos de estilo de programación, como C y C++, declaraciones de variables son una mejor lectura de derecha a izquierda. Declarar SomeType* __weak variable en este orden de lecturas de la forma más natural de derecha a izquierda como: variable is a weak pointer to SomeType.

  7. 1

    Me encontré con esta advertencia recientemente y quería entender un poco mejor. Después de un poco de ensayo y error, he descubierto que se origina a partir de tener un método que empiezan con «agregar» o «guardar». Objetivo C trata método de nombres que comienzan con «nuevo», «asignación», etc como devolver un objeto retenido, pero no menciona (que puedo encontrar nada sobre «añadir» o «guardar». Sin embargo, si puedo usar un nombre de método de esta manera:

    [self addItemWithCompletionBlock:^(NSError *error) {
                [self done]; }];

    Voy a ver la advertencia en el [auto hecho] de la línea. Sin embargo, esto no:

    [self itemWithCompletionBlock:^(NSError *error) {
        [self done]; }];

    Voy a seguir adelante y utilizar el «__débiles __typeof(auto) weakSelf = auto» forma de hacer referencia a mi objeto, pero en realidad no te gusta tener que hacerlo, ya que confundir a un futuro conmigo y/o otras dev. Por supuesto, yo no podría también usar «añadir» (o «save»), pero que es peor, ya que quita el sentido del método.

Dejar respuesta

Please enter your comment!
Please enter your name here