objective c - Tipo genérico para auto referencias débiles
objective-c cocoa (10)
Referencia de Weakself genérica (no se requiere importación + fragmento)
En mi experiencia, el camino a seguir es usar:
__typeof__(self) __weak weakSelf = self;
Observe cómo el calificador de propiedad pertenece al frente de la variable real.
Es muy evidente lo que sucede cuando se usa y se puede convertir en un práctico fragmento de código en Xcode, lo que hace que sea aún más fácil de usar en cualquier proyecto o clase donde sea necesario. (Uso "ws" como atajo de finalización del fragmento)
Hmm ... Necesito una referencia débil aquí ...
ws{return}
Hecho. No es necesario incluir un encabezado en futuros proyectos para esto, solo use el fragmento.
Fragmento de Xcode
Título: Generic Weak Self Reference
Plataforma: All
Idioma: Objective-C
Atajo de finalización: ws
Alcance de finalización: Function or Method
Código: __typeof__(self) __weak weakSelf = self;
Editar: se agregó una nota sobre la posición del calificador de propiedad en función de los comments , y Xcode Snippet Info
Estoy tratando de encontrar una manera de usar typeof
para crear una referencia débil a self
para usar en bloques para evitar retener ciclos.
Cuando leí por primera vez acerca de esto, parece que la convención era usar __block typeof(self) bself = self;
, que compila pero usa __block
para evitar retener ciclos ya no funciona y __weak
debería usarse en su lugar.
Sin embargo, __weak typeof(self) bself = self;
resulta en un error:
El tipo ''typeof (self)'' (también conocido como ''TUAccountsViewController * const __strong'') ya tiene atributos de retención establecidos
¿Hay alguna manera de usar typeof
u otra llamada para crear genéricamente una referencia débil a self
?
¡Esto funciona!
__typeof__(o) __weak
Que he definido en mi proyecto de BBlockWeakSelf
como BBlockWeakSelf
que se puede usar así:
BBlockWeakSelf wself = self;
https://github.com/kgn/BBlock/blob/master/BBlock.h
Editado basado en la respuesta de Aleph7.
¿Por qué no solo usas
__weak id bself = self;
¿Qué hay de __unsafe_unretained? Eso no es tan seguro como __weak, pero es lo único que se me ocurre. Además, ¿por qué usas typeof ()?
Creo que usa esto para estar bien:
__weak __typeof (& * self) weakSelf = self;
hace referencia a los códigos AFURLConnectionOperation.m de AFNetworking.
En la última versión clang Apple clang versión 4.0 (etiquetas / Apple / clang-421.1.48) (basado en LLVM 3.1svn) , es decir Xcode 4.4+ , el __typeof__((__typeof__(self))self)
no es necesario más. El tipo __weak typeof(self) bself = self;
la línea compilará muy bien.
La forma correcta de hacerlo es
__weak ActualClassName* weakSelf = self;
Las macros solo dejan en claro cuál es la variable en realidad, y qué es lo que realmente está haciendo con ella, además de agregar metalenguaje no portátil a su código.
Si necesita una versión más genérica de la clase de la que proporciona ActualClassName, ya no se trata de self
, ya que cuando se define self
, también lo es la clase de self
.
En esos casos, debe usar el nombre de clase base más cercano en su árbol de herencia, NSObject
o mejor, nunca id
, por ej.
__weak MyBaseClassName* weakObject = object;
Tengo esta macro
#define weaken(object) __typeof__(self) __weak weakSelf = object
Y lo uso así
weaken(self);
//The block referencing weakSelf goes here
Tuve un error similar pero lo solucioné de manera diferente:
Fui a Project Navigator -> Project -> Target -> Build Settings
Ahí busqué C Language Dialect. Lo cambié de c11 a GNU99 y resolvió mi problema.
Espero que ayude :)
declareBlockSafe (self) luego blk (self) dentro del bloque. El yo puede ser cualquier variable o variable de instancia. Utilice declareBlockSafeAs para las propiedades y los retornos de métodos.
También funciona con no ARC si importa el espléndido MAZeroingWeakRef de Mike Ash. https://github.com/mikeash/MAZeroingWeakRef
#if __has_feature(objc_arc)
#define declareBlockSafe(__obj__) __weak typeof(__obj__) __tmpblk##__obj__ = __obj__
#define blockSafe(__obj__) __tmpblk##__obj__
#define blk(__obj__) blockSafe(__obj__)
#define declareBlockSafeAs(__obj__, __name__) /
__weak typeof((__obj__)) __tmpblk##__name__ = (__obj__)
#else
#define declareBlockSafe(__obj__) MAZeroingWeakRef *__tmpblk##__obj__ = [MAZeroingWeakRef refWithTarget:__obj__]
#define blockSafe(__obj__) ((typeof(__obj__))__tmpblk##__obj__##.target)
#define blk(__obj__) blockSafe(__obj__)
#define declareBlockSafeAs(__obj__, __name__) /
MAZeroingWeakRef *__tmpblk##__name__ = (__obj__)
#endif
REALMENTE no necesita blk () para ARC, es solo para que las macros se puedan usar de la misma manera para las que no sean ARC.