Does the iOS application delegate link in the block indicate a copy of the delegate object?

Consider the following example:

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

Having made the assumption that the completion block is executed in the main / user interface thread to avoid additional insanity, this is what I'm not sure about:

  • Does the appDelegate variable push onto the stack, like the usual block rules when referring to variables inside the block?
  • If yes at # 1, is this a good / safe practice? I could see that this could cause problems if you did it in a block that was subsequently sent to the GCD queue, since .someNeatObject could change state / went to zero?

I understand that appDelegate should not be abused, but it is useful for it to store information about the current state of the application, for example, objects related to Core Data, if you use Apple templates to initialize the Core Data stack (at least on iOS projects). In this particular case (Core Data), it bothers me that most of this stack is not thread safe, and it is not recommended to copy it.

Thanks in advance.

+8
ios objective-c macos
source share
2 answers

Your example will not compile because the delegate is not defined. I suppose you mean "SomeNeatObject * object = appDelegate.someNeatObject;"

In this example, appDelegate is a variable whose value will be committed by the block. This is no different from any other variable.

This is unsafe because the [[UIApplication sharedApplication] delegate] always returns the same unless you change the delegate, which you probably aren't doing.

Key concepts: appDelegate is a variable that points to (or refers to) an object (or instance) of type AppDelegate . There is one such instance in an iOS application that is returned by the [[UIApplication sharedApplication]] delegate. If you create a link to appDelegate inside a block, you make a copy of the variable, not the object. So, in your code block:

 SomeNeatObject *object = appDelegate.someNeatObject; 

This is semantically the same as putting the following code in a block (sheets omitted):

 SomeNeatObject *object = [[UIApplication sharedApplication] delegate].someNeatObject; 

Referred SomeNeatObjects are one and the same.

A slightly more advanced concept: any object has an address in memory (integer, usually in hexadecimal). If two variables have the same hexadecimal value, they point to the same object. If they have different meanings, they point to different objects. In your example, appDelegate (the outer block) and appDelegate (inside the block) have the same value, therefore they point to the same object.

If you must do this:

 AppDelegate * otherDelegate = [appDelegate copy]; 

Then you make a copy of the object pointed to by appDelegate. But do not do this, please.

+5
source share

Saving counter increases. The tool is to mark it with the __weak attribute:

 - (void)exampleFunction { __weak AppDelegate *weakDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; SomeClass *classObject = [[SomeClass alloc] init]; [classObject someFunctionThatDoesBackgroundWorkAndCallsACompletionBlock:^(NSDictionary *results) { SomeNeatObject *object = weakDelegate.someNeatObject; [object doSomeNeatStuff:results]; }]; } 
+2
source share

All Articles