IOS understands this article, and your block no longer needs WeakSelf weak reference !, Iosweakself

Source: Internet
Author: User

IOS understands this article, and your block no longer needs WeakSelf weak reference !, Iosweakself
Preface:

Recently, the Sagit frame memory is being released.

For beginners, all the articles you have learned are intended to use typeof (self) _ weak weakSelf = self.

For veterans, WeakSelf may have become a habit.

This time, I will learn how to avoid WeakSelf.

1: Starting from the reference counter:

Here we first design a TableBlock class:

@interface BlockTable : NSObjecttypedef void (^AddCellBlock)();@property (nonatomic,copy)AddCellBlock addCell;@end

First, a BlockTable has only one block attribute, and then outputs a release log.

-(Void) dealloc {NSLog (@ "Table relase"); // The relase is the error word. To be consistent with the error word, it will not be changed here .}

Next, you can find a place to write code: to create a new BlockTable and print the information:

At this time, its reference number is 1 and Table relase exists.

Next, assign a value to the addCell attribute and run:

An empty event does not reference table, so the number of references is still 1.

2: Start loop reference

Reference a table in a block to generate a circular reference and run the following command:

We can see that the number of references has changed to 3, and there is no output object release information. Why not 2? Big question mark !!

Why are two reference counts enhanced when one attribute is assigned?

3: Counter for guessing and jumping

Next, set the attribute to nil and run the following command:

Set to nil, and 2?

Is it released normally?

To verify that you have obviously guessed this: rewrite the setter method of addCell without any storage:

@implementation BlockTable-(void)setAddCell:(AddCellBlock)addCell{    }

At the same time, remove the code set to nil: Run it again to see:

The counter is still 2 and released.

After thinking, we come up with the following conclusions:

1: The Block definition itself will cause one reference. However, this reference will offset the number of references when the block is released when it leaves the function. 2: Archive block may cause one reference, which is the reason why the memory cannot be released.
4: according to the above explanation, I got a crazy conclusion:
As long as the block code is executed only once, self or other strong references can be willful.In fact, the code we write, a lot of blocks do only execute once, whether it is executed at the time of the transfer, or after the transfer is completed, the callback will be executed after a period of time. WeakSelf is not required for execution once, unless the designers of the third-party framework leave a hole and forget to add block = nil after the execution of the archive block.
5: eliminate the reference count of the assignment:

Continue to use your imagination. Since there will be a new reference when it is stored, it will be nice to keep it from adding references:

@implementation BlockTable-(void)setAddCell:(AddCellBlock)addCell{    __weak AddCellBlock addCellWeak=addCell;    _addCell=addCellWeak;}

Let's first define a weak reference for this block, and then assign it to _ addCell. Run the command to see:

Wow, it's done! The counter is 2, which is released normally. It seems that your imagination is okay !!

Next, let's complete the code and add a reloadData method to call events in the method.

The complete code is as follows:

@ Interface BlockTable: NSObjecttypedef void (^ AddCellBlock) (); @ property (nonatomic, copy) AddCellBlock addCell;-(void) reloadData; @ end @ implementation BlockTable-(void) setAddCell :( AddCellBlock) addCell {_ weak AddCellBlock addCellWeak = addCell; _ addCell = addCellWeak;}-(void) reloadData {if (self. addCell) {self. addCell ();
Self. addCell (); // It's okay for two times. Simulate multiple cycles of table adding cell}-(void) dealloc {NSLog (@ "Table relase");} @ end

Modify and add log output. Now, execute the following command:

EverythingLooks likeThey are all perfect and do not need to be introduced. Third, it needs to be used multiple times. It is done only when a weak reference is stored.

6. Weak references:
The block definition and use scenario must be in the same function. To put it bluntly, the block will die out when it leaves the function body, so hurry and cherish it.

Normally, after writing the code reloadData for a Table, the data is generated.

But what if there is a refresh and reload function later?

The re-call of reloadData may be different from the block function. For example, the Code is like this:

-(Void) start {BlockTable * table = [BlockTable new];Self. table= Table; // get the global variableTable. addCell = ^ {_ weak typeof (table) this = table; NSLog (@ "addCell call") ;}; [table reloadData]; NSLog (@ "table retain = % ld", CFGetRetainCount (_ bridge CFTypeRef) (table )));}-(Void) reflesh {[self. table reloadData];}

Defines a table attribute for the external class, and then calls reflesh after calling start to run it. What will happen?

The most terrible EXC_BAD_ACCESS wild pointer error occurs on IOS.

It is easy to understand the disappearance of blocks after they leave the function, but here:

What is this directly throwing an exception? Did you make a judgment?

Let's rewrite the Code:

In addition, we can see that _ addCell still has a value.

Why does if (self. addCell) die directly when it is determined, but if (_ addCell) does not die? Normal self. addCell normal not return _ addCell? This question is left for you to think about.

 

The most terrible thing is the following:

7: avoids the wild pointer. It is still a weak reference and its function remains unchanged.

OK. Continue to use your imagination to see how to avoid the wild pointer and achieve the above effect:

1: Change the block attribute from copy to weak.

@property (nonatomic,weak)AddCellBlock addCell;

2: manual copy of the assignment code:

-(Void) setAddCell :( AddCellBlock) addCell {addCell = [addCell copy]; _ addCell = addCell; // _ addCell = [addCell copy]; this cannot be abbreviated, I don't understand it as Xiami. // It was originally written in this way: // _ weak AddCellBlock addCellWeak = addCell; // _ addCell = addCellWeak ;}

Run again, and the magic thing happened:

The process is still very smooth, there will be no abnormal wild batch needles, and the Table will be released.

The only pity is that after the function is jumped out, the block cannot be reused:

8: block copy method:

For the block passed in by default (there are three forms: Global, stack, and stack)

Global copy, global heap copy, or stack copy to heap

To put it bluntly, copy is only valid for stacks.

This is because the block of the stack directly destroys the object after the brackets are output after execution.

If there is a weak reference in the past, it will cause a wild pointer.

The other two types point to a null pointer when the pointer is destroyed.

AddCell = [addCell copy] and the default copy attribute _ addCell = addCell also perform the copy operation.

After the task is executed, the addCell type is changed to the heap type. In this way, the data is destroyed with a null pointer.

9: What is the difference between a null pointer and a wild pointer:
Null Pointer: point to a pointer created by humans. Its name is null. There is an empty house and there is nothing in it. Wild pointer: You don't know where to point to, even empty houses.
10: Expand your imagination. How can we eliminate the number of references and keep them for a long time?

The disadvantage of weak references is that the block is no longer available when a function is generated.

What else can we do? No, I have the imagination !!!!!

What if the block can be rebuilt?

For example:

1: Convert the block into a string archive, restore it at the right time, and then assign a new value. 2: serialize and save the block, and restore it at the right time? 3: The runtime reads the _ FuncPtr of the block, and the archive is created dynamically?

The pseudocode is roughly as follows:

-(Void) setAddCell :( AddCellBlock) addCell {addCell = [addCell copy]; _ addCell = addCell; // _ addCell = [addCell copy]; this cannot be abbreviated, I don't understand it as Xiami. // It was originally written in this way: // _ weak AddCellBlock addCellWeak = addCell; // _ addCell = addCellWeak; // archive block string}-(void) reloadData {if (! _ AddCell) {// restore the block from the archive block string // _ addCell = restore the block} if (_ addCell) {_ addCell (); _ addCell ();}}

So there are two questions left?

1: How to archive a block? 2: how to restore archive data to blocks.

For C #, these are common, oc is not familiar, and a friend passing by can give support !!

11: If the 10th solution cannot be solved, only the third party can be introduced.

However, this introduction of a third party is only a time point. When this time is triggered, the reference of one party is set to nil.

The timing for the layout of the Sagit framework should be handled in events such as navigation rollback.

However, here is a tip:

When archiving a block, you do not have to exist the current object. You can also use a unified global block for management.

In this way, some blocks can be removed from the global block according to the business situation during business processing.

It depends on the business, so this will not be expanded.

Summary:

I believe that we can see it all the way. In the future, we basically cannot use WeakSelf, because like a block, its lifecycle must be consistent with that of the owner, very few.

In this rare case, if step 4 is solved, it will basically be all solved, but it cannot be solved, and there are still 11.

I believe that after reading this article, if you fully understand it, you will no longer see WeakSelf before the block, and WeakSelf is not necessary.

Finally, we welcome everyone to pay attention to IT-related startups, although I have been tossing IOS recently, haha.

However, it is still necessary to work hard on the basis of IOS, and there will be a qualitative leap in subsequent product improvements.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.