self.demoView.center = CGPointMake(self.view.center.x, 0); // 此方法会立即执行动画 block [UIView animateWithDuration:2.0 delay:0 usingSpringWithDamping:0.3 initialSpringVelocity:10 options:0 animations:^{ NSLog(@"动画开始"); self.demoView.center = self.view.center; } completion:^(BOOL finished) { // 会在动画结束后执行 NSLog(@"动画完成"); }]; NSLog(@"come here");
block
- (void)blockDemo1 { // 定义block // 类型 变量名 = 值 void (^block)() = ^ { NSLog(@"Hello block"); }; // 执行 block(); }
使用
inlineBlock
可以快速定义block
,不过block
一定要过关
- (void)blockDemo2 { void (^block)() = ^ { NSLog(@"Hello block"); }; [self demoBlock:block]; } /// 演示 block 当作参数传递 - (void)demoBlock:(void (^)())completion { NSLog(@"干点什么"); completion(); }
- (void)blockDemo3 { // 栈区变量 int i = 10; NSLog(@"%p", &i); void (^block)() = ^ { // 定义 block 的时候会对栈区变量进行一次 copy NSLog(@"Hello block %d %p", i, &i); }; [self demoBlock:block]; }
如果 block 中使用了外部变量,会对外部变量做一次
copy
- (void)blockDemo4 { // 栈区变量 __block int i = 10; NSLog(@"%p", &i); void (^block)() = ^ { // 定义 block 的时候会对栈区变量进行一次 copy NSLog(@"Hello block %d %p", i, &i); i = 20; }; NSLog(@"block 定义完成 %p %d", &i, i); [self demoBlock:block]; NSLog(@"===>%d", i); }
如果要在 block 内部修改栈区变量,需要使用 __block
修饰符,并且定义 block 之后,栈区变量的地址会变化为堆区地址block 的内存位置
@property (nonatomic, copy) void (^myBlock)();
- (void)blockDemo5 { int i = 10; void (^block)() = ^ { NSLog(@"i --- %d", i); }; NSLog(@"%@", block); self.myBlock = block; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"%@", self.myBlock); }
注意:虽然目前 ARC 编译器在设置属性时,已经替程序员复制了 block,但是定义 block
时,仍然建议使用 copy
属性
// 面试题 - (void)blockDemo4 { int i = 10; // 提问:输出是几? // 10,定义 block 的时候,10已经被复制到堆中了 void (^block)() = ^ { NSLog(@"%d", i); }; i = 20; block(); }
问:block在哪里?=> 全局区
- (void)blockDemo5 { // 问:block在哪里?=> 全局区 // 原因:block 中没有使用任何的外部变量,不会因为任何外部因素而改变 // 会保存在全局区 void (^block)() = ^ { NSLog(@"hello world"); }; NSLog(@"%@", block); }
问:block在哪里?=> 堆区
- (void)blockDemo6 { int i = 10; // 问:block在哪里?=> 堆区 // 原因:因为用到了外部变量,而block准备好的代码,在`需要的时候`被执行 // 调用方并不知道 block 什么时候会被调用 // MRC 开发,block 在栈区,因为 MRC 的所有内存管理由程序员负责 // ARC 开发,block 之所以在堆区,是因为编译器帮我们实现的 // 问:为什么block属性要用 copy? void (^block)() = ^ { NSLog(@"hello %d", i); }; NSLog(@"%@", block); // 在定义 block 属性的时候,必须使用 copy,这样在设置数值的时候,可以将栈区的 block 复制到堆中 self.myBlock = block; NSLog(@"%@", self.myBlock); }
原文:http://www.cnblogs.com/r360/p/4931661.html