1、block可以修改外部变量吗?
在block内如何修改block外部变量引发的思考:为什么直接就可以修改全局变量?使用__block才可以修改局部变量?
__block int a = 1;
void (^foo)(void) = ^{
a = 2;
};
foo(); //这里,a的值被修改为2
我们都知道:block不允许修改外部变量的值,这里所说的外部变量的值,指的是栈中指针的内存地址。__block 所起到的作用就是只要观察到该变量被 block 所持有,就将“外部变量”在栈中的内存地址放到了堆中。进而在block内部也可以修改外部变量的值。
__block int a = 1;
NSLog(@"定义前:%p", &a); //栈区
void (^foo)(void) = ^{
a = 2;
NSLog(@"block内部:%p", &a); //堆区
};
NSLog(@"定义后:%p", &a); //堆区
foo();
这也证实了:a 在定义前是栈区,但只要进入了 block 区域,就变成了堆区。这才是 __block 关键字的真正作用。
NSMutableString *s = [NSMutableString stringWithString:@"Tom"];
void (^foo)(void) = ^{
s.string = @"Jerry"; //修改s中string成功(可以理解为s在栈区,s.tring在堆区)
s = [NSMutableString stringWithString:@"William"];// 这时报错,不允许修改
};
foo();
这里的s已经由基本数据类型,变成了对象类型。block会对对象类型的指针进行copy,copy到堆中,但并不会改变该指针所指向的堆中的地址,所以在上面的示例代码中,block体内修改的实际是s指向的堆中的内容。
2、@synthesize和@dynamic是什么?用法?
在声明property属性后(@property本质 = ivar+getter+setter),有2种实现选择
-
@synthesize
编译器期间,让编译器自动生成getter/setter方法。
当有自定义的存或取方法时,自定义会屏蔽自动生成该方法 -
@dynamic
告诉编译器,不自动生成getter/setter方法,避免编译期间产生警告
然后由自己实现存取方法
或存取方法在运行时动态创建绑定:主要使用在CoreData的实现NSManagedObject子类时使用,由Core Data框架在程序运行的时动态生成子类属性
dynamic告诉编译器不要自动创建setter、getter方法,由用户手动去实现,注意如果此时会找不到_(属性名)的实例对象,只能self.(属性名)。
synthesize如果你没有手动实现setter方法和getter方法,那么在编译的时候编译器会自动为你加上这两个方法。
如果没有声明,默认就是@synthesize 属性名 = _属性名;
使用场景:
synthesize 可以在需要同时实现set和get方法时声明 ;修改实例对象的名称等
dynamic 需要自己手动实现set和get方法时去声明,注意一定要去实现,不然调用set或get时会导致程序崩溃
3、自动释放池中的变量什么时候释放
自动释放池其实会在其作用域结束时释放池子,所有在池中的变量都会执行一次release操作,所以如果在池子中的变量执行过release操作后引用计数仍然大于0,那么就不会被释放,反之为0就会被释放,所以自动释放池中的变量也不一定出了池作用域后就会被释放的。
详细答案:http://blog.csdn.net/peixuan197/article/details/47318011
网友评论