引子
为了弄明白委托和协议是什么东西以及怎么使用,我经常是隔三差五的在网上找资料来理解它。每次看完各种博客对于“委托和协议”的讲解,没过几天当我又看到“协议”、“委托“这两个关键词的时候,心里又产生一种陌生以及恐惧的感觉!我不认识他了,我又不认识它了!!
今天我又遇见它了,这一次我得记住它!就算记不住,我也要把我今天对”协议“、”委托”的理解程度给记下来。方便下次再遇到这两个东西的时候,进行回忆以及关联思考!所以,我决定了,文章、博客看了这么多,还不如自己动手写以下代码,实践检验真理,让“真理“更加深刻!
协议
因自己是从C++开发过来的,所以对Ios 的协议理解和c++作为关联比较。协议类似c++种的抽象类(带有纯虚方法的类叫做抽象类),它只列出了一些列的方法的声明,而并没有方法的实现。即协议是多个类共享的一个方法列表,在协议中所列出的方法是没有相应的实现,有其他使用协议的人(类)类实现。
1. 用”@protocol“ 关键字来声明,类似用”@interface“来声明一个类!
2. 用“@required” 关键字来声明,关键字下面包含的方法声明是
使用该协议的类必须要实现的方法。
3. 用“@optional” 关键字来声明,关键字下面包含的方法声明
使用该协议的类可选实现的方法。
4. 协议不是一个类。
协议的声明形式:
@protocol delegateName
@required
- (void) requiredFunc1;
@optional
- (void) optionalFunc2;
@end
例子
设题:李四要买一个苹果,但是他不想自己去买,于是他就委托张三帮他卖一个苹果!
那么,用协议和委托怎么来实现呢?
1.声明一个协议“ByAppleDelegate”
//
// ByAppleDelegate.h
// ProtocolDemo
//
// Created by fenglh on 14-8-6.
// Copyright (c) 2014年 yons. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol ByAppleDelegate <NSObject>
@required
- (void) required_byApple;//
@optional
- (void) optional_byApple; //后面不用到该方法!
@end
2.定义和实现一个“张三”类
//
// ZhangSan.h
// ProtocolDemo
//
// Created by fenglh on 14-8-6.
// Copyright (c) 2014年 yons. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ByAppleDelegate.h"
@interface ZhangSan : NSObject<ByAppleDelegate> //ZhangSan 类使用了ByAppleDelegate 这个协议!
@end
//
// ZhangSan.m
// ProtocolDemo
//
// Created by fenglh on 14-8-6.
// Copyright (c) 2014年 yons. All rights reserved.
//
#import "ZhangSan.h"
@implementation ZhangSan
//实现ByAppleDelegate协议中的required_byApple方法
- (void) required_byApple
{
NSLog(@"ZhangSan help LiSi bought an Apple! (via required_byApple)");
}
@end
3.定义和实现一个“李四”类
//
// LiSi.h
// ProtocolDemo
//
// Created by fenglh on 14-8-6.
// Copyright (c) 2014年 yons. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ByAppleDelegate.h"
@interface LiSi : NSObject
{
id<ByAppleDelegate> delegate; //声明一个委托 注:①
}
- (void) IWantByApple;//声明一个李四自己想买苹果的方法
@property(nonatomic, retain) id<ByAppleDelegate> delegate; //例用特性实现它的set和get的访问方法
@end
//
// LiSi.m
// ProtocolDemo
//
// Created by fenglh on 14-8-6.
// Copyright (c) 2014年 yons. All rights reserved.
//
#import "LiSi.h"
#import "ZhangSan.h"
@implementation LiSi
@synthesize delegate;
- (void) IWantByApple
{
NSLog(@"LiSi want to by an apple via delegate ZhangSan!"); //李四想买一个苹果,但是他不想自己买,于是...
[delegate required_byApple]; //于是他就委托别人(张三)去买 ,注:②
}
@end
4. main函数
//
// main.m
// ProtocolDemo
//
// Created by fenglh on 14-8-6.
// Copyright (c) 2014年 yons. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ZhangSan.h"
#import "LiSi.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
ZhangSan * zhangsan = [[ZhangSan alloc] init];//实例化一个张三
LiSi *lisi = [[LiSi alloc] init]; //实例化一个李四
lisi.delegate = zhangsan; //设置李四的委托人是张三
[lisi IWantByApple]; //李四买苹果
}
return 0;
}
5. 输出结果
2014-08-06 18:26:14.996 ProtocolDemo[874:303] LiSi want to by an apple via delegate ZhangSan!
2014-08-06 18:26:14.997 ProtocolDemo[874:303] ZhangSan help LiSi bought an Apple! (via required_byApple)
委托
在注解① 这里声明一个委托!id<ByAppleDelegate> delegate; 没错delegate这就是一个委托!如果这样看起来很别扭,难以理解的话,你可以从C++的角度来理解,如果把它换成用C++的写法那应该是这样:
@interface LiSi : NSObject
{
id<ByAppleDelegate> delegate; //用Ios的写法
ZhangSan * zhangsan; //用C++的写法,一个指向张三类的指针!
}
上面的第一句和第二句的写法有什么区别吗?有点:
1)第一句,使用了协议以及委托的结合。
1)第一句,id是一个指向任何对象的指针,所以,在注:②中,你不必关心你的委托人是谁!
2)第二句,这里定义了一个指向ZhangSan类的指针,也相当于是一个委托。这里,你需要明确指定委托的人是张三!然后在注:②中,你还要改成这样:
[zhangsan required_byApple];
所以,委托是一种设计模式,李四想要做的事,他委托张三来完成,这就是委托!
(不明白的,可以自己用第二句的语法来代码实现以下!)
7.小结
1.协议,它只是一个方法列表的集合,他只有方法声明而没有方法的实现,由关键字 "@protocol"来声明一个协议。类似于C++的抽象类!
2.委托,它只是一个设计模式,也就是说是一种思想,无论在C++、objc、java 、C#都存在委托,他们的意义是一样的!
3.委托,如果你学过C++开发的话,你可以把它理解成这样:
Class A{
}
Class B{
A * a; //这就是相当于一个委托!!相当于这个类中指向另外一个对象的指针
}