• (8/18)重学Standford_iOS7开发_协议、block、动画_课程笔记


    第八课:

      1、协议

        另一种安全处理id类型的方式如:id <MyProtocol> obj

        a.声明

    //协议一般放于.h文件中或者在类的.h文件中
    
    @protocol Foo <Xyzzy, NSObject>//<>中的内容表示还需实现自哪些协议,所有协议的根协议一般都是NSObject
    - (void)someMethod;//默认为必须实现的方法
    @optional//可选方法声明
    - (void)methodWithArgument:(BOOL)argument;
    @required
    @property (readonly) int readonlyProperty; //只有getter在协议中
    @property NSString *readwriteProperty; //getter与setter都在协议中
     - (int)methodThatReturnsSomething;
    @end

        b.在类中实现协议

    #import “Foo.h” 
    @interface MyClass : NSObject <Foo> 
    //(do not have to declare Foo’s methods again here, it’s implicit that you implement it)
    @end
    
    //或者私有实现
    @interface MyClass() <Foo>
    @end
    @implementation MyClass
    //@required methods here! 
    @end

        c.用途

          ①委托

          ②数据源

    //UI与controller盲通信的方式
    @property (nonatomic, weak) id <UISomeObjectDelegate> delegate;
    @property (nonatomic, weak) id <UISomeObjectDataSource> dataSource;

          ③动画

      2、Block(来源于API文档)

        实际上为一段代码块,类似于C语言中的函数指针

        a.声明

    int multiplier = 7;
    int (^myBlock)(int) = ^(int num) {
        return num * multiplier;
    };
    //int 为block返回值 
    //^表示为此为代码块
    //myBlock为此代码块名
    //int 为参数类型
    //等号右边为block实现

        block可以使用和他的同一范围内声明的变量,使用block与使用C函数类似

    int multiplier = 7;
    int (^myBlock)(int) = ^(int num) {
        return num * multiplier;
    };
     
    printf("%d", myBlock(3));
    // prints "21"

        b.直接使用block

          block可以省略block声明直接使用

    char *myCharacters[3] = { "TomJohn", "George", "Charles Condomine" };
    
    //直接使用block作为参数 
    qsort_b(myCharacters, 3, sizeof(char *), ^(const void *l, const void *r) {
        char *left = *(char **)l;
        char *right = *(char **)r;
        return strncmp(left, right, 1);
    });
     
    // myCharacters is now { "Charles Condomine", "George", "TomJohn" } 

        c.Cocoa中使用block

    NSArray *stringsArray = @[ @"string 1",
                               @"String 21",
                               @"string 12",
                               @"String 11",
                               @"String 02" ];
     
    static NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch | NSNumericSearch |
            NSWidthInsensitiveSearch | NSForcedOrderingSearch;
    NSLocale *currentLocale = [NSLocale currentLocale];
     
    //比较器为代码块
    NSComparator finderSortBlock = ^(id string1, id string2) {
        NSRange string1Range = NSMakeRange(0, [string1 length]);
        return [string1 compare:string2 options:comparisonOptions range:string1Range locale:currentLocale];
    };
     
    NSArray *finderSortArray = [stringsArray sortedArrayUsingComparator:finderSortBlock];
    NSLog(@"finderSortArray: %@", finderSortArray);
     
    /*
    Output:
    finderSortArray: (
        "string 1",
        "String 02",
        "String 11",
        "string 12",
        "String 21"
    )
    */

        d.__block变量

          首先看简单的例子

    //直接使用变量
    int x = 123;
     
    void (^printXAndY)(int) = ^(int y) {
        printf("%d %d
    ", x, y);
    };
     
    printXAndY(456); // prints: 123 456
    
    //不可以直接更改变量,此处变量对block来说为只读
    int x = 123;
    void (^printXAndY)(int) = ^(int y) {
        x = x + y; // error
        printf("%d %d
    ", x, y);
    };

          解决方法,引入__block变量

    __block int x = 123; //  x lives in block storage
     
    void (^printXAndY)(int) = ^(int y) {
        x = x + y;
        printf("%d %d
    ", x, y);
    };
    printXAndY(456); // prints: 579 456
    // x is now 579

        e.各种类型的变量在block中的使用

          对于普通局部变量,在block声明时保存其值,之后普通局部变量的改变对block不可见

    //注意block的调用时机
    extern NSInteger CounterGlobal;//block对全局变量有读写权限
    static NSInteger CounterStatic;//静态变量
    {
        NSInteger localCounter = 42;//普通本地变量
        __block char localCharacter;//__block本地变量
     
        void (^aBlock)(void) = ^(void) {
            ++CounterGlobal;
            ++CounterStatic;
            CounterGlobal = localCounter; // localCounter fixed at block creation
            localCharacter = 'a'; // sets localCharacter in enclosing scope
        };
     
        ++localCounter; // unseen by the block,对block不可见,block的值认为42
        localCharacter = 'b';
     
        aBlock(); // execute the block
        // localCharacter now 'a'
    }

        f.对象在block中的使用

    dispatch_async(queue, ^{
        /* 
        block中访问实例变量,instanceVariable为block所在类的实例变量,此时直接访问了实例变量,因此需要对包含它的对象(self)保留
        */
        doSomethingWithObject(_instanceVariable);
    });
     
     
    id localVariable = _instanceVariable;
    dispatch_async(queue, ^{
        /*
        在本地创建了指向实例变量的引用,因此需要保留localVariable而不是self
        */
        doSomethingWithObject(localVariable);
    });

        g.使用typedef声明block

    typedef float (^MyBlockType)(float, float);
     
    MyBlockType myFirstBlock = // ... ;
    MyBlockType mySecondBlock = // ... ;

        h.Memory Cycles 

    //block中引用self,所以有强指针指向self,而block又在self中定义,所以self又有强指针指向block
    [self.myBlocks addObject:^ {
        [self doSomething];
    }];

          解决方法

    __weak MyClass *weakSelf = self; //重新声明为弱引用
    [self.myBlocks addObject:^ {
        [weakSelf doSomething];
    }];

        i.用途

          枚举,动画,排序,通知(Notification),Error handlers,Completion handlers (错误与完成事件的处理,可以理解为回调函数),多线程

      3、动画(Animation)

        a.动画的种类

          Animating views :视图动画,包括移动、缩放、淡入淡出、旋转等

          Animation of View Controller transitions:视图控制器动画,视图的切换等

          Core Animation:核心动画框架

          本节课只涉及视图动画

        b.为视图添加动画的三种方法

          ①通过设置视图属性

            frame

            transform (translation, rotation and scale)

            alpha (opacity) 

           值会立即改变,但动画效果会延时

    + (void)animateWithDuration:(NSTimeInterval)duration
                                      delay:(NSTimeInterval)delay
                                   options:(UIViewAnimationOptions)options
                              animations:(void (^)(void))animations
                              completion:(void (^)(BOOL finished))completion;//适用于常规动画设置
    //example
    [UIView animateWithDuration:3.0
                          delay:0.0
                        options:UIViewAnimationOptionBeginFromCurrentState
                     animations:^{ myView.alpha = 0.0; }
                     completion:^(BOOL fin) { if (fin) [myView removeFromSuperview]; }];//视图在3秒内从父视图淡出,完成动画后并移除自己
    
    + (void)transitionWithView:(UIView *)view
                      duration:(NSTimeInterval)duration
                       options:(UIViewAnimationOptions)options
                    animations:(void (^)(void))animations
                    completion:(void (^)(BOOL finished))completion;//适用于转场动画设置,比如卡牌的翻转
    
    + (void)transitionFromView:(UIView *)fromView
                        toView:(UIView *)toView
                      duration:(NSTimeInterval)duration
                       options:(UIViewAnimationOptions)options
                    completion:(void (^)(BOOL finished))completion;//适用于切换视图动画
    //UIViewAnimationOptions
    
    //常规动画属性设置(可以同时选择多个进行设置)
    UIViewAnimationOptionLayoutSubviews          //父视图变化时自动更新子视图约束@see:http://segmentfault.com/q/1010000002872390 
    UIViewAnimationOptionAllowUserInteraction      //动画时响应用户事件,如 touch等   
    UIViewAnimationOptionBeginFromCurrentState     //从当前状态开始动画,比如此时有动画正在改变属性
    UIViewAnimationOptionRepeat                    //无限制重复动画
    UIViewAnimationOptionAutoreverse               //执行动画回路(动画运行到结束点后仍然以动画方式回到初始点),前提是设置动画无限重复
    UIViewAnimationOptionOverrideInheritedDuration //忽略嵌套动画时间设置
    UIViewAnimationOptionOverrideInheritedCurve    //忽略嵌套动画速度设置
    UIViewAnimationOptionAllowAnimatedContent      //动画过程中重绘视图(注意仅仅适用于转场动画)
    UIViewAnimationOptionShowHideTransitionViews   //视图切换时直接隐藏旧视图、显示新视图,而不是将旧视图从父视图移除(仅仅适用于转场动画)
    UIViewAnimationOptionOverrideInheritedOptions  //不继承父动画设置或动画类型
    
    //动画速度控制(可从其中选择一个设置)
    UIViewAnimationOptionCurveEaseInOut           //动画先缓慢,然后逐渐加速
    UIViewAnimationOptionCurveEaseIn               //动画逐渐变慢
    UIViewAnimationOptionCurveEaseOut              //动画逐渐加速
    UIViewAnimationOptionCurveLinear              //动画匀速执行,默认值
    
    //转场类型(仅适用于转场动画设置,可以从中选择一个进行设置,基本动画、关键帧动画不需要设置)
    UIViewAnimationOptionTransitionNone            //没有转场动画效果
    UIViewAnimationOptionTransitionFlipFromLeft    //从左侧翻转效果
    UIViewAnimationOptionTransitionFlipFromRight   //从右侧翻转效果
    UIViewAnimationOptionTransitionCurlUp          //向后翻页的动画过渡效果
    UIViewAnimationOptionTransitionCurlDown        //向前翻页的动画过渡效果
    UIViewAnimationOptionTransitionCrossDissolve   //旧视图溶解消失显示下一个新视图的效果
    UIViewAnimationOptionTransitionFlipFromTop     //从上方翻转效果
    UIViewAnimationOptionTransitionFlipFromBottom  //从底部翻转效果

          ②Dynamic Animator :动力动画

            实现步骤:a.创建一个UIDynamicAnimator

                 b.向UIDynamicAnimator添加UIDynamicBehaviors(gravity, collisions, etc.)

                 c.向UIDynamicAnimator添加UIDynamicItems(usually UIViews) 

                 d.动画自动运行

    //Create a UIDynamicAnimator
    UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:aView];
    
    //Create and add UIDynamicBehaviors
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] init];
     [animator addBehavior:gravity];
    UICollisionBehavior *collider = [[UICollisionBehavior alloc] init];
     [animator addBehavior:collider];
    
    //Add UIDynamicItems to a UIDynamicBehavior
    id <UIDynamicItem> item1 = ...; 
    id <UIDynamicItem> item2 = ...; 
    [gravity addItem:item1]; 
    [collider addItem:item1]; 
    [gravity addItem:item2];
    //UIDynamicItem 协议
    @protocol UIDynamicItem
    @property (readonly) CGRect bounds;
    @property (readwrite) CGPoint center;
    @property (readwrite) CGAffineTransform transform; 
    @end
    
    //一般UIView即可作为Item,天生实现了UIDynamic协议
    
    //以上属性一般有动画运行时的animator来改变,若需要主动改变,需要调用
    - (void)updateItemUsingCurrentState:(id <UIDynamicItem>)item;

             UIDynamicBehaviors

    //UIGravityBehavior
    @property CGFloat angle;//重力方向,默认向下
    @property CGFloat magnitude; // 1.0 is 1000 points/s/s
    
    //UICollisionBehavior 碰撞
    @property UICollisionBehaviorMode collisionMode; // Items,Boundaries,Everything (default) 
    - (void)addBoundaryWithIdentifier:(NSString *)identifier forPath:(UIBezierPath *)path; //用UIBezierPath自定义碰撞边界
    @property BOOL translatesReferenceBoundsIntoBoundary;//参考视图(动力动画的顶级视图)作为碰撞边界
    
    //UIAttachmentBehavior 吸附行为
    - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)anchor;//以点作为吸附
    - (instancetype)initWithItem:(id <UIDynamicItem>)i1 attachedToItem:(id <UIDynamicItem>)i2;//以动力项作为吸附,两个动力项的吸附
    - (instancetype)initWithItem:(id <UIDynamicItem>)item offsetFromCenter:(CGPoint)offset ... //偏移中心的吸附
    @property (readwrite) CGFloat length; // 吸附的长度
    @property (readwrite) CGPoint anchorPoint; // 吸附点
    @property (readwrite, nonatomic) CGFloat damping; // 锚点移动时的阻尼
    @property (readwrite, nonatomic) CGFloat frequency; // 锚点移动时的频率
    
    //UISnapBehavior 捕捉行为
    - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point;
     @property CGFloat damping;.//移动到锚点时振动的阻尼
    
    //UIPushBehavior 推动行为
    @property UIPushBehaviorMode mode; // Continuous or Instantaneous
    @property CGVector pushDirection;
    @property CGFloat magnitude/angle; // magnitude 1.0 moves a 100x100 view at 100 pts/s/s
    
    //UIDynamicItemBehavior 动力项行为,应用于所有Items
    @property (readwrite, nonatomic) CGFloat elasticity; // 弹力,[0.1]
    @property (readwrite, nonatomic) CGFloat friction; //摩擦力,0表示无摩擦力
    @property (readwrite, nonatomic) CGFloat density; // 密度,默认为1
    @property (readwrite, nonatomic) CGFloat resistance; //线性阻力系数0--CGFLOAT_MAX
    @property (readwrite, nonatomic) CGFloat angularResistance; //角度阻力系数0--CGFLOAT_MAX
    @property (readwrite, nonatomic) BOOL allowsRotation; //是否允许旋转
    - (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;//获取Item速度
    - (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;//获取Item角速度

             创建UIDynamicBehavior子类实现自定义行为

    - (void)addChildBehavior:(UIDynamicBehavior *)behavior;//将其他行为添加到自定义行为中
    @property UIDynamicAnimator *dynamicAnimator;//获取当前行为所在的Animator
    - (void)willMoveToAnimator:(UIDynamicAnimator *)animator;//行为加入到方法或者移除时(此时参数为nil)会调用
    @property (copy) void (^action)(void);//每当行为发生时总会执行此block,注意调用比较频繁的效率问题 

      4、demo

        Dropit:https://github.com/NSLogMeng/Stanford_iOS7_Study/commit/515b76c7ed6e74a7e30108efe6d4c833f33a6e0c

    课程视频地址:网易公开课:http://open.163.com/movie/2014/1/D/L/M9H7S9F1H_M9H80D0DL.html

           或者iTunes U搜索standford课程

  • 相关阅读:
    Linux Shell 1>/dev/null 2>&1 含义
    iSCSI存储的3种连接方式
    Linux Shell远程执行命令(命令行与脚本方式)
    VIM常用命令
    RHEL6.2配置从零开始
    shell 正则表达式与文件名匹配
    Java中判断非空对象.
    Facebook的时序数据库技术(上)
    SpringBoot+SpringCache实现两级缓存(Redis+Caffeine)
    Swagger模型字段排序问题
  • 原文地址:https://www.cnblogs.com/nslogmeng/p/4622995.html
Copyright © 2020-2023  润新知