引用块中的iOS应用程序委托是否会创建委托对象的副本?

Mat*_* S. 8 macos objective-c ios

请考虑以下示例:

- (void)exampleFunction
{
  AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  SomeClass *classObject = [[SomeClass alloc] init];
  [classObject someFunctionThatDoesBackgroundWorkAndCallsACompletionBlock:^(NSDictionary *results) {
    SomeNeatObject *object = appDelegate.someNeatObject;
    [object doSomeNeatStuff:results];
  }];
}
Run Code Online (Sandbox Code Playgroud)

假设在主/ UI线程上执行完成块以避免额外的疯狂,这是我不确定的:

  1. appDelegate变量是否被复制到堆栈中,按照常规块规则引用块内的变量?
  2. 如果是#1,这是一个好/安全的做法吗?我可以看到这可能会导致问题,如果你在随后调度到GCD队列的块中执行此操作,因为.someNeatObject可能已更改状态/变为nil?

我意识到appDelegate不应该被过度使用,但如果你使用Apple的模板来初始化Core Data堆栈(至少在iOS上),它可以保存有关应用程序当前状态的信息,例如Core Data相关对象.项目).那个特殊情况(核心数据)让我担心这个堆栈不是线程安全的,也不是复制它的好主意.

提前致谢.

Sof*_*LLC 6

您的示例将无法编译,因为未定义委托.我假设你的意思是"SomeNeatObject*object = appDelegate.someNeatObject;"

在此示例中,appDelegate是一个变量,其值将由块捕获.它与任何其他变量没有什么不同.

它不是不安全的,因为[[UIApplication sharedApplication]委托]总是返回相同的东西,除非你改变委托,你可能不会.

这里的基本概念是:的appDelegate是一个变量,其指向(或引用)到一个对象类型的(或实例)的AppDelegate.在iOS应用程序中,有一个这样的实例,由[[UIApplication sharedApplication]委托]返回.如果在块内创建对appDelegate的引用,则表示您正在复制变量,而不是对象.所以在你的代码块中:

SomeNeatObject *object = appDelegate.someNeatObject;
Run Code Online (Sandbox Code Playgroud)

这在语义上与在块中放置以下代码相同(强制转换):

SomeNeatObject *object = [[UIApplication sharedApplication] delegate].someNeatObject;
Run Code Online (Sandbox Code Playgroud)

引用的SomeNeatObjects是相同的东西.

略微更高级的概念:任何对象在内存中都有一个地址(一个整数,通常以十六进制显示).如果两个变量具有相同的十六进制值,则它们指向同一个对象.如果它们具有不同的值,则它们指向不同的对象.在您的示例中,appDelegate(外部块)和appDelegate(内部块)具有相同的值,因此指向同一个对象.

如果你这样做:

AppDelegate * otherDelegate = [appDelegate copy];
Run Code Online (Sandbox Code Playgroud)

然后你将制作appDelegate指向的对象的副本.但请不要这样做.