iHu*_*ter 4 objective-c objective-c-blocks automatic-ref-counting
我想知道问题主题的变量声明是否合法.想象一下以下代码:
__weak typeof(self) weakSelf = self;
[self doSomethingThatMayCauseRetainCycleWithBlock:^{
typeof(self) self = weakSelf; // <---- !!!!
if (self == nil) return;
NSAssert(self.someProperty != nil, @"This doesn't lead to retain cycle!");
[self doSomething];
self.someProperty = someValue;
// even
self->someIvar = anotherValue;
}
Run Code Online (Sandbox Code Playgroud)
此代码在Xcode 4.5.2中完美运行,仅发出警告Declaration shadows a local variable.
这个怪癖有什么意义:
self为弱变量的强引用后,您可以安全地复制/移动块内部/外部的代码,而不会有偶尔创建保留周期的风险(除了ivars,但它们是邪恶的).NSAssert 块中不再导致保留周期.更新
我发现这种技术libextobjc用于@weakify/@strongify宏.
这个答案分为两个部分:
GCC_WARN_SHADOW,以及为什么打开它可能是一个糟糕的警告.NSAssert并不需要这种技巧你得到的警告来自GCC_WARN_SHADOW,一个更无用的警告(在我看来,无论如何).编译器在这里做了正确的事情,但是由于GCC_WARN_SHADOW它引起了你的注意,你可能做了一些非你想要的事情.
这是偏执狂编译器警告擅长的事情.缺点是很难(不是不可能)放弃一个特定的警告,表明你知道你在做什么.
使用GCC_WARN_SHADOWon,此代码将生成警告:
int value = MAX(1,MAX(2,3));
Run Code Online (Sandbox Code Playgroud)
尽管如此,它将完美运作.
这样做的原因是它编译成这个,这很丑,但(对编译器)非常清楚:
({
int __a = (1);
int __b = (({
int __a = (2);
int __b = (3);
__a < __b ? __b : __a;
}));
__a < __b ? __b : __a;
})
Run Code Online (Sandbox Code Playgroud)
所以你提出的建议会很好.NSAssert是使用使用该self变量的宏实现的.如果你self在你的范围内定义,那么它就会self取而代之.
但是,如果您认为GCC_WARN_SHADOW有用,那么还有另一种解决方案.无论如何它可能会更好:提供自己的宏.
#define BlockAssert(condition, desc, ...) \
do { \
__PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \
if (!(condition)) { \
[[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd \
object:strongSelf file:[NSString stringWithUTF8String:__FILE__] \
lineNumber:__LINE__ description:(desc), ##__VA_ARGS__]; \
} \
__PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \
} while(0)
Run Code Online (Sandbox Code Playgroud)
这实际上是一个复制粘贴NSAssert,但它使用strongSelf而不是self.在使用该strongSelf模式的地方,它会起作用; 在strongSelf未定义的地方,您将收到编译器错误:使用未声明的标识符:'strongSelf'.我认为这是一个非常好的暗示.
| 归档时间: |
|
| 查看次数: |
2642 次 |
| 最近记录: |