前言-OC语法篇
我是一名iOS开发者, iOS底层 菜鸟的进阶之路30天。
问题
self在函数中是全局变量还是布局变量?
- 是全局变量,因为他是函数自带的两个参数self _cmd
block的本质
- block本质上也是一个OC对象,它内部也有个isa指针
- block是封装了函数调用以及函数调用环境的OC对象
- 如下图
block变量的截获
- 全局变量没有捕获,因为全局变量直接可以访问
// auto:自动变量,是定义的隐藏关键字,离开作用域(括号)就销毁
auto int age = 10; //等价于 int age = 10;//值传递
static int height = 10;//static修饰的东西,会取地址这个值//指针的传递
void (^block)(void) = ^{
// age的值捕获进来(capture)
NSLog(@"age is %d, height is %d", age, height);
};
age = 20;
height = 20;
block();
- self的捕获
- (void)test {
void (^block)(void) = ^{
NSLog(@"-------%p", self);
};
block();
}
//因为self _cmd是每个类的隐式参数.所以self有被捕获
- (void)test {
void (^block)(void) = ^{
NSLog(@"-------%d", self.name);
};
block();
}
block的三种类型
- 可以通过调用class方法或者isa指针查看具体类型,最终都是继承自NSBlock类型
- NSGlobalBlock ( _NSConcreteGlobalBlock )全局block
- NSStackBlock ( _NSConcreteStackBlock )栈block
- NSMallocBlock ( _NSConcreteMallocBlock )堆block
void (^block)(void) = ^{
NSLog(@"Hello");
};
NSLog(@"%@", [block class]); __NSGlobalBlock__
NSLog(@"%@", [[block class] superclass]); __NSGlobalBlock__
NSLog(@"%@", [[[block class] superclass] superclass]); NSBlock
NSLog(@"%@", [[[[block class] superclass] superclass] superclass]); NSObject
block类型判断
- 变量的区别
int age = 10;//全局变量
int main(int argc, const char * argv[]) {
@autoreleasepool {
int a = 10;//局部变量
NSLog(@"数据段:age %p", &age);//全局变量
NSLog(@"栈:a %p", &a);//局部变量
NSLog(@"堆:obj %p", [[NSObject alloc] init]);//alloc 和malloc出来
NSLog(@"数据段:class %p", [MJPerson class]);
}
}
- 三种block类型 ARC下
//block1:__NSGlobalBlock__ ( _NSConcreteGlobalBlock )全局block
//没有访问外部(auto)变量的为全局block
void (^block1)(void) = ^{
NSLog(@"Hello");
};
//block2:__NSMallocBlock__ ( _NSConcreteMallocBlock )堆block
//堆[person alloc]或者[person malloc]需要我们手动销毁
//在ARC下将栈block进行了一次拷贝操作到堆block
int age = 10;
void (^block2)(void) = ^{
NSLog(@"Hello - %d", age);
};
//block3:__NSStackBlock__ ( _NSConcreteStackBlock )栈block
//会自动销毁
NSLog(@"%@ %@ %@", [block1 class], [block2 class], [^{
NSLog(@"%d", age);
} class]);
block的copy修饰符
-
在ARC环境下,编译器会根据情况自动将栈上的block复制到堆上,比如以下情况
- block作为函数返回值时
- 将block赋值给__strong指针时
- block作为Cocoa API中方法名含有usingBlock的方法参数时
- block作为GCD API的方法参数时
-
MRC下block属性的建议写法
- @property (copy, nonatomic) void (^block)(void);
-
ARC下block属性的建议写法
- @property (strong, nonatomic) void (^block)(void);
- @property (copy, nonatomic) void (^block)(void);