若排版有错误,请查看PDF版:http://pan.baidu.com/s/1hqFv0KO
第五章 block
一、 什么是block
1. block用来封装一段代码,可以在任何时候执行。
2. block的标志:^
3. block与函数很像:
1) 可以保存代码
2) 有返回值
3) 有形参
4) 调用方法一样
4. 内联函数从源代码层看,有函数的结构,而在编译后,却不具备函数的性质。编译时,类似宏替换,使用函数体替换调用处的函数名
二、 定义block变量
1. 无返回值,无形参
// 如果block没有形参,可以省略= ^后面的()
void (^myblock)() = ^(){
NSLog(@"----------------");
NSLog(@"----------------");
};
// 利用block变量调用block内部的代码
myblock();
2. 有返回值,有形参
int (^sumblock)(int,int) = ^(int a,int b){
return a + b;
};
int c = sumblock(10,11);
// 用一个block输出n条横线
void (^lineBlock)(int) = ^(int n)
{
for (int i =0; i<n; i++) {
NSLog(@"----------------");
}
};
lineBlock(5);
3. block访问外部变量
1) block内部可以访问外面的变量
2) 默认情况下,block内部不能修改外面的局部变量
3) 给局部变量加上__block关键字,这个局部变量就可以在block内部修改
int a = 10;
__block int b = 20;
void (^block)();
block = ^{
NSLog(@"a = %d", a); // block内部可以访问外面的变量
// 默认情况下,block内部不能修改外面的局部变量
// a = 20;
// 给局部变量加上__block关键字,这个局部变量就可以在block内部修改
b = 25;
};
block();
4. 利用typedef定义block变量
1) 利用typedef声明block类型
typedef int (^MyBlock)(int,int);
2) 再利用MyBlock这种类型定义block变量
MyBlock sumBlock; // int (^sumBlock)(int, int);
sumBlock = ^(int a, int b) {
return a + b;
};
int c = sumBlock(10,20); // 调用sumBlock
三、 block与函数指针的对比
block | 函数指针 |
int (^sumblock)(int,int) = ^(int a,int b){ return a + b; }; int c = sumblock(10,11); | int sum(int a,int b) { return a + b; } int (*p)(int,int) = sum;// 定义指针p指向sum函数 int d = p(10,20); // |
利用typedef | |
typedef int (^MyBlock)(int, int);// 声明block类型 | typedef int (*SumP)(int,int); // 声明函数指针类型 int sum(int a,int b) { return a + b; } |
MyBlock sumBlock; sumBlock = ^(int a, int b) { return a + b; }; int c = sumblock(10,11); | SumP p = sum;
int d = p(10,20); |
第六章 protocol协议
一、 基本用途
1. 可以用来声明一大堆方法(不能声明成员变量)
2. 只要某个类遵守了这个协议,就相当于拥有这个协议中的所有方法声明
3. 只要父类遵守了某个协议,就相当于子类也遵守了
一、 协议的定义
@protocol 协议名称 <NSObject>
// 方法声明列表....
@end
@protocol MyDogProtocol <NSObject>
…
@end
二、 如何遵守协议
1. 类遵守协议
@interface 类名 : 父类名<协议名称1, 协议名称2>
…
@end
@interface Person : NSObject<MyProtocol1, MyProtocol2>
…
@end
2. 协议遵守协议(一个协议遵守了另外一个协议,就可以拥有另一个协议的所有方法声明)
@protocol 协议名称<其他协议名称1, 其他协议名称2>
…
@end
@protocol MyProtocol3<MyProtocol1>
…
@end
三、 协议中方法声明的关键字
1. @required (默认)
要求实现,如果没有实现,会发出警告
2. @optional
不要求实现,怎样不会有警告
// 定义了一个名叫MyProtocol的协议
@protocol MyProtocol <NSObject>
// @required 要求实现,不实现就会发出警告
// @optional 不要求实现
- (void)test4;
@required
- (void)test;
- (void)test2;
@optional
- (void)test3;
@end
四、 定义一个变量的时候,限制这个变量保存的对象遵守某个协议
类名<协议名称>*变量名;
id<协议名称> 变量名;
NSObject<MyProtocol> *obj;
id<MyProtocol> obj2;
// 要求obj3保存的对象必须是遵守是MyProtocol这个协议
NSObject<MyProtocol> *obj3 = [[Person alloc] init];
id<MyProtocol> obj3 = [[Person alloc] init];
// 要求obj5,保存的对象必须遵守MyProtocol3、并且继承了Person
Person<MyProtocol3> *obj5 = [[Person alloc] init];
如果没有遵守对应的协议,编译器会警告
五、 @property中声明的属性也可用做一个遵守协议的限制
@property (nonatomic, strong) 类名<协议名称>*属性名;
@property (nonatomic,strong) id<协议名称>属性名;
@property (nonatomic,strong) Dog<MyProtocol>*dog;
@property (nonatomic,strong) id<MyProtocol> dog2;
六、 协议可用定义在单独.h文件中,也可用定义在某个类中
1. 如果这个协议只用在某个类中,应该把协议定义在该类中
2. 如果这个协议用在很多类中,就应该定义在单独文件中
七、 分类可用定义在单独.h和.m文件中,也可用定义在原来类中
1. 一般情况下,都是定义在单独文件
2. 定义在原来类中的分类,只要求能看懂语法
八、 协议的应用——代理模式
1. 代理模式原理
有些麻烦的事情不想自己亲自做,就可以找个人帮忙做,即交给代理对象去做。
2. 原则
1) 首先得拥有某个代理对象属性
2) 其次要很清楚代理有哪些方法
3) 最后要保证能解耦
3. 实现方案
1) 定义一个protocol,在其中声明一些和代理沟通的方法
2) 拥有一个代理属性id<protocol> delegate
3) 让代理遵守protocol
代理协议(TicketDelegate) | |
TicketDelegate.h | |
#import <Foundation/Foundation.h> //声明一些跑腿方法 @protocol TicketDelegate <NSObject> //返回票价 - (double) ticketPrice; //还剩多少张票 - (int) leftTicketsNumber; @end | |
Person类 | |
Person.h | Person.m |
#import <Foundation/Foundation.h> #import "TicketDelegate.h" @interface Person : NSObject - (void) buyTicket; // 拥有一个代理属性 // id代表代理的类名随便 // 但必须遵守TicketDelegate协议 @property (nonatomic,retain) id<TicketDelegate> delegate; @end | #import "Person.h" @implementation Person // 买电影票 - (void)buyTicket { // 叫代理去帮自己买票(询问一下票价、询问一下票的剩余张数) double price = [_delegate ticketPrice]; int number = [_delegate leftTicketsNumber]; NSLog(@"通过代理的帮忙,票价=%f,还剩%d张票", price, number); } - (void)dealloc { [_delegate release]; [super dealloc]; } @end |
代理(Agent询问电影票的情况) | |
Agent.h(声明遵守代理协议) | Agent.m(实现代理协议方法) |
#import <Foundation/Foundation.h> #import "TicketDelegate.h" @interface Agent : NSObject <TicketDelegate> @end | #import "Agent.h" @implementation Agent // 剩余的票数 - (int)leftTicketsNumber { return 1; } // 每一张票多少钱 - (double)ticketPrice { return 1000; } @end |
主函数 | |
main.m | |
#import <Foundation/Foundation.h> #import "Person.h" #import "Agent.h"
int main() { // 人 Person *p = [[Person alloc] init]; // 代理 Agent *a = [[Agent alloc] init];
// 设置人的代理 p.delegate = a;
// 人打算看电影 [p buyTicket];
[a release]; [p release]; return 0; } |