(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\n", x, y);
};
 
printXAndY(456); // prints: 123 456

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

      解决方法,引入__block变量

__block int x = 123; //  x lives in block storage
 
void (^printXAndY)(int) = ^(int y) {
    x = x + y;
    printf("%d %d\n", 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课程

posted on 2015-07-05 23:56  NSLogMeng  阅读(885)  评论(0编辑  收藏  举报