CS193P-2013 Lecture 8 协议、block、动画

协议

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 就会被调用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容