黑马程序员——10、OC语言(block、protocol和代理模式)

---------------------- Java培训、Android培训、iOS培训、.Net培训期待与您交流! ---------------------


一、block

block封装了一段代码,可以在任何时候执行。

block可以作为函数参数或函数的返回值,而其本身又可以带输入参数和返回值。

* block在程序运行时确定

block用来保存一端代码

block的标示:^

* block跟函数很像:

》可以保存代码

》有返回值

》有形参

》调用方式一样

  1.如何定义block变量

int (^sumBlock)(int, int);

  2.如何利用block封装代码

^(int a, int b){

return a+b;

};

    // 如果block没有形参,^() 可以省略()
    // 定义block变量
    void (^myblock)() = ^{
        NSLog(@"+++++++++++++++");
        NSLog(@"---------------");
    };
    
    // 利用block变量调用block内部代码
    myblock();
    // 用一个block输出n条横线
    void (^lineBlock)(int) = ^(int n){
        for (int i=0; i<n; i++) {
            NSLog(@"-------------");
        }
    };
    
    lineBlock(4);

  3.block访问外部变量

* block可以直接访问外部变量

* 默认情况下,block【不可以修改】外面的局部变量

* 给局部变量加上__block修饰,这个局部变量就可以在block中修改

    __block int i = 10;
    MyBlock printBlock = ^(int v1, int v2){
        i++; // 可以修改局部变量了
        NSLog(@"a=%d", i);
        return v1+v2;
    };
    int f = printBlock(12, 13);
    NSLog(@"%d", f);

  4.利用typedef定义block类型

typedef int (^MyBlock)(int, int);

以后可以利用MyBlock这种类型定义block变量

MyBlock b1;

b1 = ^(int a, int b){

return 12;

}

// 指向函数的指针  定义为  SumP类型
typedef int (*SumP)(int, int);
// block  定义为  MyBock类型
typedef int (^MyBlock)(int, int);
    
SumP p = sum;
int c = p(10, 15);
NSLog(@"%d", c);
    
MyBlock sumBlock = ^(int a, int b){
    return a+b;
};
int d = sumBlock(10, 15);
NSLog(@"%d", d);
    
MyBlock minusBlock = ^(int a, int b){
    return a-b;
};
int e = minusBlock(10, 15);
NSLog(@"%d", e);

  5. block与指向函数的指针

    // block
    int (^sumblock)(int, int) = ^(int a, int b){
        return a+b;
    };
    
    int res = sumblock(10, 12);
    NSLog(@"%d", res);
    
    /********************************/
    
    //指向函数的指针
    int (*p)(int, int) = sum;
    int c = p(10, 11);
    NSLog(@"%d", c);




二、protocol

一系列方法的声明。

: 继承父类(OC单继承)

<> 遵守协议(协议多遵守)

() 分类

  1. 协议的定义

@protocol 协议名称 <NSObject>

// 方法声明列表

@end

  2. 如何遵守协议

1》类遵守协议

@interface 类名 : 父类名 <协议名称1, 协议名称2>

@end

2》协议遵守协议

@protocol 协议名称 <其他协议名称1, 其他协议名称2>

@end

一个协议遵守了另一个协议,就可以拥有另一个协议的所有方法声明。

  3. 协议方法中声明的关键字

1》@required(默认)

要求实现。若不实现,则发出警告

2》@optional

不要求实现

只要一个类遵守了某个协议,就能拥有这份协议的所有方法声明。

NSObject是一个基类,同时也有个NSObject的基协议,基协议里有很多最基本的方法,比如:description、retain、release等。

建议每一个新的协议都遵守NSObject协议。

// 定义了一个名叫MyProtocol的协议
@protocol MyProtocol <NSObject>

// 默认@required
- (void)test4;

@required
- (void)test1;
- (void)test2;

@optional
+ (void)test3;

@end

  4. 定义一个变量的时候,限制这个变量保存的对象遵守某个协议

类名<协议名称> *变量名;

id<协议名称> 变量名;

如果没有遵守对应的协议,编译器会警告(比较严重的)

    // 要求obj2保存的对象必须是遵守MyProtocol这个协议
    // Person 已经遵守了MyProtocol这个协议,没有警告
    NSObject<MyProtocol> *obj2 = [[Person alloc] init];
    obj2 = nil;
    
    id<MyProtocol> obj3 = [[Person alloc] init];
    obj3 = nil;
    
    
    // 要求obj4,保存对象必须遵守MyProtocol3,并且继承Person
    Person<MyProtocol3> *obj4 = [[Person alloc] init];
    obj4 = nil;

  5. @property中声明的属性也可以用来声明一个遵守协议的限制

@property (nonatomic, strong) 类名<协议名称> *变量名;

@property (nonatomic, strong) id<协议名称> 变量名;


  6. 协议可以定义在单独.h文件中,也是定义在某个类的文件中

1》如果这个协议用在某个类中,应该把协议定义在这个类中

2》如果这个协议用在很多类中,就应该定义在单独.h文件中

  7. 分类可以定义在单独.h和.m文件中,也是定义在原来类中

1》一般情况下,都是定义在单独文件中

2》也可以定义在原来类中,只要求能看懂语法

  8. 声明某个字符串是一个协议

@protocol 协议名;

但是在实现文件.m中,还是要#import引入这个协议的.h文件。跟@class相同。




三、代理模式

请求方 —— 协议 —— 代理方

需要代理方具有协议里面的方法,才能实现请求方的代理需求。

设计原则:

》先让某个对象属性拥有代理权利

》清楚代理协议里的方法

》要保证能解耦

实现方法:

》先定义一个protocol,在其中声明一些和代理沟通的方法

》拥有一个代理属性 id<protocol> delegate;

》让代理类遵守这个协议protocol

  (1)Person类的声明与实现

Person.h

#import <Foundation/Foundation.h>
@protocol TicketDelegate;

@interface Person : NSObject

// 拥有一个代理属性
// 代理类名随便,但必须遵守TicketDelegate协议
@property (nonatomic, strong) id<TicketDelegate> delegate;

- (void)wantMoive;

@end


Person.m

#import "Person.h"
#import "TicketDelegate.h"

@implementation Person

- (void)wantMoive
{
    NSLog(@"xiang看电影");
    
    // 叫代理去帮自己买票
    double price = [_delegate ticketPrice];
    int number = [_delegate leftTickets];
    
    NSLog(@"通过代理,票价:%f,剩余票数:%d", price, number);
}

- (void)dealloc
{
    NSLog(@"Person dealloced!!");
}

@end


  (2)代理协议(谁遵守了这个协议,谁就可以做代理)

TicketDelegate.h

#import <Foundation/Foundation.h>

// 声明一些跑腿的方法
@protocol TicketDelegate <NSObject>

// 返回票价
- (double)ticketPrice;

// 剩余票数
- (int)leftTickets;

@end


  (3)Agent类的声明与实现

Agent.h

#import <Foundation/Foundation.h>
#import "TicketDelegate.h"

@interface Agent : NSObject <TicketDelegate>

 返回票价
//- (double)ticketPrice;
//
 剩余票数
//- (int)leftTickets;

@end


Agent.m

#import "Agent.h"


@implementation Agent

- (double)ticketPrice
{
    // ...查票价
    return 1;
}

- (int)leftTickets
{
    // ...查票数
    return 1000;
}

@end


  (4)运行代理

    Person *p = [[Person alloc] init];
    // 代理
    Agent *a = [[Agent alloc] init];
    
    // 设置人的代理
    p.delegate = a;
    
    // 人打算看电影
    [p wantMoive];



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值