Opening:

If you’ve read block’s other posts before, you’ll find it easier to explain some of the deeper aspects of this blog post. There’s only one point in each post, and if you’ve read all of this, you’ll probably have no problems with Block.

Capture for block source code

From the source code, ARC, MRC take you to understand the three types of block

Understand the underlying copy of blocks in depth

Understand the auto variable of the underlying block object type

Understand the underlying implementation of __block modifiers

Circular reference:

In the process of development at ordinary times, the function of the block is we often use, if you don’t pay more attention to will cause some problems, the most obvious is the problem of circular reference, is also the interviewer frequently asked questions, this blog will focus on the circular reference solutions, and interpreted from the Angle of source why these solutions can solve the circular reference.

Look at the code below

Loop over code instances

The reason for the circular reference is that myBlock holds the Person object, and the Person holds myBlock inside of it, causing the circular reference

person -> myBlock ->person

The illustration is:

Self and block hold each other, like above

When the person is released, it cannot release itself because it holds a myBlock. The myBlock also waits for the Person to release itself, so it’s a mutual holding that can’t be released

I call dealloc in GDPerson and print NSLog(@”%s”,__func__); So let’s see if we can call this and obviously this program doesn’t call this dealloc method when it’s done, so let’s look at the solution

Solve the problem of circular references -ARC

There are three ways to solve this problem. First, let’s look at what is available in ARC mode

1. Use _ _weak to resolve the problem

First of all, we know that we have a person ->block and a block -> person, and we just want one of the strong references to be missing, and we’re done with that, and we’d prefer to have a block -> The person line breaks, because person is an object with a block in it, and we want to keep that relationship, as shown in the following code:

Run in ARC environment

Iphoneos clang -arch arm64-rewrite-objc -fobjc-arc – fobjc – runtime = ios – 8.0.0. Main m – o main CPP)

Run in ARC environment

If you read my previous blog, you should be very familiar with the source code: stack block copy stack block, when the object is automatically generated as copy and dispose function, then copy function will call the internal __main_block_copy_0 function, and then call again The _Block_object_assign function determines whether the object holds, depending on whether you pass it weak or strong. Weak is obviously passed in, so it won’t be held. (Please refer to the previous blog for details.)

2. Use _ _unsafe_unretained

__unsafe_unretained and __weak:

__unsafe_unretained: strong references are not generated, and the address of the pointer remains unchanged when the referenced object is destroyed

__weak: No strong references are generated, and Pointers are automatically set to nil when the object they point to is destroyed

__unsafe_unretained direct translation is also unsafe. As a result, the __unsafe_unretained direct translation is not safe, but it can be accessed as a wild pointer. __unsafe_unretained is very rarely used, but it can be used throughout an interview. It does work across repeated references

Ok, let’s look at the following code result:

Under the environment of the ARC

At first glance, the dealloc method was indeed called, and the circular reference was definitely resolved

3. Use _ _block to solve the problem

First of all, we know that _ _block can solve the problem of internal block trying to modify external auto. It can also solve the problem of circular reference. If the interviewer asks you what _ _block does, I’m sure you can answer both functions

Under the environment of the ARC

So let’s see if we call dealloc as well, which means we’ve successfully released the circular reference, but the downside is that you have to call the code that I circled above in red, in order to resolve the circular reference MyPerson =nil; person.myBlock(); The two words.

Let’s take a look at the reasons for this. First let’s look at the reasons for this circular reference. Let’s review our previous knowledge

Under the environment of the ARC

So a __block holds a Person, which was explained very clearly in previous blogs, so there are three blocks in the code

This diagram explains the relationship very clearly

person->block; block->__block; __block->person

It happens to be a triangulation loop, so it creates circular references. So all we have to do is get rid of the strong references, so I set the object to nil that’s the line that __block-> points to the object, that strong reference is removed, the object doesn’t exist, the natural relationship doesn’t exist, and that solves the problem of circular references.

The only downside to this is that you have to write those two lines of code, and if you only write code that sets block internals to nil and you don’t call it, that will also cause a memory leak!

Solve the problem of circular reference -MRC

This is just for understanding, because it’s all ARC now, if the interviewer asks you about ARC, you need to know about ARC,

Since MRC does not have the idea of __weak, we will not discuss this. Weak Pointers are not supported

1. Use _ _unsafe_unretained-

Take a look at the code result below. (Note the change to MRC test oh!) And MRC calls [super dealloc];

MRC environment running

So obviously, this is a solution to the problem of circular reference in MRC environment.

2. Use _ _block- to resolve the problem

So let’s look at the results first

MRC environment running

That’s one difference, one difference. In the MRC case,__block doesn’t make a strong reference to person, whether your myPerson is a strong pointer or a weak pointer. That’s the difference.

Conclusion:

Here we can summarize the previous block interview questions, take a look.

The following is just a summary for your reference, many of which I have summarized before, but I did not carry them all over.

1. How does Block work? What is the essence?

A block is essentially an OC object with an ISA pointer inside it, enclosing a function call and its OC object.

2. What is the function of _block? What is the use of attention?

The auto variable can be modified inside the block, and circular references can also be addressed, noting the handling of memory addresses, and __block does not make strong references to objects in MRC environments

3. Why does the modifier block copy? What are the implications of using blocks?

Copy to the heap, live longer, use it better, pay attention to circular references, etc.

4. Block Is modifying NSMutableArray. Do I need to add _block?

No, because you’re using it, not modifying it, don’t use _block if you can’t use _block, because you’re going to generate more stuff.

I’m going to talk about Runtime in the next part of my blog

If you find my writing helpful, please follow me and I will continue to update 😄