ObjC: using delegate memory vs block?

I am comparing the memory size of the vs block delegate in Objective-C to solve the same problem. For example, there is a working class that does some work:

// delegate @protocol WorkerDelegate : NSObject - (void)workHasBeenDone; @end // block typedef void (^WorkerBlock)(); @interface Worker : NSObject @property (nonatomic, weak) id<WorkerDelegate> delegate; @property (nonatomic, copy) WorkerBlock block; - (void)doTheWork; @end 

The code requires no explanation, in order to know when the work was done, I can use a delegate or a block:

 @implementation MyObject - (void)workHasBeenDone { [self doCleanUp]; } - (void)entryMethod { Worker *worker = [Worker new]; worker.delegate = self; // or: worker.block = ^{[self doCleanUp];}; [worker doTheWork]; } @end 

As far as I know, in the above code, self as a delegate is in memory; And block copied to a bunch, but I'm not sure which one has more memory.

Now I need the number of employees:

 Worker *workerA = ... // created and set delegate OR block for completion notification Worker *workerB = ... // created and set delegate OR block for completion notification Worker *workerC = ... // created and set delegate OR block for completion notification ... NSDictionary *workers = @{ "jobA": workerA, "jobB": workerB, ... }; 

In this case, the block seems to be cleaner, but, nevertheless, does it have the best, the same or the worst amount of memory?

Thanks a lot!

+5
source share
2 answers

A block is an ObjC object, so it has the same memory usage. You're on the right track, thinking of several Worker - what happens if you want to do the same cleanup in response to all of them?

With a delegate:

 workerA.delegate = workerB.delegate = workerC.delegate = self; //... - (void)workHasBeenDoneWithWorker:(Worker *)worker { //... } 

Here you get three weak links to the same object, so no additional storage or property requirements. And the same workHasBeenDoneWithWorker: method is called three times. (Note: I changed it a bit - it’s useful for the delegate method to know who called it, precisely for this reason: one object may be a delegate for several others, and he may want to know whose work he delegated.)

Now, with the blocks:

 workerA.block = workerB.block = workerC.block = ^{ [self doCleanUp]; }; 

Since your block is declared @property (copy) , this gets three copies of the block. Despite the fact that the source code is the same, the internal and captured state for each will be different. In addition, there is no way (as stated) to the block to know whose work it is doing ... and if you add a parameter to the block that refers to the Worker to which it belongs, you need to be careful about the reference cycles. The difference in memory usage trivial, but the difference in API architecture is more significant.

In general, delegates work well when:

  • multiple delegate objects can share the same delegate
  • the same delegate method can be called multiple times for the same delegation object

And (completion-handler style) is blocked when:

  • the work will be done once, the block will be called once, and then the block will be discarded
  • completion tasks are so closely related to installation tasks that the ability of the unit to capture the surrounding state is valuable.
+9
source

A reverse block pattern gives you more control over the memory management relationship than a delegate pattern.

With a delegation template, whether a delegate link is a strong or weak link is defined in the declaration of the class that performs the delegation (whether the strong or weak property is declared). This is usually weak . The delegate object (the parent object) does not have control over who it wants to be.

 Parent object <----weak---- Delegator 

With the block callback template, the delegating class has a strong link to the block, but the block provided by the parent can have either a strong or weak reference to the parent, which effectively defines the strong or weak connection between the delegator and the parent. He can do this because the block, usually created inside the code of the parent, can choose to capture self (the parent) either strongly (directly) or weakly (using the weakSelf variable).

Thus, the parent using this delegation class can control whether the link is strong or weak depending on the design requirements of a particular use case.

 Parent object <----strong/weak---- block <----strong---- Delegator 
0
source

Source: https://habr.com/ru/post/1206375/


All Articles