(1) block definition
An anonymous function with automatic variables (local variables) is called a block
(2) block classification
There are three main types of blocks
__NSGlobalBlock__
: globalblock
, stored in the global area
In this case, the block has no parameters and no return value, and belongs to the global block
__NSMallocBlock__
: heap areablock
Because theBlocks are both functions and objects
The block accesses an external variable, the underlying copy of A, so it’s a heap block
__NSStackBlock__
: the stack zoneblock
Where the local variable A is a stack block before processing (before no copy), and a heap block after processing (after copy). Currently, there are fewer and fewer stack blocks
In this case, you can pass__weak
No strong holding,block
It stillThe stack area block
Conclusion:
block
Stored directly in the global area- if
block
Access external variables and performblock
Corresponding copy, that iscopy
operation- If at this point
Blocks are strong references
,block
Stored in theThe heap area
, i.e.,Heap area block
- If at this point
block
through__weak
Becomes a weak reference, thenblock
Stored in theThe stack area
, i.e.,The stack area block
- If at this point
Block loop reference
① Analysis of circular reference
-
Normal release
: refers to theA hold B
WhenA
calldealloc
Methods toB
sendrelease
Signal,B
receivedrelease
The signal, if at this pointB
theretainCount
(that is, reference count) is0
Is calledB
thedealloc
methods -
A circular reference
:A and B
They hold each other, which leads toA
Can’t calldealloc
Approach toB
sendrelease
Signal, butB
I can’t receive itrelease
Signal. SoA and B
They can’t be released at this point
② Solve circular references
Do the following two pieces of code have circular references?
- Code one kind of hair
A circular reference is generated
Because, inblock
Internally usedExternal variable name
, resulting inBlock is holding self
And theSelf originally owned block
So it leads toSelf and block hold each other
. - Code 2.
Acyclic reference
, although external variables are used, butself
They don’t holdanimation
theblock
Only, onlyanimation
holdself
, does not constitute mutual possession.
There are several common ways to resolve circular references:
- Methods (1) :
weak-strong-dance
— Dance between strong and weak - (2) :
__block
Modify objects (note that inblock
Internal needsempty
Object, andblock
Must call) - Method 3: Pass objects
self
As ablock
Is provided toblock
Internal use - Mode 4: Use
NSProxy
1 Mode ①: weak-strong-dance
- if
block
There is no nesting insideblock
, direct use__weak
modifiedself
Can be
At this timeweakSelf
andself
Point to the same pieceMemory space
And the use of__weak
Does not lead toself
The reference count changes can be printedweakSelf
andself
Pointer address, as well asself
To verify, as shown below
- if
block
Nested insideblock
Need to be used at the same time__weak
和__strong
StrongSelf is a temporary variable in the scope of the block, which releases strongSelf when the internal block is finished executing
This is breaking self’s strong reference to a block, depending on the mediator pattern, and is auto-set to nil, auto-release
②.2 Mode ②: __block modifies variables
This approach, which also relies on the mediator pattern, is manual release and modifies objects with __block, mainly because __block modifies objects that can be changed
Notice that the block here has to be called, if it’s not called, vc is not null, it’s still a circular reference, self and block are not released.
②.3 Method ③: The object self is used as a parameter
The object self is supplied as an argument to the block for internal use, with no reference counting problems
4 Mode 4: NSProxy virtual class
-
OC is a single-inheritance language, but it is based on the run-time mechanism, so NSProxy can be used to implement pseudo-multiple inheritance, filling the gap of multiple inheritance
-
NSProxy and NSObject are sibling classes, or virtual classes, that implement the protocol of NSObject
-
NSProxy is an abstract class that encapsulates message redirection. It is like a proxy, middleware, that can inherit it and rewrite the following two methods to implement message forwarding to another instance
- (void)forwardInvocation:(NSInvocation *)invocation; - (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel Copy the code
-
1. NSProxy is an abstract base class that is the root class, similar to NSObject
-
2. Both NSProxy and NSObject implement the
protocol
-
3. Provides a universal interface for message forwarding
** Usage scenarios **
There are two scenarios for using NSProxy
- implementation
Multiple inheritance
function - To solve the
NSTimer&CADisplayLink
Created forself
Strong reference problem, referenceYYKit
theYYWeakProxy
The principle of circular reference solution is to replace self with a custom NSProxy class object and use methods to implement message forwarding
The following is an implementation of the NSProxy subclass and the scenario in which it is used
-
Define a NSProxy subclass CJLProxy! [](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/797421aa58a84ee7b470ed03fd436a68~tplv-k3u1fbpfcp-watermark.image)
-
The custom
TCJCat
Classes andTCJDog
class
-
through
TCJProxy
Realize multiple inheritance function
-
through
TCJProxy
Resolve timerself
The strong reference problem of
(2). 5
There are basically two ways to solve a circular reference, for example self -> block -> self
- break
self
rightblock
A strong reference to theblock
Property modifier is usedweak
But this will lead toblock
It is also released as soon as it is created, so breaking strong references from here won’t work - break
block
rightself
Strong reference, mainly isself
The scope and ofblock
Scope communication, communication hasProxy, pass value, notification, pass parameter
And other ways to solve the cycle, the common solutions are as follows:weak-strong-dance
__block
(block
The inner object is empty and calledblock
)- The object
self
As ablock
The parameters of the - through
NSProxy
Subclass ofself
Iii. Underlying principle of Block
Mainly through clang, breakpoint debugging and other ways to analyze the Block bottom
(3). 1 block essence
-
define
block.c
file -
through
xcrun -sdk iphonesimulator clang -arch x86_64 -rewrite-objc block.c
That will beblock.c
Compiled intoblock.cpp
, includingblock
At the bottom it is compiled into the following form
By simplification we know that the equivalent block is __main_block_IMPL_0, which is a function
- To view
__main_block_impl_0
, it isA structure
At the same time, it can be explainedblock
Is a__main_block_impl_0
Type of object, that’s why, rightblock
To be able to% @
Reasons for printing.
Summary: The essence of a block is an object, a function, or a structure. Since a block function has no name, it is also called an anonymous function or code block
block
throughclang
The relationship between the compiled source code is shown below__block
For example, modify a variable
③ 1.1 Why does block need to be called
The underlying block has a __main_block_IMPL_0 structure of type, created by its constructor of the same name, and the first passed block’s internal implementation code block, __main_block_func_0, is expressed as FP, which is then assigned to the FuncPtr property of the IMPL, The call is then made in main, which is why the block needs to be called. If not called, the code block implemented inside the block will not execute, which can be summarized as follows
Function declaration
: that is,block
The internal implementation declares a function__main_block_func_0
Perform specific function implementations
: by callingblock
theFuncPtr
Pointer, callblock
perform
③ 1.2 How does block obtain external variables
- Define a variable and set it to
block
In the call - The underlying compilation looks like this
The ain __main_block_func_0 is a copy of the value, and if you do a++ inside a block implementation, it is problematic and will cause confusion in the compiler code that a is read-only.
Summary: When a block captures an external variable, it automatically generates the same internal property to hold
③ 1.3 the principle of __block
- right
a
Add a__block
And then inblock
In thea
for++
operation
The underlying compilation is as follows
main
In thea
Is encapsulated by external variablesobject
__main_block_impl_0
,Object a
The address of the&a
To the constructor- in
__main_block_func_0
Within thea
The process isPointer to the copy
, the object created at this timea
With the object passed ina
Point to theSame memory space
Conclusion:
External variables
through__block
generate__Block_byref_a_0
The structure of the bodyThe structure of the body
Used toSaves the pointer and value of the original variable
- To generate a variable
The pointer address of a structure object
Passed to theblock
And then inblock
You can manipulate external variables internally
The __block and non-__block modifier local variables above produce two different copies
The __block modification
:Copy the value
–Deep copy
, just copy the value, and the copied value cannot be changed, pointing to a different memory space, in the case of ordinary variablesa
isCopy the value
__block modification
:Pointer to the copy
–Shallow copy
.Generated object
Point to theSame memory space
, through the case__block
Modified variablea
isPointer to the copy
]