Protocol简单来说就是一系列方法的列表,当中声明的方法能够被不论什么类实现。这中模式一般称为代理(delegation)模式。

在IOS和OS X开发中,Apple採用了大量的代理模式来实现MVC中View(UI控件)和Controller(控制器)的解耦。

以下我们先来看一下我们熟悉的Android中的button监听过程,然后再对照理解delegation。

首先我建立一个非常easy的Androidproject,在Layout中放置一个button,例如以下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/mybutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button"/>
</LinearLayout>
package com.example.helloword;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.widget.Button;
import android.widget.Toast; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.mybutton);
button.setOnClickListener(new MyOnClickListener());
} class MyOnClickListener implements OnClickListener{ @Override
public void onClick(View arg0) {
Toast.makeText(MainActivity.this,
"点击了button", Toast.LENGTH_SHORT).show();
}
} class MyonLongClickListener implements OnLongClickListener{ @Override
public boolean onLongClick(View arg0) {
Toast.makeText(MainActivity.this,
"长按了button", Toast.LENGTH_SHORT).show();
return false;
} }
}

OnClickListener是View的一个内部类,是View定义的一个接口,我们打开OnClickListener源代码例如以下:

    /**
* Interface definition for a callback to be invoked when a view is clicked.
*/
public interface OnClickListener {
/**
* Called when a view has been clicked.
*
* @param v The view that was clicked.
*/
void onClick(View v);
}

我们再来看看setOnClickListener方法

    public void setOnClickListener(OnClickListener l) {
if (!isClickable()) {
setClickable(true);
}
getListenerInfo().mOnClickListener = l;
}

先推断View是不是可点击的,主要我们来看看以下那一句,getListenerInfo().mOnClickListener = 1;

    ListenerInfo getListenerInfo() {
if (mListenerInfo != null) {
return mListenerInfo;
}
mListenerInfo = new ListenerInfo();
return mListenerInfo;
}

从这段代码能够看出来,将我们的OnClickListener实例保存到了ListenerInfor对象中了,那么ListenerInfor对象是用来干嘛的呢?因为我当下没有Android系统源代码就不在跟踪下去了,能够猜想这个类持有我们的OnClickeListener对象,当系统响应屏幕点击事件的时候,通过事件分发,能够调用onClick方法来告诉全部实现了OnClickeListener接口的对象。

接下来我们来模拟一下IOS中button监听的实现。

Button.h文件

#import <Foundation/Foundation.h>
@class Button; //<>代表实现某个协议
//这里相当于OnClickListener
@protocol ButtonDelegate <NSObject> //将Button对象传递给监听器,来推断详细的调用实例
- (void) onClick:(Button *)btn; @end @protocol ButtonLongClickDelegate <NSObject> - (void) onLongClick:(Button *)btn; @end @interface Button : NSObject //delegate就是button的监听器
//id代表不论什么OC对象
@property (nonatomic, retain) id<ButtonDelegate> delegate;
@property (nonatomic, retain) id<ButtonLongClickDelegate> longClickDeleate; //模拟系统调用click方法
- (void)click; //模拟系统调用longclick方法
- (void)longClick; @end

Button.m文件

#import "Button.h"

@implementation Button

- (void)click {
//button被点击了,就应该通知监听器(这里是模拟)
//假设onClick方法被实现,调用onClick方法
if([_delegate respondsToSelector:@selector(onClick:)]){
[_delegate onClick:self];
}else{
NSLog(@"onClick监听器未实现");
}
} - (void)longClick {
//button被长按(模拟系统)
if([_delegate respondsToSelector:@selector(onClick:)]){
[_longClickDeleate onLongClick:self];
}else{
NSLog(@"longClick监听器未实现");
}
} - (void)dealloc {
[_delegate release];
[_longClickDeleate release];
[super dealloc];
} @end

ButtonListener.h

#import <Foundation/Foundation.h>
@protocol ButtonDelegate; //实现button点击协议
@interface ButtonListener : NSObject <ButtonDelegate> @end

ButtonListener.m

#import "ButtonListener.h"
#import "Button.h" @implementation ButtonListener - (void)onClick:(Button *)btn {
NSLog(@"button被点击了");
}
@end

ButtonLongClickListener.h文件

#import <Foundation/Foundation.h>

//对协议进行提前声明,跟@class的用途是一样的
@protocol ButtonLongClickDelegate; @interface ButtonLongClickListener : NSObject <ButtonLongClickDelegate> @end

ButtonLongClickListener.m文件

#import "ButtonLongClickListener.h"
#import "Button.h" @implementation ButtonLongClickListener - (void)onLongClick:(Button *)btn{
NSLog(@"button被长按了");
} @end

main.m文件

#import <Foundation/Foundation.h>
#import "Button.h"
#import "ButtonListener.h"
#import "ButtonLongClickListener.h" int main(int argc, const char * argv[]) {
@autoreleasepool {
//初始化一个button
Button *button = [[[Button alloc] init] autorelease];
//初始化一个button的监听器
ButtonListener *listener = [[[ButtonListener alloc] init] autorelease];
//初始化一个button长按监听器
ButtonLongClickListener *longClickListener =
[[[ButtonLongClickListener alloc] init] autorelease];
//设置button的监听器
button.delegate = listener;
//设置长按button监听器
button.longClickDeleate = longClickListener;
//点击button
[button click];
//长按button
[button longClick];
}
return 0;
}

输出结果:

2014-11-16 13:52:35.215 ProtocalTest[845:82273] button被点击了

2014-11-16 13:52:35.216 ProtocalTest[845:82273] button被长按了

Objective-C基础笔记(5)Protocol的更多相关文章

  1. Java基础笔记 – Annotation注解的介绍和使用 自定义注解

    Java基础笔记 – Annotation注解的介绍和使用 自定义注解 本文由arthinking发表于5年前 | Java基础 | 评论数 7 |  被围观 25,969 views+ 1.Anno ...

  2. php代码审计基础笔记

    出处: 九零SEC连接:http://forum.90sec.org/forum.php?mod=viewthread&tid=8059 --------------------------- ...

  3. MYSQL基础笔记(六)- 数据类型一

    数据类型(列类型) 所谓数据烈性,就是对数据进行统一的分类.从系统角度出发时为了能够使用统一的方式进行管理,更好的利用有限的空间. SQL中讲数据类型分成三大类:1.数值类型,2.字符串类型和时间日期 ...

  4. MYSQL基础笔记(五)- 练习作业:站点统计练习

    作业:站点统计 1.将用户的访问信息记录到文件中,独占一行,记录IP地址 <?php //站点统计 header('Content-type:text/html;charset=utf-8'); ...

  5. MYSQL基础笔记(四)-数据基本操作

    数据操作 新增数据:两种方案. 1.方案一,给全表字段插入数据,不需要指定字段列表,要求数据的值出现的顺序必须与表中设计的字段出现的顺序一致.凡是非数值数据,到需要使用引号(建议使用单引号)包裹. i ...

  6. MYSQL基础笔记(三)-表操作基础

    数据表的操作 表与字段是密不可分的. 新增数据表 Create table [if not exists] 表名( 字段名 数据类型, 字段名 数据类型, 字段n 数据类型 --最后一行不需要加逗号 ...

  7. MYSQL基础笔记(二)-SQL基本操作

    SQL基本操作 基本操作:CRUD,增删改查 将SQL的基本操作根据操作对象进行分类: 1.库操作 2.表操作 3.数据操作 库操作: 对数据库的增删改查 新增数据库: 基本语法: Create da ...

  8. MYSQL基础笔记(一)

    关系型数据库概念: 1.什么是关系型数据库? 关系型数据库:是一种建立在关系模型(数学模型)上的数据库 关系模型:一种所谓建立在关系上的模型. 关系模型包含三个方面: 1.数据结构:数据存储的问题,二 ...

  9. JavaScript基础笔记二

    一.函数返回值1.什么是函数返回值    函数的执行结果2. 可以没有return // 没有return或者return后面为空则会返回undefined3.一个函数应该只返回一种类型的值 二.可变 ...

  10. JavaScript基础笔记一

    一.真假判断 真的:true.非零数字.非空字符串.非空对象 假的:false.数字零.空字符串.空对象.undefined 例: if(0){ alert(1) }else{ alert(2) } ...

随机推荐

  1. 一个分组查询 每组前 10 的sql 语句

    USE tmpgo CREATE TABLE Employee( ID int identity(1,1), EmpName varchar(20), EmpSalary varchar(10), E ...

  2. JS 获取星期几的四种写法

    今天是星期几的4种JS代码写法,有需要的朋友可以参考一下 第一种写法 复制代码代码如下: var str = "";  var week = new Date().getDay() ...

  3. 谓词--Predicate

    去苹果的的技术官网搜索-Predicate就会找到相关的文档-Predicate Programming Guide 1,创建谓词时 %@是变量时不加单双引号,常量是加单引号,加双引号需要转义符号\ ...

  4. nfs:server is not responding,still trying 原因与解决

    方案(学自他人) nfs:server is not responding,still trying的解决方法 (2009-04-20 10:20) 方法1 : 我在arm上通过NFS共享文件时出现下 ...

  5. android handler工作原理

    android handler工作原理 作用 便于在子线程中更新主UI线程中的控件 这里涉及到了UI主线程和子线程 UI主线程 它很特别.通常我们会认为UI主线程将页面绘制完成,就结束了.但是它没有. ...

  6. C程序设计语言之一

    %d 按照十进制整形数打印: %o 按照八进制整形数打印: %x 按照十六进制整形数打印: %c 表示字符 %s 表示字符串 %% 表示%本身打印: %ld long型输出 ”幻数“: #define ...

  7. BZOJ 1798: [Ahoi2009]Seq 维护序列seq( 线段树 )

    线段树.. 打个 mul , add 的标记就好了.. 这个速度好像还挺快的...( 相比我其他代码 = = ) 好像是#35.. ---------------------------------- ...

  8. android 判断网络连接的工具类

    package com.way.util; import android.content.Context; import android.net.ConnectivityManager; import ...

  9. Android的回调

    学了两三周的安卓了,最先开始是看mars老师的视频,看了一两天结合慕课网上的一些安卓视频,到现在算是有点入门了. 安卓立用得比较多的回调函数有点不明是怎么实现的,网上找了一些资料,结合自己的实践,总算 ...

  10. Easyui中tree组件实现搜索定位功能及展开节点定位

    这几天遇到个input + tree  实现搜索功能的需求,在这里贴出来供大家参考下,如果你有更好的实现效果希望不腻赐教! 首先给大家看看效果     小二 上图  : 需要的部件知识: easyui ...