Skip to content

Instantly share code, notes, and snippets.

@wanyakun
Created November 1, 2016 03:18
Show Gist options
  • Save wanyakun/b2354dcdfbe7ee85c981d0ac29bdeab0 to your computer and use it in GitHub Desktop.
Save wanyakun/b2354dcdfbe7ee85c981d0ac29bdeab0 to your computer and use it in GitHub Desktop.
Block块代码示例,以及Clang编译后的解释,以及将Clang编译后的代码贴到block之上,并进行注释
//
// main.m
// BlockDemo
//
// Created by wanyakun on 16/7/19.
// Copyright © 2016年 com.ucaiyuan. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "MyObject.h"
/**
* Block实体形式如下:^(传入参数列){行为主体};
*/
void block1() {
int result = ^(int a){
return a*a;
} (5);
NSLog(@"block1 -> %d", result);
}
/**
* Block Pointer是这样定义的:回传值(^名字)(参数列);
*/
void block2() {
int (^block)(int);
block = ^(int a){
return a*a;
};
int result = block(6);
NSLog(@"block2 -> %d", result);
}
/**
* Block里面可以读取同一类型的outA的值,result is 11
*/
void block3() {
int outA = 8;
int (^block)(int) = ^(int a) {
return outA + a;
};
int result = block(3);
NSLog(@"block3 -> result = %d", result);
}
/**
* 调用过程void block4, 其中第二句调用__block4_block_impl_0构造函数初始化结构体:__block4_block_impl_0((void *)__block4_block_func_0, &__block4_block_desc_0_DATA, outA)得到__block4_block_impl_0类型变量赋值给block,然后执行block->FuncPtr。事实上,使用clang编译后得到的C代码,发现结构体函数使用_outA初始化结构体中的outA变量,然后再改变outA的值,在真正调用FuncPtr的时候是使用结构体中的outA的值,所以改变outA的值,result仍是11
struct __block4_block_impl_0 {
struct __block_impl impl;
struct __block4_block_desc_0* Desc;
int outA;
__block4_block_impl_0(void *fp, struct __block4_block_desc_0 *desc, int _outA, int flags=0) : outA(_outA) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static int __block4_block_func_0(struct __block4_block_impl_0 *__cself, int a) {
int outA = __cself->outA; // bound by copy
return outA + a;
}
static struct __block4_block_desc_0 {
size_t reserved;
size_t Block_size;
} __block4_block_desc_0_DATA = { 0, sizeof(struct __block4_block_impl_0)};
void block4() {
int outA = 8;
int (*block)(int) = ((int (*)(int))&__block4_block_impl_0((void *)__block4_block_func_0, &__block4_block_desc_0_DATA, outA));
outA = 5;
int result = ((int (*)(__block_impl *, int))((__block_impl *)block)->FuncPtr)((__block_impl *)block, 3);
NSLog((NSString *)&__NSConstantStringImpl__var_folders_0y_zzzq899s2js3g0f8d71jvbnm0000gp_T_main_2d0f53_mi_3, result);
}
*/
void block4() {
int outA = 8;
int (^block)(int) = ^(int a) {
return outA + a;
};
outA = 5;
int result = block(3);
NSLog(@"block4 -> result = %d", result);
}
/**
* block主体中用到的变量如果是个指针,它的值在block中是可以被改变的, mutableArray在block中被更改,变为{@"one", @"two"}, clang中代码发现是指针传递,保存到结构体中的mutableArray
struct __block5_block_impl_0 {
struct __block_impl impl;
struct __block5_block_desc_0* Desc;
NSMutableArray *mutableArray;
__block5_block_impl_0(void *fp, struct __block5_block_desc_0 *desc, NSMutableArray *_mutableArray, int flags=0) : mutableArray(_mutableArray) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __block5_block_func_0(struct __block5_block_impl_0 *__cself) {
NSMutableArray *mutableArray = __cself->mutableArray; // bound by copy
((void (*)(id, SEL))(void *)objc_msgSend)((id)mutableArray, sel_registerName("removeLastObject"));
}
static void __block5_block_copy_0(struct __block5_block_impl_0*dst, struct __block5_block_impl_0*src) {_Block_object_assign((void*)&dst->mutableArray, (void*)src->mutableArray, 3);}
static void __block5_block_dispose_0(struct __block5_block_impl_0*src) {_Block_object_dispose((void*)src->mutableArray, 3);}
static struct __block5_block_desc_0 {
size_t reserved;
size_t Block_size;
void (*copy)(struct __block5_block_impl_0*, struct __block5_block_impl_0*);
void (*dispose)(struct __block5_block_impl_0*);
} __block5_block_desc_0_DATA = { 0, sizeof(struct __block5_block_impl_0), __block5_block_copy_0, __block5_block_dispose_0};
void block5() {
NSMutableArray *mutableArray = ((NSMutableArray *(*)(id, SEL, ObjectType, ...))(void *)objc_msgSend)((id)objc_getClass("NSMutableArray"), sel_registerName("arrayWithObjects:"), (id)(NSString *)&__NSConstantStringImpl__var_folders_0y_zzzq899s2js3g0f8d71jvbnm0000gp_T_main_2d0f53_mi_4, (NSString *)&__NSConstantStringImpl__var_folders_0y_zzzq899s2js3g0f8d71jvbnm0000gp_T_main_2d0f53_mi_5, (NSString *)&__NSConstantStringImpl__var_folders_0y_zzzq899s2js3g0f8d71jvbnm0000gp_T_main_2d0f53_mi_6, __null);
void (*block)() = ((void (*)())&__block5_block_impl_0((void *)__block5_block_func_0, &__block5_block_desc_0_DATA, mutableArray, 570425344));
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
NSLog((NSString *)&__NSConstantStringImpl__var_folders_0y_zzzq899s2js3g0f8d71jvbnm0000gp_T_main_2d0f53_mi_7, mutableArray);
}
*/
void block5() {
NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil];
void (^block)() = ^() {
[mutableArray removeLastObject];
};
block();
NSLog(@"block5 -> array:%@", mutableArray);
}
/**
* 直接存取static类型的变量,甚至可以直接在block里面修改outA的值,clang中发现是使用outA指针引用,保存到结构体中的outA指针,在__block6_block_func_0中也是使用的指针,所以能够改变outA的值
struct __block6_block_impl_0 {
struct __block_impl impl;
struct __block6_block_desc_0* Desc;
int *outA;
__block6_block_impl_0(void *fp, struct __block6_block_desc_0 *desc, int *_outA, int flags=0) : outA(_outA) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static int __block6_block_func_0(struct __block6_block_impl_0 *__cself, int a) {
int *outA = __cself->outA; // bound by copy
(*outA)++;
return (*outA) + a;
}
static struct __block6_block_desc_0 {
size_t reserved;
size_t Block_size;
} __block6_block_desc_0_DATA = { 0, sizeof(struct __block6_block_impl_0)};
void block6() {
static int outA = 8;
int (*block)(int) = ((int (*)(int))&__block6_block_impl_0((void *)__block6_block_func_0, &__block6_block_desc_0_DATA, &outA));
outA = 5;
int result = ((int (*)(__block_impl *, int))((__block_impl *)block)->FuncPtr)((__block_impl *)block, 3);
NSLog((NSString *)&__NSConstantStringImpl__var_folders_0y_zzzq899s2js3g0f8d71jvbnm0000gp_T_main_2d0f53_mi_8, result);
}
*/
void block6() {
static int outA = 8;
int (^block)(int) = ^(int a) {
outA++;
return outA + a;
};
outA = 5;
int result = block(3);
NSLog(@"block6 -> result = %d", result);
}
/**
* 在某个变量前面如果加上修饰字__block的话,这个变量就称作block variable,那么多在block里面就可以任意修改此变量的值,clang编译后的代码可以看出,outA会被封装为__Block_byref_outA_0结构体,并通过指针引用传递到block结构体内部
struct __Block_byref_outA_0 {
void *__isa;
__Block_byref_outA_0 *__forwarding;
int __flags;
int __size;
int outA;
};
struct __block7_block_impl_0 {
struct __block_impl impl;
struct __block7_block_desc_0* Desc;
__Block_byref_outA_0 *outA; // by ref
__block7_block_impl_0(void *fp, struct __block7_block_desc_0 *desc, __Block_byref_outA_0 *_outA, int flags=0) : outA(_outA->__forwarding) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static int __block7_block_func_0(struct __block7_block_impl_0 *__cself, int a) {
__Block_byref_outA_0 *outA = __cself->outA; // bound by ref
(outA->__forwarding->outA)++;
return (outA->__forwarding->outA) + a;
}
static void __block7_block_copy_0(struct __block7_block_impl_0*dst, struct __block7_block_impl_0*src) {_Block_object_assign((void*)&dst->outA, (void*)src->outA, 8);}
static void __block7_block_dispose_0(struct __block7_block_impl_0*src) {_Block_object_dispose((void*)src->outA, 8);}
static struct __block7_block_desc_0 {
size_t reserved;
size_t Block_size;
void (*copy)(struct __block7_block_impl_0*, struct __block7_block_impl_0*);
void (*dispose)(struct __block7_block_impl_0*);
} __block7_block_desc_0_DATA = { 0, sizeof(struct __block7_block_impl_0), __block7_block_copy_0, __block7_block_dispose_0};
void block7() {
__attribute__((__blocks__(byref))) __Block_byref_outA_0 outA = {(void*)0,(__Block_byref_outA_0 *)&outA, 0, sizeof(__Block_byref_outA_0), 8};
int (*block)(int) = ((int (*)(int))&__block7_block_impl_0((void *)__block7_block_func_0, &__block7_block_desc_0_DATA, (__Block_byref_outA_0 *)&outA, 570425344));
int result = ((int (*)(__block_impl *, int))((__block_impl *)block)->FuncPtr)((__block_impl *)block, 3);
NSLog((NSString *)&__NSConstantStringImpl__var_folders_0y_zzzq899s2js3g0f8d71jvbnm0000gp_T_main_2d0f53_mi_9, result);
}
*/
void block7() {
__block int outA = 8;
int (^block)(int) = ^(int a) {
outA++;
return outA + a;
};
int result = block(3);
NSLog(@"block7 -> result = %d", result);
}
void block8() {
__block NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil];
void (^block)() = ^() {
[mutableArray removeLastObject];
};
block();
NSLog(@"block8 -> array:%@", mutableArray);
}
void block9() {
__block int val = 0;
void (^blk)(void)= ^{
++val;
};
++val;
blk();
NSLog(@"%d", val);
}
//typedef void(^blk_t)(id obj);
//blk_t blk;
//
//void captureObject() {
// id array = [[NSMutableArray alloc] init];
// blk = ^(id obj) {
// [array addObject:obj];
// NSLog(@"array count = %ld", [array count]);
// };
//}
//
//
//void block10() {
// captureObject();
//
// blk([[NSObject alloc] init]);
// blk([[NSObject alloc] init]);
// blk([[NSObject alloc] init]);
//}
typedef void (^eBlock)();
eBlock exampleE_getBlock() {
char e = 'E';
void (^block)() = ^{
printf("%c\n", e);
};
return block;
}
void exampleE() {
eBlock block = exampleE_getBlock();
block();
}
void memory1() {
NSMutableString *str = [@"string1" mutableCopy];
NSMutableString *str2 = [str mutableCopy];
[str appendString:@"__str"];
[str appendString:@"__str2"];
NSLog(@"str1:%@ str2:%@", str, str2);
NSLog(@"str1:%p str2:%p", str, str2);
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
// block1();
// block2();
// block3();
// block4();
// block5();
// block6();
// block7();
// block8();
// block9();
// block10();
// exampleE();
//
id myObject = [[MyObject alloc] init];
NSLog(@"%@", myObject);
memory1();
}
return 0;
}
//
// MyObject.h
// BlockDemo
//
// Created by wanyakun on 16/8/1.
// Copyright © 2016年 com.ucaiyuan. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface MyObject : NSObject
@end
//
// MyObject.m
// BlockDemo
//
// Created by wanyakun on 16/8/1.
// Copyright © 2016年 com.ucaiyuan. All rights reserved.
//
#import "MyObject.h"
@interface MyObject ()
@property (nonatomic, copy) NSString *str;
@end
@implementation MyObject
- (instancetype)init {
self = [super init];
_str = @"123";
[self block];
[self instanceMethod];
[MyObject classMethod];
return self;
}
- (void)block {
__weak __typeof(self) weakSelf = self;
void (^block)() = ^() {
__strong __typeof(self) strongSelf = weakSelf;
NSLog(@"block str:%@", strongSelf.str);
};
block();
}
- (void)instanceMethod {
NSLog(@"this is an instance method");
}
+ (void)classMethod {
NSLog(@"this is an class method");
}
- (void)dealloc {
NSLog(@"dealloc");
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment