黑马程序员 OC语言 - 6 block、协议

若排版有错误,请查看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;

}

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值