[QiShare team] [QiShare team] [QiShare team] [QiShare team] [QiShare team] [QiShare team
Introduction: These articles are part of an effort to delve into Effective Objective-C 2.0. They include opinions from the author and from the editor, as well as some demos. Hope to help you quickly understand the essence of the original author with concise words. Here, the QiShare team pays tribute to original author Matt Galloway.
The table of contents is as follows: IOS write high-quality Objective-C code (1) iOS write high-quality Objective-C code (2) iOS write high-quality Objective-C code (3) iOS write high-quality Objective-C code (4) iOS Write high-quality Objective-C code for iOS (6) Write high-quality Objective-C code for iOS (7)
The topic of this article is “How blocks work and How they work” in iOS.
A brief introduction to today’s hero: Block.
- Block: A “lexical closure” through which a developer passes a block of code as an object.
Understanding the concept of “block” :
1. Block data structure:
Using the clang command line tool (OC to C++), let’s take a look at the internal data structure of the block.
struct Block_descriptor { unsigned long int reserved; unsigned long int size; void (*copy)(void *dst, void *src); void (*dispose)(void *); }; struct Block_layout { void *isa; int flags; int reserved; void (*invoke)(void *, ...) ; struct Block_descriptor *descriptor; /* Imported variables. */ };Copy the code
Block_layout isa structure that contains an isa pointer to the Class object. There is also a function pointer that points to the block’s implementation code.
2. There are three types of blocks: global block, stack block, and heap block.
Blocks are divided into three types based on their location in memory:
type | Memory location | introduce |
---|---|---|
__NSStackBlock__ | The stack area | Stack valid, out of the stack after destruction. |
__NSMallocBlock__ | The heap area | Copy to the heap space. It can be used outside of the defined scope. |
__NSGlobalBlock__ | The global area | Without capturing any external variables, all information is determined at the compiler. |
- 1. NSStackBlock:Stack blocks are stored in the stack area, out of scope, on the stack
block
And declarative_block
Will be destroyed.
Such as:
__block NSString *name = @"QiShare";
void (^block)(void) = ^{
NSLog(@"%@ is an iOS team which loves to share technology.", name);
};
NSLog(@"block = %@", block);
Copy the code
Note: When an external variable needs to be modified or accessed from within a block, the external variable needs to be modified with an additional __block modifier. Otherwise, it cannot be modified.
Let’s take a look at printing:
What? __NSMallocBlock__? That’s because the compiler automatically added a copy operation for us in ARC.
Set Objective-C Automatic Reference Counting = NO. Take a look at printing:
- 2. NSMallocBlock heap block: The heap block memory is located in the heap and is still available when the variable scope ends.
From the example above: Under ARC, block will be copy by default: __NSMallocBlock__.
- NSGlobalBlock: There are no external objects in the block. The required memory is determined at compile time. Memory is located in the global area. Like a singleton, copy is an empty operation.
Such as:
void (^qiShare)(void) = ^{
NSLog(@"We love sharing.");
};
NSLog(@"% @",qiShare);
Copy the code
Create a typedef for a common block type
To increase the readability and extensibility of your code, you need to give common blocks individual names.
Using typedefs as aliases for blocks also makes it easier to use block variables. For example:
- (void)getDataWithToken:(NSString *)token success:(void (^)(id responseDic))success; / /! Typedef void (^SuccessBlock)(id responseDic); - (void)getDataWithToken:(NSString *)token success:(SuccessBlock)success;Copy the code
Use handler blocks to reduce code dispersion
In our iOS development, it’s common to execute tasks asynchronously, wait until the task is finished, and then tell objects to call methods. There are three ways to do this:
- First: use NSNotificationCenter:
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
- Second: Use a delegate protocol: See Writing High-quality Objective-C code for iOS (Part 4).
- Third: Using block callbacks: Directly pass the block object as an argument to the related method.
For example: The API design and use of AFNetworking is the Block callback
- Interface design:
- (NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure {
return [self POST:URLString parameters:parameters progress:nil success:success failure:failure];
}
Copy the code
- Use:
AFHTTPSessionManager *manger =[AFHTTPSessionManager manager]; NSString *urlString = @""; NSMutableDictionary *parameter= @{@"":@"",@"":@""}; [manger POST:urlString parameters:parameter success:^(NSURLSessionDataTask * _Nonnull task, } (NSURLSessionDataTask * _Nullable responseObject) {NSURLSessionDataTask * _Nullable responseObject); NSError * _Nonnull error) { NSLog(@"%@",error); }]; }Copy the code
Avoid circular references when a block refers to an object it belongs to
In our daily development, blocks can easily leak memory if not used properly.
- Reason: If
block
By the current ViewController (self
If the block holds a ViewController (self
), creating a circular reference. - Solution: In
block
Outside ofweakeningself
And then inside the blockstrengtheningweakenedweakSelf
For Example:
__weak typeof(self) weakSelf = self;
[self.operationQueue addOperationWithBlock:^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (completionHandler) {
KTVHCLogDataStorage(@"serial reader async end, %@", request.URLString); completionHandler([strongSelf serialReaderWithRequest:request]); }}];Copy the code
Of course, not all blocks that use self should be first weakened into weakSelf and then strengthened into strongSelf. As long as the block is not held by self, self can be used in the block. For example:
[QiNetwork requestBlock:^(id responsObject) {
NSLog(@"% @",self.name);
}];
Copy the code
Tips: For information about memory leak detection, see iOS Memory leak detection method and cause analysis
QiShare(Simple book) QiShare(digging gold) QiShare(Zhihu) QiShare(GitHub) QiShare(CocoaChina) QiShare(StackOverflow) QiShare(wechat public account)
Recommended article: Qiwu Weekly 278 iOS push notification