Objective-C基础笔记(5)Protocol

Protocol简单来说就是一系列方法的列表,其中声明的方法可以被任何类实现。这中模式一般称为代理(delegation)模式。

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

下面我们先来看一下我们熟悉的Android中的按钮监听过程,然后再对比理解delegation。

首先我建立一个很简单的Android工程,在Layout中放置一个按钮,如下:

<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="按钮"/>
</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,
					"点击了按钮", Toast.LENGTH_SHORT).show();
		}
    }

    class MyonLongClickListener implements OnLongClickListener{

		@Override
		public boolean onLongClick(View arg0) {
			Toast.makeText(MainActivity.this,
					"长按了按钮", 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.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就是按钮的监听器
//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 {
    //按钮被点击了,就应该通知监听器(这里是模拟)
    //如果onClick方法被实现,调用onClick方法
    if([_delegate respondsToSelector:@selector(onClick:)]){
        [_delegate onClick:self];
    }else{
        NSLog(@"onClick监听器未实现");
    }
}

- (void)longClick {
    //按钮被长按(模拟系统)
    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;

//实现按钮点击协议
@interface ButtonListener : NSObject <ButtonDelegate>

@end

ButtonListener.m

#import "ButtonListener.h"
#import "Button.h"

@implementation ButtonListener

- (void)onClick:(Button *)btn {
    NSLog(@"按钮被点击了");
}
@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(@"按钮被长按了");
}

@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 alloc] init] autorelease];
        //初始化一个按钮的监听器
        ButtonListener *listener = [[[ButtonListener alloc] init] autorelease];
        //初始化一个按钮长按监听器
        ButtonLongClickListener *longClickListener =
            [[[ButtonLongClickListener alloc] init] autorelease];
        //设置按钮的监听器
        button.delegate = listener;
        //设置长按按钮监听器
        button.longClickDeleate = longClickListener;
        //点击按钮
        [button click];
        //长按按钮
        [button longClick];
    }
    return 0;
}

输出结果:

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

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

时间: 2024-10-10 12:03:28

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

网络基础笔记——OSI七层模型

OSI七层模型 由于整个网络连接的过程相当复杂,包括硬件.软件数据封包与应用程序的互相链接等等.如果想要写一支将联网全部功能都串连在一块的程序,那么当某个小环节出现问题时,整只程序都需要改写.所以我们将整个网络分成数层,每层都有自己独立的功能,而且每层的代码都可以独立撰写,因为相互之间不会干扰.如此一来,当某个小环节出现问题时,只要将该层的代码改写即可.并且这样可以让整个网络层次更加的清晰. 在网络上传输信息就像是一个发包裹的过程,从己方的应用程序开始往第七层的包裹里塞数据,再依次塞到第一层的包

OC方面的基础笔记摘录

OC方面的基础笔记摘录: 1.类的基本用法 #import <Foundation/Foundation.h>// 大体上就是include, 用于包含头文件, 但是即使头文件中, 没有ifndef defined endif, 仍然能够踢除重复包含的头文件// [email protected] section----// OC中声明和实现是分离的, 两个都必须有.@interface Fraction : NSObject {    // @interface 类名: 父类名字// 在这里

java String 类 基础笔记

字符串是一个特殊的对象. 字符串一旦初始化就不可以被改变. String s = "abc";//存放于字符串常量池,产生1个对象 String s1=new String("abc");//堆内存中new创建了一个String对象,产生2个对象 String类中的equals比较字符串中的内容. 常用方法: 一:获取 1.获取字符串中字符的个数(长度):length();方法. 2.根据位置获取字符:charAt(int index); 3.根据字符获取在字符串中

[Java基础笔记]数组

Java基础笔记 定义数组: int[] numbers = new int[100]; //方法一 double[] num = new double[10]; int[][] a = new int[2][5]; 通过new创建的数组,元素默认值为0(0.0) int[] scores = {5,4,33,12,46}; //方法二 int[][] a = { //位数不足,自动补0 {5,3,2,1,6}, {10,12,14,15}, }; 数组特性:存储的都是同类型数据:长度定义后不可

C# 基础笔记(第一篇)

C#基础 概念:.net与c#.net/dontnet:一般指.net framework框架,一种平台,一种技术c#(charp):一种编程语言,可以开发基于.net的应用. *java既是一种技术又是一种编程语言.                           .net都能干什么?开发桌面应用程序   Winforminternet应用程序    Asp.net/webservice C/S:客户机(Client)/服务器模式(Server)B/S:浏览器(Browser)/务器模式(

我的LINUX基础笔记

Linux系统管理      1 Day   2014.5.23 su -name   切换用户passwd 密码   更改密码gnome-terminal    伪CLI   桌面终端程序1.查看内核版本uname -r    2.查看红帽系统版本cat /etc/redhat-rdlease3.查看LINUX标准分发版信息  lsb_release4.查看网卡的IP,MAX       ifconfig                       ifconfig eth 10.0.0.10

Nginx基础笔记

Nginx基础笔记 资源 安装 ubuntu下 编译安装 基本操作 HTTP基本配置 配置说明 配置文件目录结构 配置文件结构 模块 模块化 index模块 Log模块 Real IP模块 Access模块 Rewrite模块 Proxy模块 upstream模块 其他 配置静态化目录 负载均衡 控制页面缓存 nginx的内置变量 nginx小结 资源 资源 Nginx 官网 Nginx 官方下载地址 Nginx最佳实践配置项目 地址 Nginx Configuration wiki 教程 ag

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

数据表的操作 表与字段是密不可分的. 新增数据表 1 Create table [if not exists] 表名( 2 字段名 数据类型, 3 字段名 数据类型, 4 字段n 数据类型 --最后一行不需要加逗号 5 )[表选项]; If not exists:如果表名不存在,那么就创建,否则不执行创建代码,实现检查功能. 表选项:控制表的表现 1.字符集:charset/character 具体字符集:--保证表中数据存储的字符集. 2.校对集:collate 具体校对集: 3.存储引擎:e

REDIS基础笔记

Redis基础笔记 资源链接 简介 简介 安装 五种数据类型及相应命令 1. 字符串类型 2. 散列类型 3. 列表类型 4. 集合类型 5. 有序集合 其他 事务 SORT 生存时间 任务队列 发布/订阅模式 Python中使用Redis 实际实例 管理 其他 资源链接 推荐书籍:<Redis入门指南> 资源列表: redis命令速查command | CMD索引-中文 | CMD树-中文 redis源码github 下载地址redis.io The Little Redis book 入口

php代码审计基础笔记

出处: 九零SEC连接:http://forum.90sec.org/forum.php?mod=viewthread&tid=8059 ---------------------------------------------------------- team:xdsec&90sec author:wilson blog:http://blog.wils0n.cn/ 文章链接:wilson's blog_php代码审计基础笔记[求人气~~] ----------------------