考虑以下示例:
- (void)exampleFunction
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
SomeClass *classObject = [[SomeClass alloc] init];
[classObject someFunctionThatDoesBackgroundWorkAndCallsACompletionBlock:^(NSDictionary *results) {
SomeNeatObject *object = appDelegate.someNeatObject;
[object doSomeNeatStuff:results];
}];
}
假设完成 block 在主/UI 线程上执行以避免额外的疯狂,这是我不确定的:
- 当在 block 内引用变量时,appDelegate 变量是否按照正常的 block 规则复制到堆栈上?
- 如果对 #1 的回答是肯定的,那么这是一种好的/安全的做法吗?如果您在随后分派(dispatch)到 GCD 队列的 block 中执行此操作,我认为这可能会导致问题,因为 .someNeatObject 可能已更改状态/变为 nil?
我意识到 appDelegate 不应该被过度使用,但如果您使用 Apple 的模板来初始化 Core Data 堆栈(at至少在 iOS 项目上)。那个特殊情况(核心数据)让我担心,因为该堆栈的大部分内容都不是线程安全的,复制它也不是一个好主意。
提前致谢。
最佳答案
您的示例将无法编译,因为未定义委托(delegate)。我假设你的意思是“SomeNeatObject *object = appDelegate.someNeatObject;”
在这个例子中,appDelegate 是一个变量,它的值将被 block 捕获。它与任何其他变量没有什么不同。
这并非不安全,因为 [[UIApplication sharedApplication] delegate] 总是返回相同的东西,除非您更改委托(delegate),而您可能不会这样做。
这里的基本概念是:appDelegate 是一个变量,它指向(或引用)一个对象 AppDelegate 类型的(或实例)。在 iOS 应用程序中有一个这样的实例,它由 [[UIApplication sharedApplication] delegate] 返回。如果您在 block 内创建对 appDelegate 的引用,则您正在复制变量,而不是对象。所以在你的代码块中:
SomeNeatObject *object = appDelegate.someNeatObject;
这在语义上与将以下代码放入 block 中相同(省略强制转换):
SomeNeatObject *object = [[UIApplication sharedApplication] delegate].someNeatObject;
被引用的 SomeNeatObjects 是同一件事。
稍微高级一点的概念:任何对象在内存中都有一个地址(一个整数,通常以十六进制形式出现)。如果两个变量具有相同的十六进制值,则它们指向同一个对象。如果它们具有不同的值,则它们指向不同的对象。在您的示例中,appDelegate(外部 block )和 appDelegate(内部 block )具有相同的值,因此指向相同的对象。
如果你要这样做:
AppDelegate * otherDelegate = [appDelegate copy];
然后您将复制 appDelegate 指向的对象。但请不要这样做。
关于ios - 在 block 中引用 iOS 应用程序委托(delegate)是否会创建委托(delegate)对象的副本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22826288/