协议
id <Proctocol> obj
只是编译器中的语法,与 NSString * 等标识没有区别
编译时仍然是 id 类型,只是给编译器类型检查上的方便
-
声明
@protocol Foo <Xyzzy, NSObject> //如果实现 Foo, 必须实现 Xyzzy 和 NSObject 协议中的方法(类似于父协议) - (void)someMethod; - (void)methodWithArgument: (BOOL)argument; @optional //optional 标记下方的方法为可选,否则必须实现 @property (readonly) int readonlyProperty; @required //这样下面两个方法/属性仍然必须实现 @property NSString *readwriteProperty; - (int)methodThatReturnsSomething; @end
-
NSObject 协议
里面的方法和 NSObject 类中的方法几乎完全一致。有时候为了让非 NSObject 类实现一些如内省的方法(很少用到)
-
@protocol 的位置
头文件(可以是需要实现该协议的类的头文件,也可以是独立的)
-
遵循协议:
#import "Foo.h" @interface MyClass : NSObject <Foo> //实现所有 Foo 的 require 方法 @end
-
特性
- 可以作为参数
- 不像 NSString * 可以知道某个类的所有方法,也不像 id 一样什么都不知道,类似于一个折中的静态类型
- 编译上不会对代码产生任何区别,只是方便编译器的代码提示等
-
用途
- 委托、数据源
Block
Block 是一段代码快,可以嵌入其他代码中
可以作为参数传递,也可以放在 NSArray 里
在其他语言中常被称为闭包
-
示例
[aDictionary enumerateKeyAndObjectsUsingBlock: ^(id key, id value, BOOL *stop) { //^returnType(arg1, arg2...) {//代码} 是 block 的基本形态 //如果返回值可以被推断,可以不用显式写出 //如果没有参数,可以连括号也省略 NSLog(@"value for key %@ is %@", key, value); if ([@"ENOUGH" isEqualToString: key]) { *stop = YES; } }] //这段代码会对 aDictionary 中的全部键值对循环执行这个 block
-
值捕获
block 可以捕获在 block 之前被声明的变量,但该变量是只读的(在执行 block 时被保存在栈中)
如果要修改这个变量,在变量声明之前加上 __block(将这个变量移到堆中)
-
可存储性
block 可以像对象一样被存放到 NSArray、NSDictionary 中
@property (nonatomic, strong) NSMutableArray *myBlocks; [self.myBlocks addObject: ^ { [self doSomething]; }]
-
循环引用
每次在 block 中向一个对象发送信息时,都会创建一个指向该变量的强指针(保存到 block 超出范围时)。
如果在 block 中对 self 发送信息,则 self 保存了对 block 的强指针,block 保存了对 self 的强指针,就会造成循环引用导致两者都无法从堆中被释放。
解决方法:
__weak MyClass *weakSelf = self; //使用一个弱指针的引用 [self.myBlocks addObject: ^ { [weakSelf doSomething]; }]
- 用途
- 枚举
- 动画
- 排序
- 通知
- completion handler
动画
-
任意时刻都可以对视图的三个属性做动画操作
- frame
- transform(移动距离、旋转和缩放比例)
- alpha(透明度)
-
方法
//注意这是一个 UIView 的类方法 + (void)animateWithDuration: (NSTimeInterval)duration //持续时间 delay: (NSTimeInterval)delay //延迟时间 options: (UIViewAnimationOptions)options //选项 animations: (void (^)(void))animations //修改上述三个属性 completion: (void (^)(BOOL finished))compeltion; //处理 //示例:视图的淡出消失 [UIView animateWithDuration: 3.0 delay: 0.0 options: UIViewAnimationOptionBeginFromCurrentState //这个选项表示如果是在其他动画的执行过程中打断其进程,从打断的状态继续 //比如前一个动画的 alpha 从0.7变为0,变化到0.2时被打断,从0.2继续 animations: ^{myView.alpha = 0.0} //修改会立刻生效 completion: ^(BOOL fin) { if (fin) [myView removeFromSuperview]; //如果动画没有正常结束(比如被另一个动画打断,这里的 fin 就是 false) } ];
对视图自身属性的修改会立即完成,但是动画会持续 duration 时间
-
有时候会想要让整个视图一起被修改(比如翻转),或者要动画化非上述三个属性的修改操作
+ (void)transitionWithView : (UIView *)view duration : (NSTimeInterval)duration options : (UIViewAnimationOptions)options animations : (void (^)(void))animations //修改属性 completion : (void (^)(BOOL finished))completion; /* options: UIViewAnimationOptionsTransitionFlipFrom{Lect, Right, Top, Bottom} UIViewAnimationOptionsTransitionCrossDissolve UIViewAnimationOptionsTransitionCurl{Up, Down} */
-
如果需要改变视图的层级
使用 transitionFromView 方法(类方法)
- dynamic animation 动力动画
定义一些物理效果,应用于要添加动画效果的视图,然后会被立刻执行
//创建一个 UIDynamicAnimator 动力动画者
UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:aView];
//aView 必须是视图的顶级视图(Top)
//创建并添加 UIDynamicBehaviors(重力、碰撞等)到动力动画者中
UIGravityBehavior *gravity = [[UIGravityBehavior alloc] init];
[animator addBehavior:gravity];
UICollisionBehavior *collider = [[UICollisionBehavior alloc] init];
[animator addBehavior:collider];
//创建并添加 UIDynamicItems (通常是 UIView) 到动力行为中
id <UIDynamicItem> item1 = ...;
id <UIDynamicItem> item2 = ...;
[gravity addItem:item1];
[collider addItem:item1];
[gravity addItem:item2];
@protocol UIDynamicItem
@property (readonly) CGRect bounds;
@property (readwrite) CGPoint center;
@property (readwrite) CGAffineTransform transform;
@end
//如果 animator 在执行的时候需要修改 center 或 transform,需要调用 UIDynamicAnimator 的下述方法
- (void)updateItemUsingCurrentState: (id <UIDynamicItem) item;
-
UIGravityBehavior - 重力行为
- @property CGFloat angle
- @property CGFloat magnitude (1.0表示 1000p/s/s 加速度)
-
UICollisionBehavior - 碰撞行为
-
@property UICollisionBehaviorMode collisionMode(Items, Boundaries, 缺省为 Everything)
决定 Item 是互相碰撞时还是碰到边界时被弹开
@property BOOL translatesReferenceBoundsIntoBoundary;
将参考视图的边界添加到弹性边界,碰到会被弹开
-
UIAttachmentBehavior - 吸附行为
UISnapBehavior - 速甩行为
UIPushBehavior - 推动行为
-
UIDynamicItemBehavior
- 控制 item 的内在行为(摩擦力、密度等)
-
block 属性(所有的 Behavior 都有)
一个无返回值无参数的闭包,当某个 behavior 被执行的时候,这个 block 就会被调用