可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am trying to figure out a way to use typeof
to create a weak reference to self
for use in blocks to avoid retain cycles.
When I first read about this it seems that the convention was to use __block typeof(self) bself = self;
, which compiles but using __block
to avoid retain cycles doesn't work anymore and __weak
should be used instead.
However __weak typeof(self) bself = self;
results in an error:
The type 'typeof (self)' (aka 'TUAccountsViewController *const __strong') already has retainment attributes set on it
Is there a way to use typeof
or another call to generically create a weak reference to self
?
回答1:
In the latest clang version Apple clang version 4.0 (tags/Apple/clang-421.1.48) (based on LLVM 3.1svn), i.e. Xcode 4.4+, the __typeof__((__typeof__(self))self)
trick is not necessary anymore. The __weak typeof(self) bself = self;
line will compile just fine.
回答2:
This works!
__typeof__(o) __weak
Which I've defined in my BBlock project as BBlockWeakSelf
which can be used like this:
BBlockWeakSelf wself = self;
https://github.com/kgn/BBlock/blob/master/BBlock.h
Edited based on Aleph7's response.
回答3:
The correct way to do this is
__weak ActualClassName* weakSelf = self;
Macros only make it unclear what the variable actually is, and what you're actually doing with it, in addition to adding non-portable meta-language to your code.
If you need a more generic version of the class than ActualClassName provides, you aren't dealing with self
anymore, since where self
is defined, so is the class of self
defined.
In those cases, you should use the closest base class name in your inheritance tree, NSObject
or better, never id
, e.g.
__weak MyBaseClassName* weakObject = object;
回答4:
Generic Weakself Reference (No Import Required + Snippet)
In my experience, the way to go is to use:
__typeof__(self) __weak weakSelf = self;
Note how the ownership qualifier belongs in front of the actual variable.
It's very apparent what's happening when it is used and it can be made into a handy code snippet in Xcode which makes it even easier to use in any project or class where this is needed. (I use "ws" as the snippet's completion shortcut)
Hmm.. I need a weak reference here..
ws{return}
Done. No need to ever include a header in future projects for this, just use the snippet.
Xcode Snippet
Title: Generic Weak Self Reference
Platform: All
Language: Objective-C
Completion Shortcut: ws
Completion Scopes: Function or Method
Code: __typeof__(self) __weak weakSelf = self;
Edit: Added note about ownership qualifier position based on comments, and Xcode Snippet Info
回答5:
why don't just use
__weak id bself = self;
回答6:
i think use this to be ok:
__weak __typeof(&*self)weakSelf = self;
it reference AFNetworking's AFURLConnectionOperation.m codes.
回答7:
I had a similar error but I fixed it differently:
I went to Project Navigator -> Project -> Target -> Build Settings
There I looked for C Language Dialect. I changed it from c11 to GNU99 and it solved my problem.
I hope it helps :)
回答8:
declareBlockSafe( self ) then blk( self ) inside the block. Self can be any variable or instance variable. Use declareBlockSafeAs for properties and method returns.
Also works with non-ARC if you import Mike Ash's splendid MAZeroingWeakRef.
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
You don't REALLY need blk() for ARC, it's just so that the macros can be used in the same way for non-ARC.
回答9:
I have this macro
#define weaken(object) __typeof__(self) __weak weakSelf = object
And i use it like this
weaken(self);
//The block referencing weakSelf goes here
回答10:
What about __unsafe_unretained? That's not as safe as __weak but it's the only thing I could think of. Also, why do you use typeof()?