diary

Also talk about __block-ios learning in ObjectiveC from entry to mastery.

Sharing the hottest information

  • This article is CocoaChina netizens. SjtuPeter Contribute

Almost every iOS developer knows that in block, the value of non static local variables can not be modified, and the solution is to use __block to modify variables.

But did you think deeply about it? For example:

1. why can't block modify non static local variables?

The first response is that variables are passed to block, so they cannot be modified. Why can we treat non static local variables directly as pointers to static local variables? When it comes to this, we have to say that static local variables are different from non static local variables. Static variables exist in the entire life cycle of the application, rather than static local variables, which exist only in a local context. If the non static local variables pointed out during the execution of block are not recovered by the stack, this execution is OK, and in most cases, block is postponed, so this is very inappropriate.

Before talking about why __block can solve this problem, let's first discuss a question. Why do we need to manually add __block to the compiler, and the compiler can't add __block to the default? If the compiler does this, the non static global variables used in block can be modified in block. In fact, block is an anonymous function. Instead of static variables, it is external variables relative to block, which is a typical modification of external variables in the function, resulting in side effects. In addition, doing so is also against the original intention of non static variables, causing great confusion. Therefore, it is not appropriate for the compiler to add __block modifiers by default. This decision can only be handed to the developer to decide whether to add __block or not.

What's wrong with 2. plus __block?

By rewriting the source code through clang, you can find that after __block is modified, the original variable has been replaced by a corresponding struct variable (new variable), for example, to define a new variable.

__block NSMutableArray *array = [NSMutableArray new]; will become

__Block_byref_array_1 array = {0, &array, 33554432, size, copyFunc, disposeFunc, [NSMutableArray new]}; (deleted and modified)

The structure of __Block_byref_array_1 is shown below.

Through analysis, it is found that there is a __forwarding pointer in the structure. When initialization, this pointer points to the variable itself after the transformation, and there is a variable of the same type as the original variable in the structure.

At the same time, the places where the original variables are involved in the code will be transformed into new variables ->__forwarding-> primitive variables. In fact, there are few books or articles mentioned in the code. If you fail to realize this, you will be surprised at the understanding of many problems.

Why is 3.__block feasible?

Through the above analysis, if we directly modify the value of variables in block, it will be transformed into a new variable ->__forwarding-> primitive variable. So the final modification is actually the same type variable of the original variable in the structure, and this variable obviously does not belong to the external variable of block, so it can be modified in block.

At this point, there are two questions:

  • This new variable is also a non static local variable. When block executes, the new variable may have been recovered by the stack.

If the new variable is released when block is executed, the program will be crash. In fact, even using __block can not solve this problem, or __block does not seem to have anything to do with this situation.

In daily development, it seems that this kind of crash is seldom encountered. Because most of the block encountered in the actual development have been copy to the heap, block will trigger the copy of the __block variable when copy is copy, which will change the variables from stack space copy to heap space, so block is using the corresponding variables on the heap space when executing, so it will not generate crash.

  • What is the function of __forwarding? Why design this way?

  • What's the use of __forwarding? Where will it be involved?

From the code level analysis, as before, when using __block variables, after conversion, they are actually accessed through their __forwarding.

From the result of the phenomenon, if the __block variable is modified in block, the modification outside block is also effective. In fact, this is also the function of __forwarding.

  • How does a compiler work? What are the benefits of this?

This can be combined with the __block variable's copy source code to analyze:

From the source code, you can see all kinds of details clearly. There is not much explanation here. One thing to note is that src->forwarding = copy; the forwarding of the original object is pointed to the newly created object. It is obvious that the __block variable starts in the stack space, and its forwarding points to itself. When the variable from stack space copy to heap space, the forwarding of the original stack space points to the newly created variable (heap space), which in fact achieves the effect of changing the original variable from the Objective C level.

  • No __forwarding, okay?

For the time being, I did not think of a good alternative. Welcome to add! Obviously, __forwarding is indeed a highlight of the whole scheme design.

IOS learn from entry to master.

Also talk about __block-ios learning in ObjectiveC from entry to mastery.

Sharing the hottest information

  • This article is CocoaChina netizens. SjtuPeter Contribute

Almost every iOS developer knows that in block, the value of non static local variables can not be modified, and the solution is to use __block to modify variables.

But did you think deeply about it? For example:

1. why can't block modify non static local variables?

The first response is that variables are passed to block, so they cannot be modified. Why can we treat non static local variables directly as pointers to static local variables? When it comes to this, we have to say that static local variables are different from non static local variables. Static variables exist in the entire life cycle of the application, rather than static local variables, which exist only in a local context. If the non static local variables pointed out during the execution of block are not recovered by the stack, this execution is OK, and in most cases, block is postponed, so this is very inappropriate.

Before talking about why __block can solve this problem, let's first discuss a question. Why do we need to manually add __block to the compiler, and the compiler can't add __block to the default? If the compiler does this, the non static global variables used in block can be modified in block. In fact, block is an anonymous function. Instead of static variables, it is external variables relative to block, which is a typical modification of external variables in the function, resulting in side effects. In addition, doing so is also against the original intention of non static variables, causing great confusion. Therefore, it is not appropriate for the compiler to add __block modifiers by default. This decision can only be handed to the developer to decide whether to add __block or not.

What's wrong with 2. plus __block?

By rewriting the source code through clang, you can find that after __block is modified, the original variable has been replaced by a corresponding struct variable (new variable), for example, to define a new variable.

__block NSMutableArray *array = [NSMutableArray new]; will become

__Block_byref_array_1 array = {0, &array, 33554432, size, copyFunc, disposeFunc, [NSMutableArray new]}; (deleted and modified)

The structure of __Block_byref_array_1 is shown below.

Through analysis, it is found that there is a __forwarding pointer in the structure. When initialization, this pointer points to the variable itself after the transformation, and there is a variable of the same type as the original variable in the structure.

At the same time, the places where the original variables are involved in the code will be transformed into new variables ->__forwarding-> primitive variables. In fact, there are few books or articles mentioned in the code. If you fail to realize this, you will be surprised at the understanding of many problems.

Why is 3.__block feasible?

Through the above analysis, if we directly modify the value of variables in block, it will be transformed into a new variable ->__forwarding-> primitive variable. So the final modification is actually the same type variable of the original variable in the structure, and this variable obviously does not belong to the external variable of block, so it can be modified in block.

At this point, there are two questions:

  • This new variable is also a non static local variable. When block executes, the new variable may have been recovered by the stack.

If the new variable is released when block is executed, the program will be crash. In fact, even using __block can not solve this problem, or __block does not seem to have anything to do with this situation.

In daily development, it seems that this kind of crash is seldom encountered. Because most of the block encountered in the actual development have been copy to the heap, block will trigger the copy of the __block variable when copy is copy, which will change the variables from stack space copy to heap space, so block is using the corresponding variables on the heap space when executing, so it will not generate crash.

  • What is the function of __forwarding? Why design this way?

  • What's the use of __forwarding? Where will it be involved?

From the code level analysis, as before, when using __block variables, after conversion, they are actually accessed through their __forwarding.

From the result of the phenomenon, if the __block variable is modified in block, the modification outside block is also effective. In fact, this is also the function of __forwarding.

  • How does a compiler work? What are the benefits of this?

This can be combined with the __block variable's copy source code to analyze:

From the source code, you can see all kinds of details clearly. There is not much explanation here. One thing to note is that src->forwarding = copy; the forwarding of the original object is pointed to the newly created object. It is obvious that the __block variable starts in the stack space, and its forwarding points to itself. When the variable from stack space copy to heap space, the forwarding of the original stack space points to the newly created variable (heap space), which in fact achieves the effect of changing the original variable from the Objective C level.

  • No __forwarding, okay?

For the time being, I did not think of a good alternative. Welcome to add! Obviously, __forwarding is indeed a highlight of the whole scheme design.

IOS learn from entry to master.

Fabulous ( Zero )

This article is composed of Ji Chang Xin Creation, article address: Https://blog.isoyu.com/archives/20365.html
Use Knowledge sharing signature 4 The international license agreement is licensed. In addition to the reprint / provenance, all originals or translations of this site must be signed before retransmission. The final editing time is August, 25, 2017 at 04:00 afternoon.

Hot articles

Comment

[required]

Invisibility?

Please wait three seconds after submission, so as not to cause unsuccessful successes and duplication.