Fast memory management: saving func in var

I am looking for best practice for storing functions as variables in other objects. In particular, I try to avoid loops involving capturing self in a function.

From objective-c and blocks, I would usually do something like this:

 __weak id _self = self; iVar.someBlock = ^{ [_self doSomething]; }; 

Of course, the iVar class should copy the block and save it. The save loop does not exist because I have a __weak id _self .

In Swift, I'm a little less confident, especially since I can pass class functions / methods. So, let's say in the iVar class I have:

 class iVarClass { var callBack:() -> ()? func jumpUpAndDown(){ //Weeeeeee! self.callBack?() } } 

Now in my "main" class, I have an instance variable of the specified class, and I do:

 class mainClass { var iVar: iVarClass init(iVar:iVarClass){ self.iVar = iVar iVar.callback = self.doSomething } func doSomething(){ self.iVar.jumpUpAndDown?() } } 

Do we have a retention cycle? I would think so, and I think that maybe I need to make callback weak:

  weak var callBack:() -> ()? 

Of course, I could do something like this in the main class:

  init(iVar:iVarClass){ self.iVar = iVar weak var _self = self iVar.callback = { _self?.doSomething() } } 

But it’s so nice to be able to pass class functions as arguments! In addition, if I need to make callback weak, then I think that I will lose the ability to assign a closure to it (because after assignment, the closure will be released from memory with only one weak link).

Also pay attention to how the responsibility for managing the memory lies with the recipient now instead of the appointment, but since the recipient cannot know the source of the job, he cannot be held responsible. In other words, there should now be an implicit contract between the recipient and the assignor about which function should be transferred, which is fragile and not recommended. When the responsible assignor is responsible, he can take steps to ensure that there is no retention cycle, but the receiver cannot take such steps.

This makes me think that we should never pass a class function to another object. This is too dangerous. You cannot know how the receiver will store / use it.

Or am I missing something? Can Swift solve this problem behind the scenes?

Update

@Kirsteins pointed out what I forgot: capture lists. So instead of explicitly declaring weak var _self = self you can declare it in closure:

  init(iVar:iVarClass){ self.iVar = iVar iVar.callback = { [weak self] in self?.doSomething() } } 

This is better, but not as elegant as just assigning a class function.

I think I want Swift to automatically convert the class function to closure using a capture list, so I don't need to do this. In fairness, this is not entirely complicated, but, of course, much prettier if I can just assign a class function. Damn, even that would be better:

 self.iVar.callback = weak self.doSomething 
+6
source share
1 answer

Could you do something like this:

 class mainClass { var iVar: iVarClass init(iVar:iVarClass){ self.iVar = iVar func go() { self.doSomething() } iVar.callback = go } func doSomething(){ self.iVar.jumpUpAndDown?() } } 

I understand that this way you won’t capture self directly and thus avoid the save loop.

0
source

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


All Articles