• 【Objective-C 基础】4.分类和协议


    1.分类

    OC提供了一种与众不同的方式--Category,可以动态的为已经存在的类添加新的行为(方法)

    这样可以保证类的原始设计规模较小,功能增加时再逐步扩展。

    使用Category对类进行扩展时,不需要创建子类

    Category使用简单的方式,实现了类的相关方法的模块化,把不同的类方法分配到不同的分类文件中

    ()代表着一个分类 ()中的代表者分类的名称

    也可以为系统子类的类添加一些扩展方法

    2.协议(Protocol)

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

    2.模拟实现Button的点击监听机制

    a.声明代理

    #import <Foundation/Foundation.h>
    @class  Button;
    //<>代表实现某个协议
    @protocol ButtonDelegate <NSObject>
    -(void)onClick:(Button *)btn;
    @end
    
    @interface Button : NSObject
    @property (nonatomic,retain) id<ButtonDelegate> delegate;
    -(void)click;
    @end
    #import "Button.h"
    
    
    @implementation Button
    
    -(void)dealloc{
        //释放Button 同时释放delegate
        [_delegate release];
        [super dealloc];
    }
    -(void)click{
        //判断监听器是否有OnClick:方法
        if([_delegate respondsToSelector:@selector(onClick:)]){
            [_delegate onClick:self];
        }else{
            NSLog(@"监听器没有实现onClick方法");
        }
    }
    @end

    b.定义一个类ButtonListener遵循ButtonDelegate协议

    #import <Foundation/Foundation.h>
    
    //对协议进行提前声明 ,跟@class的用途是一样的
    @protocol ButtonDelegate;
    
    @interface ButtonListener : NSObject <ButtonDelegate>
    
    @end
    #import "ButtonListener.h"
    #import "Button.h"
    @implementation ButtonListener
    
    -(void)onClick:(Button *)btn{
        NSLog(@"ButtonListener已经监听到按钮%@被点击",btn);
    }
    @end

    c.调用

    #import <Foundation/Foundation.h>
    #import "Button.h"
    #import "ButtonListener.h"
    
    int main(int argc, const char * argv[])
    {
    
        @autoreleasepool {
            
         
            Button *button=[[[Button alloc] init]autorelease];
            Button *button2=[[[Button alloc] init]autorelease];
            ButtonListener *listener=[[[ButtonListener alloc] init]autorelease];
            button.delegate=listener;
            button2.delegate=listener;
            //按钮1被点击
            [button click];
            [button2 click];
        }
        return 0;
    }

    打印结果:

    2013-08-29 22:00:24.276 Protocol[6473:303] ButtonListener已经见听到按钮<Button: 0x1001098d0>被点击

    2013-08-29 22:00:24.281 Protocol[6473:303] ButtonListener已经见听到按钮<Button: 0x10010b690>被点击

    3.Protocol补充

    #import <Foundation/Foundation.h>
    
    @protocol Study <NSObject>
    //不加限制 默认是required 
    //@required   表示必须实现的方法
    //虽然是必须实现,但编译器并不强求某个类必须实现
    @required
    -(void)test;
    -(void)test1;
    //@optional 表示可选(可实现、也可以不实现)
    @optional
    -(void)test2;
    @end
    #import <Foundation/Foundation.h>
    #import "Study.h"
    #import "Learn.h"
    @protocol Study,Learn;
    //遵循多个协议
    @interface Student : NSObject <Study,Learn>
    
    @end
    #import <Foundation/Foundation.h>
    #import "Student.h"
    int main(int argc, const char * argv[])
    {
    
        @autoreleasepool {
            Student *stu=[[[Student alloc ]init]autorelease];
            //
            if([stu conformsToProtocol:@protocol(Study)]){
                NSLog(@"Student遵守了Study这个协议");
            }
        }
        return 0;
    }

    2013-09-02 21:44:08.659 Protocol[3491:303] Student遵守了Study这个协议

    3.Block

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

    a.Block定义和调用

            //Block定义
            int (^Add) (int,int)=^(int a,int b){
                return a+b;
            };
            //调用Block
            int a=Add(5,6);
            NSLog(@"a=%i",a);//打印结果a=11;

    b.使用typedef定义

    typedef int (^Add) (int,int);
    int main(int argc, const char * argv[])
    {
    
        @autoreleasepool {
            Add add=^(int a,int b){
                return a+b;
            };
            NSLog(@"123+321=%i",add(123,321));//打印结果
        }
        return 0;
    }

    c.Block可以访问外面定义的局部变量,但是不能修改。声明变量使用__block关键字可以进行修改。

            int i=10;
            int j=11;
            __block int k=12;
            Add add=^(int a,int b){
                NSLog(@"i=%i",i);
                //j=111;//variable is not assignable
                k=122;
                NSLog(@"k=%i",k);
                return a+b;
            };

    d.使用block实现回调

    #import <Foundation/Foundation.h>
    @class  Button;
    //<>代表实现某个协议
    typedef void (^ButtonBlock) (Button *);
    
    @interface Button : NSObject
    @property (nonatomic,assign) ButtonBlock block;
    -(void)click;
    @end
    #import "Button.h"
    
    
    @implementation Button
    
    -(void)click{
        _block(self);
    }
    @end
    #import <Foundation/Foundation.h>
    #import "Button.h"
    int main(int argc, const char * argv[])
    {
    
        @autoreleasepool {
            Button *btn=[[[Button alloc] init]autorelease];
            btn.block=^(Button *btn){
                NSLog(@"按钮%@被点击了",btn);
            };
            [btn click];//打印:按钮<Button: 0x1001098d0>被点击了
        }
        return 0;
    }

    2.Block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。它和传统的函数指针很类似但是有区别。block是inline(内联函数)的,并且默认情况下它对局部变量是只读的。

    3.苹果官方建议尽量多用block。在多线程、异步任务、集合遍历、集合排序、动画转场用的很多。

    http://blog.csdn.net/totogo2010/article/details/7839061

  • 相关阅读:
    MSSQL_打开xp_cmdshell
    想在win7 32bit的情况下装个64位虚拟机的想法
    查看系统已运行了多久
    sql弄个表结构出来..
    在win下的cmd 的find
    告别google.com.hk的龟速
    VC常用数据类型使用转换详解
    C++中的文件输入/输出ios:xx eat Processing(zz)
    X86汇编语言学习手记(1)
    程序员数据结构笔记
  • 原文地址:https://www.cnblogs.com/malinkang/p/3276640.html
Copyright © 2020-2023  润新知