Do I need to use a weak self pointer if a method called from a Block uses self?

后端 未结 4 673
悲&欢浪女
悲&欢浪女 2021-01-15 14:46

Using self. in blocks causes retain cycles, so I need to create a reference to weakSelf. I understand this

BUT!

If from my block I

4条回答
  •  北恋
    北恋 (楼主)
    2021-01-15 15:26

    I might be misreading your question, but your wording:

    If from my block I call a method which uses "self.", does this too cause a retain cycle? For instance if I reload a UITableView from a block and in some of my UITableView delegates I call "self.", I'm causing a retain cycle? That means I have to pass around this weakReference everywhere?

    suggests you are misunderstanding what self is. Hopefully if so the following will help and not hinder your understanding...

    What is self?

    The identifier self is just the name of one of the parameters to your method, it is just passed implicitly rather then explicitly like the other parameters. For example if you have a class:

    @implementation MyClass
    
    - (void) someMethod:(NSInteger)value
    {
       ... self ... value
    }
    
    @end
    

    then the method is effectively (i.e. bending the facts just a little for clarity):

    - (void) someMethod:(NSInteger)value withObject:(MyClass *)self
    {
       ... self ... value
    }
    

    When an instance method is called the value passed for the self parameter is a reference to the instance the method should operate on, e.g. the call

    MyClass *someInstance = ...
    
    [someInstance someMethod:42];
    

    is effectively a call to:

    someMethod:42 withObject:someInstance
    

    Strong reference cycles

    An object - which includes both instances of classes and blocks - is kept alive as long as there exists a strong reference to the object.

    If an object A holds a strong references, e.g. in an instance variable or property, to an object B, then B will be kept alive at least (there could be other strong references to B) as long as A is alive.

    If an object A holds a strong reference to B and B holds one to A then you have a strong reference cycle - each object is keeping the other alive and neither will ever be collected. This could lead to a memory leak - where unused memory is never collected - unless both A and B are meant to live from creation till the end of the program.

    Further, you do not create a strong reference cycle simply by having references stored in the local variables and parameters of methods. By their nature such variables, and therefore their contents, are transient and are destroyed when the method returns.

    Using self in blocks

    using "self." in blocks causes retain cycles so I need to create a reference to weakSelf.

    Not quite. When you use self in a block, either directly or indirectly by referencing an instance variable, then the compiler will warn you that you may create a reference cycle. (Note: There are other ways to create reference cycles, both with and without using blocks, and the compiler will not warn you at all. Managing cycles is just something you need to be aware of.)

    You will only actually create a cycle if you store a reference to the block in the object referenced by self. However this is not bad in itself, as long as at some point you break the cycle manually - say by storing nil in the variable referencing the block - the cycle need not be problematic at all.

    Finally...

    You have nothing per se to worry about with your:

    UITableView delegates I call "self."

    as that self is just a local parameter to the delegate whose initial value, at some point going back up the call chain, came from you evaluating your weakSelf reference and determining that it was not nil and then calling methods on it.

    HTH

提交回复
热议问题