Small valley bottom exploration collection
block
This thing – basic is closely related with our life, 😆, after all, with too much. Today, brothers, let’s exploreblock
What is it? 🐯
1. block
classification
- Real men don’t beat around the bush. – code
1.1. The globalblock
void (^block)(void) = ^ {NSLog(@"xiaogu");
};
NSLog(@ "% @",block);
Copy the code
- Output:
Global block when there are no external variables
1.2. The heap areablock
int a = 10;
void (^block)(void) = ^ {NSLog(@"xiaogu -- %d",a);
};
NSLog(@ "% @",block);
Copy the code
- Output:
There are external variables that are introduced that become heap blocks
1.3. The stack block
int a = 10;
void (__weak ^block)(void) = ^ {NSLog(@"xiaogu -- %d",a);
};
NSLog(@ "% @",block);
Copy the code
- Output:
With __weak, it becomes a stack block
2. block
A circular reference
I bet my bottom line: all my brothers who use blocks have experienced circular references
-
A circular reference
(I like to speak in plain English) is: I hold you, you hold me. The result can not put open ~
-
- Here’s an example:
typedef void(^XGBlock)(void);
@interface XGTestVC(a)
@property(nonatomic.copy)XGBlock block;
@property(nonatomic.copy)NSString * name;
@end
/ / implementation
self.name = @"xiaogu";
self.block = ^(void) {NSLog(@ % @ - "".self.name);
};
self.block();
Copy the code
This creates a circular reference to self — hold –> block — hold –> self
-
- If you’re testing, you can write a
dealloc
Method to see if the exit interface is released
- If you’re testing, you can write a
- (void)dealloc
{
NSLog(@"dealloc");
}
Copy the code
2.1. Solutions
- When we have a problem, there are all kinds of solutions. Today, I’ll talk to you guys about a few
2.1.1. The Dance of strength and weakness (strong - weak - dance
)
I’m sure everyone’s heard that word. Today I will present a wave of ugly ~
-
- Just begin to do
iOS
The solution my brothers came up with was to solve the dependency and then do a waveweakSelf
- Just begin to do
__weak typeof(self) weakSelf = self;
self.block = ^(void) {NSLog(@ % @ - "",weakSelf.name);
};
Copy the code
Then you find that the circular reference is really solved, and leave it alone
becauseweakSelf
This adds to the weak reference list, and you don’t know when to release. ifblock
There are time-consuming operations in, so this might benil
the
-
- Dance between strong and weak (
strong - weak - dance
), come ~ show ~
- Dance between strong and weak (
__weak typeof(self) weakSelf = self;
self.block = ^(void){
__strong __typeof(weakSelf)strongSelf = weakSelf;
// It takes time to operate something
NSLog(@ % @ - "",strongSelf.name);
};
Copy the code
This is the dance of strength and weakness, strongSelf’s life cycle will be released in block code blocks, which is a perfect solution (I feel) ~ because I like it, 😆
2.1.2. Intermediate mode — Manual release
Of course, there are also brothers who do not like to dance strong and weak, that can also be manually released
__block
External variables can be modified. So let me do this
__block XGTestVC *tvc = self;
self.block = ^(void) {// It takes time to operate something
NSLog(@ % @ - "",tvc.name);
// set nil when used up
tvc = nil;
};
Copy the code
This also resolves circular references. After all, TVC is scoped, out of scope is released
2.1.3. Value transmission mode
-
- There’s nothing left to say here, just pass a value, he doesn’t hold it, it doesn’t cause a circular reference
-
- If if the circular reference, I prefer the strong and weak dance to solve the convenient, which makes people very comfortable after all, 😆
3. block
Structure to explore
The above solutions are very simple to say, the next is the highlight ~
3.1. The globalblock
-
- Let’s do an easy one first
block
- Let’s do an easy one first
-
- Those of you who read my original blog already know what I’m going to read.
xcrun -sdk iphonesimulator clang -rewrite-objc main.m
-
- I can figure it out
.cpp
Compared the under
- I can figure it out
A block is just a structure, so it can print at sign, % at sign, and then it has its own constructor.
~ xgblock->FuncPtr(xgblock); ~(xgblock) The session is passed in the form of hidden parameters
3.2. The heapblock
-
- So let’s see, what happens if we introduce an external parameter
int a = 180;
void (^xgblock)(void) = ^ {NSLog(@"xiaogu-height-%d",a);
};
xgblock();
Copy the code
😆, let’s xcrun-Clang take a look
Stack of words on their own, ha ha ha 🙄
3.2.1. __block
modified
The __block modifier is used to change the external value of a block block, so what does __block do
-
- The test code
__block int a = 180;
void (^xgblock)(void) = ^{
a++;
NSLog(@"xiaogu-height-%d",a);
};
xgblock();
Copy the code
-
- we
xcrun-clang
Look at the
- we
-
- We see through
__block
After modification, there’s this one. Let me show you the whole thing
- We see through
-
- Conclusion: Approved
__block
After modifying the variable, a structure is generated. The structure then stores the variables and changes the values in the structure as it changes them. (In fact, the original variable into the corresponding object)
- Conclusion: Approved
4. block
Source code analysis
4.1. Locate the source code
Before we start, we need to solve a problem: we don’t know where the source code for Block is. See who
-
- First we need to locate the source code. (The following is my positioning process ~)
-
- After we find the source code. It’s comfortable. This source code can be compiled. So debugging is very comfortable ~) (I use the latest source code with the brothers to go round)
4.2. block
Stack – > pile
-
- I read a lot online
block
Blog, will say:block
From the stack area, and thencopy
Pile areablock
- I read a lot online
-
- Guys, we need to get to the bottom. We need to feel it
_Block_copy
What have you done? How do I get from stack to heap
- Guys, we need to get to the bottom. We need to feel it
-
- So let’s write a heap area
block
- So let’s write a heap area
__block int a = 10;
void (^mallocBlock)(void) = ^void {
a++;
};
NSLog(@"MallocBlock is %@", mallocBlock);
Copy the code
-
- Then by locating the source code during the process, we know it will execute
_Block_copy
(this is actually the key method), and we can debug 😆, so let’s break to 😆
- Then by locating the source code during the process, we know it will execute
-
- And then let’s look at his value when he comes in
Now it’s still a stack block.
-
- Hey hey. 😝, let’s see how he becomes a heap
block
. I first put the code affixed, can also help the brothers without source ~
- Hey hey. 😝, let’s see how he becomes a heap
void *_Block_copy(const void *arg) {
struct Block_layout *aBlock;
if(! arg)return NULL;
// The following would be better done as a switch statement
aBlock = (struct Block_layout *)arg;
if (aBlock->flags & BLOCK_NEEDS_FREE) {
// latches on high
latching_incr_int(&aBlock->flags);
return aBlock;
}
else if (aBlock->flags & BLOCK_IS_GLOBAL) {
return aBlock;
}
else {
// Its a stack block. Make a copy. - If it is a stack block, copy it
struct Block_layout *result =
(struct Block_layout *)malloc(aBlock->descriptor->size);
if(! result)return NULL;
memmove(result, aBlock, aBlock->descriptor->size); // bitcopy first
#if __has_feature(ptrauth_calls)
// Resign the invoke pointer as it uses address authentication.
result->invoke = aBlock->invoke;
#endif
// reset refcount
result->flags &= ~(BLOCK_REFCOUNT_MASK|BLOCK_DEALLOCATING); // XXX not needed
result->flags |= BLOCK_NEEDS_FREE | 2; // logical refcount 1
_Block_call_copy_helper(result, aBlock);
// Set isa last so memory analysis tools see a fully-initialized object.
result->isa = _NSConcreteMallocBlock;
returnresult; }}Copy the code
-
- My breakpoint debugging
Malloc allocates memory space for receiving blocks
Copy the block to the newly allocated memory by memmove
Set the block object type to heap block, result-> ISA = _NSConcreteMallocBlock
4.3. block
Three layerscopy
It is said that this is, the interview does not zha ask, but with brothers drink boast force easy to say the technical point 😆
-
- When using
__block
The modified variable is an object
- When using
__block NSString *name = [NSString stringWithFormat: @"XG"];
void(^blockCopy)(void) = ^{
name = @"xiaogu";
NSLog(@ "% @",name);
};
blockCopy();
Copy the code
-
- And then we use
xcrun
get.cpp
file
- And then we use
// name the initial assignment __Block_byref_name_0 modifier. (Struct assignment, corresponding to __Block_byref_name_0)
__attribute__((__blocks__(byref))) __Block_byref_name_0 name = {
(void*)0,
(__Block_byref_name_0 *)&name,
33554432.sizeof(__Block_byref_name_0), __Block_byref_id_object_copy_131, __Block_byref_id_object_dispose_131, ((NSString * _Nonnull (*)(id, SEL, NSString * _Nonnull, ...) ) (void *)objc_msgSend)((id)objc_getClass("NSString"), sel_registerName("stringWithFormat:"), (NSString *)&__NSConstantStringImpl__var_folders_6j_hfrbcdq96lsbr8vr1qjw1fkm0000gn_T_main_b45ce1_mi_0)
};
// the __Block_byref_name_0 structure
struct __Block_byref_name_0 {
void *__isa;
__Block_byref_name_0 *__forwarding;
int __flags;
int __size;
void (*__Block_byref_id_object_copy)(void*, void*);
void (*__Block_byref_id_object_dispose)(void*);
NSString *name;
};
static void __Block_byref_id_object_copy_131(void *dst, void *src) {
_Block_object_assign((char*)dst + 40, * (void((* *)char*)src + 40), 131);
}
static void __Block_byref_id_object_dispose_131(void *src) {
_Block_object_dispose(*(void((* *)char*)src + 40), 131);
}
/ / block, block
// This will not be mentioned ~ after all, brothers already have the conditions to explore, ~ as mentioned above, memory copy will occur.
void(*blockCopy)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_name_0 *)&name, 570425344));
((void (*)(__block_impl *))((__block_impl *)blockCopy)->FuncPtr)((__block_impl *)blockCopy);
Copy the code
I’m debugging with a source, so it’s easier to understand
-
- To summarize it briefly: Pass
__block
Modifier, and the variable is an objectcopy
-
3.1. The first layer of copy is _Block_copy –> its own copy –> slave stack –> heap
-
Copy: _Block_byref_copy–> Copy the modified object to the Block_byref structure type
-
3.3. Layer 3 copy:_Block_object_assign, which modifies __Block_byref_id_object_copy_131 for the current __block object
- To summarize it briefly: Pass
OK,, ah, the end of the year, very busy, I have to work overtime. O (╥ man ╥) o