18 votos

Es el weakSelf/strongSelf bailar muy necesario cuando se hace referencia a la auto dentro de un no-retención de finalización de llamada de un UIViewController?

Decir que tengo el siguiente método en el interior de un UIViewController subclase:

- (void)makeAsyncNetworkCall
{
    [self.networkService performAsyncNetworkCallWithCompletion:^{
        dispatch_async(dispatch_get_main_queue(), ^{
                [self.activityIndicatorView stopAnimating];
            }
        });
    }];
}

Sé que la referencia a la self dentro del bloque de resultados en la UIViewController ejemplo de ser retenido por el bloque. Mientras performAsyncNetworkCallWithCompletion no almacena el bloque en una propiedad (o ivar) en mi NetworkService, estoy en lo cierto al pensar que no hay retener ciclo?

Me doy cuenta de esta estructura anterior conducirá a la UIViewController que se conserva hasta performAsyncNetworkCallWithCompletion acabados, incluso si es liberado por el sistema anterior. Pero es probable (o incluso posible?) el sistema desasignar mi UIViewController en todo (después de los cambios en el estilo de iOS 6 gestiona UIViewController's soporte CALayer de memoria)?

Si hay una razón por la que tengo que hacer el "weakSelf/strongSelf de la danza", que se vería así:

- (void)makeAsyncNetworkCall
{
    __weak typeof(self) weakSelf = self;
    [self.networkService performAsyncNetworkCallWithCompletion:^{
        typeof(weakSelf) strongSelf = weakSelf;
        if (!strongSelf) {
            return;
        }
        dispatch_async(dispatch_get_main_queue(), ^{
                [strongSelf.activityIndicatorView stopAnimating];
            }
        });
    }];
}

Pero me parece que este desmesuradamente feo y quisiera evitarlo si no es necesario.

11voto

Rob Puntos 70987

Como creo que se diagnostica correctamente, usando self no necesariamente son la causa de un fuerte ciclo de referencia en este escenario. Pero esto va a conservar la vista controlador, mientras que la operación de la red completa, y en este caso (como en la mayoría de los casos), no es necesario. Por lo tanto, puede no ser necesario hacer uso weakSelf, pero probablemente sea prudente hacerlo. Se minimiza la posibilidad de un choque accidental de referencia fuerte ciclo y conduce a un uso más eficiente de la memoria (la liberación de la memoria asociada con el controlador de vista tan pronto como el controlador de vista es despedido en lugar de retener innecesariamente el controlador de vista hasta después de la operación de la red).

No hay ninguna necesidad de la strongSelf construir, aunque. Usted puede:

- (void)makeAsyncNetworkCall
{
    __weak typeof(self) weakSelf = self;
    [self.networkService performAsyncNetworkCallWithCompletion:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [weakSelf.activityIndicatorView stopAnimating];
        });
    }];
}

Sólo se necesita el weakSelf/strongSelf combinación donde es fundamental contar con una fuerte referencia (por ejemplo, usted está de eliminar ivars) o si usted necesita preocuparse acerca de las condiciones de carrera. Que no parece ser el caso aquí.

3voto

Abizern Puntos 52378

Creo que el problema es que la networkService puede mantener una fuerte referencia al bloque. Y el controlador de vista puede tener un fuerte referencia a la networkService. Por lo que el posible ciclo de VC->servicio de red->bloque->VC podría existir. Sin embargo, en este caso, generalmente, es seguro asumir que el bloque se dará a conocer después de que se ha ejecutado, en cuyo caso el ciclo se rompe. Así, en este caso, no es necesario.

Donde es necesario es si el bloque no está liberado. Decir, en lugar de tener un bloque que se ejecuta una vez, después de una llamada de red, tiene un bloque que se utiliza como una devolución de llamada. es decir, la networkService objeto mantiene una fuerte referencia a la cuadra y se utiliza para todas las devoluciones de llamada. En este caso, el bloque tendrá una fuerte referencia a la VC, y esto va a crear un fuerte ciclo, por lo que una referencia débil es el preferido.

1voto

nanjunda Puntos 604

No, Si su auto.networkService no lo utilice como un bloque de propiedad que debe estar bien

0voto

mbpro Puntos 606

La respuesta no es tan sencillo. Estoy de acuerdo con @Rob respuesta, pero necesita más explicación:

  1. __weak es considerado como una forma segura, ya que nils el auto cuando se libera, lo que significa que no habrá excepción de devolución de llamada si ocurre mucho más tarde, cuando el objeto de llamada ya está lanzado, hace referencia a bloque, como UIViewController de estallar de la pila. La adición de la posibilidad de anular cualquier tipo de operación, es meramente una cuestión de higiene y quizás también los recursos. Usted puede, por ejemplo, también acaba de cancelar NSURLConnection, no solo la de NSOperation que puede ser cancelada, usted puede cancelar ser cualquier cosa que se ejecutan de forma asíncrona en el método que llama a volver a bloquear.

  2. Si el auto es dejar de ser retenida por el bloque, entonces, la historia puede ser un poco complicado si la persona que llama objeto como, por ejemplo UIViewController está siendo editado por UINavigationController y el bloque aún conserva y llama de nuevo. En este caso de devolución de llamada de bloque será ejecutado y asumió algunos datos serán cambiados por los resultados de la misma. Que podría ser incluso quería comportamiento, pero en la mayoría de los casos no. Por lo tanto, la anulación de la operación puede ser más vital en este caso, por lo que es muy sabio en UINavigationControllerDelegate métodos por la anulación de las tareas asincrónicas de la mutable de la colección que residen en UINavigationController como objeto asociado o como un singleton.

Guardar la apuesta es con la primera opción, por supuesto, pero sólo en el caso de que no quieras operación asincrónica para continuar después de despedir a la persona que llama objeto.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X