Protocols
协议就是编译器的语法,表达式为:
id <MyProtocol> obj
意思是,声明了一个 id
类型的对象,但是加上了协议信息。这样可以告诉编译器和阅读代码的人更多的代码信息。
声明协议
声明协议的方法与 @interface
一样,我们在 @interface
里放的都是所有的公有方法和属性,或者在 @implement
头部来声明私有的 @interface
。协议只不过把 @interface
换成了 @protocol
。
协议只是方法的声明,没有实现部分。所以 @protocol
没有对应的 @implementation
,我们说的只是方法。
协议中的方法默认是必须实现的。所以如果有人想实现协议中的某个方法,那么就必须实现全部的这些方法。
这些是示例:
@protocol Foo<Xyzzy>
- (void)someMethod;
@optional
- (void)methodWithArgument:(BOOL)argument;
@property (readonly) int readonlyProperty; // getter (only) is part of this protocol
@property NSString *readwriteProperty; // getter and setter are both in the protocol
- (int)methodThatReturnsSomething;
@end
你可以在代码中添加 @optional
来把一部分方法变成可选的。现在上面的代码中只有 - (void)someMethod;
是必须实现的了。
@protocol Foo<Xyzzy>
- (void)someMethod;
@optional
- (void)methodWithArgument:(BOOL)argument;
@required
@property (readonly) int readonlyProperty; // getter (only) is part of this protocol
@property NSString *readwriteProperty; // getter and setter are both in the protocol
- (int)methodThatReturnsSomething;
@end
还可以添加 @required
来标记必须实现的方法,那现在只有 - (void)methodWithArgument:(BOOL)argument;
是可选的了。
Foo
后面的 <Xyzzy>
表示如果你要实现 Foo
的协议那么你同还也必须实现 Xyzzy
协议中全部必须实现的方法。大体上有点像是父协议,但不是继承关系。这里可以添加多个协议,比如 <Xyzzy, NSObject>
。
NSObject 协议
NSObject 协议基本上就是一个包括了 NSObject 类中全部方法的协议。为什么要同时创建一个叫做 NSObject 的协议和一个叫 NSObjetct 的类呢?两者几乎有着完全相同的方法。
是因为我们在声明协议时,有些方法是必须的,但我们还想让实现这个协议的对象(本质上说就是 NSObject 对象)有一个父协议,所以我们直接将 NSObject 中全部的方法放到一个大协议中,然后让 NSObject 来实现这个协议。
协议的使用
在 iOS 中协议主要用于委托和数据源。
Blocks
Block 就是一段代码,它可以嵌入别的代码中,可以作为参数进行传递,储存在数组中。
Block 能够捕获局部变量但是以 只读
的方式进行。如果想要改变它们的值,则必须在声明变量的时候添加 __block
比如:__block BOOL stop = NO;
,那么你就可以在 block 实现中来改变 stop
的值。这步的本质就是将 stop
从栈中移到堆中,这样他就可以在 block 中使用了,使用完后编译器就会将信息复制回堆中,再放回栈上。
只要 block 存在,那么它就会使用强指针指向所使用的变量,直到 block 被释放。
block 不是对象,但它有时表现的像是对象,因为他可以被存储,所以 block 可以像对象一样被存储,但并不像对象那样可以理解消息,实际上只能理解 copy 消息。
何处使用 Block
- 可以用于枚举,枚举字典中的键和值。
- 可以用于动画。
- 可以用于排序,想数组放松消息,让数组进行排序,或者比较两个对象的大小。
- 可以进行通知,当完成某个操作后可以直接说「执行这个 block」。
- 用于完成处理程序同样很常见,某个操作需要一段时间才能完成,会在后台线程中完成,当它完成时,执行这个 block。
动画
+ (void)animateWithDuration:(NSTimeInterval)duration
delay:(NSTimeInterval)delay
options:(UIViewAnimationOptions)options
animations:(void (^)(void))animations
completion:(void (^)(BOOL finished))completion;
第一个参数代表这个动画出现在这个屏幕的时间,要记住你所做的改变会立即生效,但会过一段时间才显示出来。delay
代表等待多长时间再开始执行。animations
这个参数很重要,在这个 block 中你可以修改 frame,还可以修改 center,center 和 frame 是关联的,还可以修改 transform 和 alpha。下面是示例:
[UIView annimateWithDuration:3.0
delay:0.0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{ myView.alpha = 0.0; }
completion:^(BOOL fin) {if (ifn) [myView removeFromSuperview];}];
UIViewAnimationOptions
BeginFromCurrentState
如果你开启这个选项,如果还有一个正在执行的动画,动画的对象与我想要的是同一个,那么执行我的动画时从他们的当前状态开始。所以如果我要修改alpha
让他逐渐消失,alpha
变成 0.2 之类的,然后我让另一个动画开始执行,alpha
增大到 0.7,如果开启了这个参数,那么alpha
会从 0.2 变为 0.7,如果不开启就会从 0 开始。因为 0 才是alpha
的真实值,然后增大到 0.7.因此BeginFromCurrentState
可以用来拦截其他动画。之所以这样做是因为设置动画参数后会立即生效。