022-block与@protocol-OC笔记

学习目标

1.【掌握】延展Extension

2.【掌握】block类型

3.【掌握】block修改外部变量

4.【理解】block的应用场景

5.【掌握】协议protocol

6.【掌握】@protocol类型限制

7.【理解】代理模式Delegation

一、延展Extension

延展(Extension)是一个特殊的分类,延展没有名字(匿名分类),而且只能有方法的声明,不能有单独的方法实现,与本类共享一个方法实现。我们可以使用@property生成私有属性和对应的getter、setter方法。所以我们常常将延展写在类的实现文件中,用于私有化类的成员(属性和方法),仅限本类访问。

 

二、block类型

block是OC中新增的一个数据类型,可以声明block变量来存储一段代码,这段代码可以有参数,也可以有返回值,也可以都没有。并且可以通过 这个block变量来执行存储在变量中的代码,同时block变量也可以作为一个参数进行传递。在使用时,我们常常会使用typedef来声明一个 block类型的别名,这样就可以把符合特定要求的代码块保存在block变量里作为方法的参数进行传递,还能简写代码。

语法:

返回值类型 (^block变量名)(参数列表) = ^代码段返回值类型(参数列表) {

    代码段;

};

block类型的简单使用

使用typedef将复杂的block定义简化

 

三、block访问外部变量

block可以访问外部变量(block外部),但无法改变外部变量的值。如果想要被修改,需要用__block修饰。

 

四、block的应用场景

block作为方法的参数,可以将调用者的代码段传递到函数内部去使用

block作为方法或函数的返回值,方法执行完毕之后会有一段代码返回给调用者

 

五、协议protocol

在OC中使用@protocol定义一个协议,遵守此协议的类就拥有了这个协议所有的方法声明。协议跟其他面向对象语言的接口有些类似,只是不一定会实现协议里的方法。

 

总结:

1.协议通过<>进行实现,并且只能在类的声明上遵守协议,一个类可以同时遵守多个协议,中间通过逗号分隔。

2.一个协议可以遵守自另一个协议,例如上面myProtocol就遵守自NSObject(基协议),如果需要遵守多个协议中间使用逗号分隔。

3.如果父类遵守了某个协议,子类继承了父类所有成员,相当于子类也遵守了这个协议,子类不实现也不会警告。

4.协议中不能定义属性,只能声明方法,不要在协议中使用@property定义属性,协议的主要作用是集中声明方法。

5.我们可以通过关键字@required和@optional分别修饰必须实现的方法和可选实现的方法,如果不修饰则默认是@required。

六、@protocol类型限制

要求某个指针保存的是遵守了指定协议的对象,比如id<协议名> obj;,这个obj指针只能指向遵守了“<协议名>”这个协议的对象。之所以要求对象要遵守某个协议,是因为我们可能会在程序中调用协议中的方法,如果没有遵守并实现其对应方法调用时就会报错。一般调用时我们都会使用respondsToSelector:方法来判断遵守了指定协议的对象是否实现了其对应的方法。

 

七、代理模式Delegation

事实上在OC中协议的更多作用是用于约束一个类必须实现某些方法,而从面向对象的角度而言这个类跟其他面向对象语言的接口(interface)并不一定存在某种自然关系,可能是两个完全不同意义上的事物,这种模式我们称之为代理模式(Delegation)。在Cocoa框架中大量采用这种模式实现数据和UI的分离,而且基本上所有的协议都是以Delegate结尾。

现在假设需要设计一个按钮,在按钮中定义按钮的代理,同时使用协议约束这个代理(事件的触发者)必须实现协议中的某些方法,当按钮被点击就检查代理是否实现了这个方法,如果实现了则调用这个方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//JFButtonDelegate.h文件
#import <Foundation/Foundation.h>
@classJFButton;
 
@protocolJFButtonDelegate<NSObject>
@required
-(void)onClick:(JFButton*)button;
 
@end
 
 
//MyListener.h文件
#import <Foundation/Foundation.h>
#import "JFButtonDelegate.h"
 
@interface MyListener : NSObject<JFButtonDelegate>
 
@end
 
 
//MyListener.m文件
#import "MyListener.h"
#import "JFButton.h"
 
@implementationMyListener
 
//实现协议中声明的方法
-(void)onClick:(JFButton*)button{
    NSLog(@"调用代理的监听方法,被点击的按钮是:%@",button);
}
@end
 
 
//JFButton.h文件
#import <Foundation/Foundation.h>
#import "JFButtonDelegate.h"
 
@interface JFButton : NSObject
 
//代理属性,同时约定作为代理的对象必须实现JFButtonDelegate协议
//id可以表示任何一个OC对象类型,类型后面的 <协议名> 用于约束作为这个属性的对象必须实现该协议。
@property(nonatomic,strong)id<JFButtonDelegate>delegate;
 
//点击方法
-(void)click;
 
@end
 
 
//JFButton.m文件
#import "JFButton.h"
 
@implementationJFButton
 
-(void)click{
    NSLog(@"调用按钮对象的点击方法");
    
    //使用respondsToSelector方法可以判断self.delegate实例是否实现了onClick:方法
    if([self.delegate respondsToSelector:@selector(onClick:)]){
        //如果确认onClich:方法已经实现,则作为JFButton的监听
        [self.delegate onClick:self];
    }
}
 
@end
 
 
//main.m文件
#import <Foundation/Foundation.h>
#import "JFButton.h"
#import "MyListener.h"
 
intmain(intargc,constchar*argv[]){
    @autoreleasepool{
        //实例化按钮和监听对象
        JFButton*button=[[JFButtonalloc]init];
        MyListener*listener=[[MyListeneralloc]init];
        
        //降遵守了协议的监听对象作为按钮的代理
        button.delegate=listener;
        
        //按钮调用点击方法
        [button click];
        
        /*
         调用按钮对象的点击方法
         调用代理的监听方法,被点击的按钮是:<JFButton: 0x100114710>
         */
    }
    return0;
}

 

 
posted on 2015-10-08 21:42  猎魂天使  阅读(164)  评论(0编辑  收藏  举报