J'essaie de trouver un moyen d'utiliser typeof
pour créer une référence faible à self
à utiliser dans les blocs pour éviter les cycles de conservation.
Quand j'ai lu pour la première fois à ce sujet, il semble que la convention était d'utiliser __block typeof(self) bself = self;
, qui compile mais en utilisant __block
Pour éviter les cycles de rétention ne fonctionne plus et __weak
Devrait être utilisé à la place.
Cependant __weak typeof(self) bself = self;
entraîne une erreur:
Le type 'typeof (self)' (aka 'TUAccountsViewController * const __strong') a déjà des attributs de rétention définis
Existe-t-il un moyen d'utiliser typeof
ou un autre appel pour créer génériquement une référence faible à self
?
Cela marche!
__typeof__(o) __weak
Que j'ai défini dans mon projet BBlock comme BBlockWeakSelf
qui peut être utilisé comme ceci:
BBlockWeakSelf wself = self;
https://github.com/kgn/BBlock/blob/master/BBlock.h
Modifié sur la base de la réponse d'Aleph7.
Dans la dernière version de clang Apple clang version 4.0 (tags/Apple/clang-421.1.48) (basé sur LLVM 3.1svn) , c'est-à-dire Xcode 4.4 +, l'astuce __typeof__((__typeof__(self))self)
n'est plus nécessaire. La ligne __weak typeof(self) bself = self;
se compilera très bien.
La bonne façon de procéder est
__weak ActualClassName* weakSelf = self;
Les macros ne permettent pas de savoir exactement ce qu'est la variable et ce que vous faites réellement avec elle, en plus d'ajouter un méta-langage non portable à votre code.
Si vous avez besoin d'une version plus générique de la classe que celle fournie par ActualClassName, vous ne traitez plus avec self
, puisque où self
est défini, tout comme la classe de self
défini.
Dans ces cas, vous devez utiliser le nom de classe de base le plus proche dans votre arbre d'héritage, NSObject
ou mieux, jamais id
, par exemple.
__weak MyBaseClassName* weakObject = object;
D'après mon expérience, la voie à suivre consiste à utiliser:
__typeof__(self) __weak weakSelf = self;
Notez comment le qualificatif de propriété appartient devant la variable réelle.
Il est très évident de savoir ce qui se passe lorsqu'il est utilisé et il peut être transformé en un extrait de code pratique dans Xcode, ce qui le rend encore plus facile à utiliser dans n'importe quel projet ou classe où cela est nécessaire. (J'utilise "ws" comme raccourci de fin de l'extrait)
Hmm .. J'ai besoin d'une référence faible ici ..
ws{return}
Terminé. Pas besoin d'inclure un en-tête dans les futurs projets pour cela, utilisez simplement l'extrait de code.
Titre: Generic Weak Self Reference
Plateforme: All
Langue: Objective-C
Raccourci de fin: ws
Portées d'achèvement: Function or Method
Code: __typeof__(self) __weak weakSelf = self;
Modifier: Ajout d'une note sur la position du qualificatif de propriété basée sur commentaires et les informations d'extrait de code X
je pense que cela doit être utilisé:
__weak __typeof (& * self) faiblesSelf = self;
il fait référence aux codes AFURLConnectionOperation.m d'AFNetworking.
pourquoi ne pas simplement utiliser
__weak id bself = self;
Avez-vous essayé de vérifier le dialecte de la langue C?
Allez dans Project Navigator -> Project -> Target -> Build Settings
Là, recherchez le dialecte du langage C. Changez-le de c11 à GNU99.
J'espère que ça aide :)
J'ai cette macro
#define weaken(object) __typeof__(self) __weak weakSelf = object
Et je l'utilise comme ça
weaken(self);
//The block referencing weakSelf goes here
declareBlockSafe (self) puis blk (self) à l'intérieur du bloc. Self peut être n'importe quelle variable ou variable d'instance. Utilisez declareBlockSafeAs pour les propriétés et les retours de méthode.
Fonctionne également avec non-ARC si vous importez le splendide 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
</code>
Vous n'avez VRAIMENT pas besoin de blk () pour ARC, c'est juste pour que les macros puissent être utilisées de la même manière pour non-ARC.
Qu'en est-il de __unsafe_unretained? Ce n'est pas aussi sûr que __weak mais c'est la seule chose à laquelle je pouvais penser. Aussi, pourquoi utilisez-vous typeof ()?