web-dev-qa-db-fra.com

Type générique pour les auto-références faibles

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?

34
keegan3d

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.

32
keegan3d

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.

37
0xced

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;
18
Brane

Référence générique Weakself (aucune importation requise + extrait)


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.


Extrait Xcode


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

16
Beltalowda

je pense que cela doit être utilisé:

__weak __typeof (& * self) faiblesSelf = self;

il fait référence aux codes AFURLConnectionOperation.m d'AFNetworking.

3
kitsionchen

pourquoi ne pas simplement utiliser

__weak id bself = self;
3
Denis Mikhaylov

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 :)

2
Ricardo Anjos

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
1
Maciej Swic

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.

1
SeruK

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 ()?

0
lbrndnr