• 类目、延展、协议


    @class 类名; //编译时只有这个类(不包括该类的变量、方法),加快编译。常用于复合对象和循环依赖问题中。#import、#include和@class的区别:http://blog.sina.com.cn/s/blog_71715bf80101a8t8.html

    id <协议名> _delegate;//代理(实现协议的对象)。

    类目、延展、协议都是针对方法。

    ----------------------------------------------------------------------------------------------------------------------------

    类目(Category

    1.作用:为已有的类(有没有源码的类都可以,包括系统类)添加方法

    2.格式:类似于类

    • 声明部分:没有继承,后加上(类目名)
    • 实现部分:后加上(类目名)
    • 文件名:类名+类目名

    3.在类目中self的作用是访问设置变量,方法.

    4.类目用处:

    • 扩展别人的类
    • 类目把代码放到多个文件中,便于多人开发,当然也会降低性能.

    5.注意

    • 类目只能给已有的类添加多个方法,无法添加实例变量,此时可以通过字典类型的参数解决。
    • 类目的方法和已有类的方法名称冲突时,类目中的方法会覆盖原有的方法。
    • 通过类目给一个新类添加新方法来扩展这个类不仅影响这个类,同时会影响他的子类,因为他的每个子类都将继承这些新方法。若为NSObject添加类目(即非正式协议)。

    ----------------------------------------------------------------------------------------------------------------------------

    延展(extension

    1.作用:定义私有方法.

    2.实现延展的形式

    • 延展形式1:编写(声明)在类的实现文件,定义的方法在类中实现.
    • 延展形式2:在自己类的实现文件中添加私有类目来声明私有方法。(延展只有一个.h文件)
    • 延展形式3:新语法最常用,方法不在.h头文件声明,直接在.m定义这个方法,相当于私有方法。

    3.延展可以定义成员变量,只供类里使用.

    ----------------------------------------------------------------------------------------------------------------------------

    协议(protocol:规定一套标准

    一.

    1. 协议定义了应该实现什么,但不关心怎样实现(只有一个.h文件).
    2. OC的协议就是@protocol声明的一组方法列表
    3. 什么时候用到协议?当要办一件事,时间尚未成熟,但还是想去完成,就委托某人去走这件事,同时委托人定义了一套双方间的标准.

    二.确认协议(相当于签字)

    1. 确认协议从某种程度上约束了类或对象的行为(方法),同时也让该类的行为得到拓展.
    2. 协议能实现多继承(如:学生确认租房协议成为中介)
    3. 哪个类确认了协议,就要实现协议中规定的方法

    三.

    1. 协议分:必须协议@required和可选协议@optional,相当于中介找房子行为必须实现,推荐房源行为可实现可不实现.
    2. 使用[对象 conformsToProtocol:@protocol(SelerProtocol)]判断是否遵循协议

    四.协议特点

    1. 可以规范类的行为
    2. 利于系统设计(ui体验)
    3. 利于团队开发
    4. 协议应用于代理

    五.代理模式

    1. A想做某件事,但时间时机条件不成熟时,B就是A实现(做)这件事,在这个过程中,B就是A的代理(人).A委托B去做这件事,A应该声明一套协议(一系列方法)来约束B的行为,同时B要确认A的协议并实现协议上的事情(方法).
    2. 应用于两个对象传递信息(传值),即A声明协议中方法的信息(参数)传给代理
    3. 传值的意义:当资源分散到2个类时,A将它拥有的资源告诉B,结合B的资源去达到某种目的.
    4. 代理模式的方向性?

    六.

    委托和委托方双方的property声明属性都是assign而不是retain
    为了避免循环引用造成的内存泄露。
    循环引用的问题这样理解:
    比如在main函数中创建了两个类的对象A和B,现在引用计数都是1。现在让A和B互相引用(A有一个属性是B对象,属性说明是retain;B有一个属性是A对象,属性说明是retain),现在两个对象的引用计数都增加了1,都变成了2。
    现在执行[A release]; [B release]; 此时创建对象的main函数已经释放了自己对对象的所有权,但是此时A和B的引用计数都还是1,因为他们互相引用了。
    这时你发现A和B将无法释放,因为要想释放A必须先释放B,在B的dealloc方法中再释放A。同理,要想释放B必须先释放A,在A的dealloc方法中再释放B。所以这两个对象将一直存在在内存中而不释放。这就是所谓的循环引用的问题。
    要想解决这个问题,一般的方法可以将引用的属性设置为assign,而不是retain来处理。

    七.

    @class
          @class就是告诉编译器有这个类存在,但是类是如何实现的不用告诉编译器.若.m文件用到了这个类,还是要在.m文件汇总import这个类的。
          既然这样,为什么不直接在头文件中import呢,举个例子:
          class A引用了class B,class B引用了class C.... , class A,B,C...的头文件又import了很多文件,那么 import了A的话,编译器就需要编译大量的文件,编译时间就会增加。 
          难道头文件中都是用@class吗?当然不是,有时也是需要#import的,那么什么时候该用什么呢?
    (1)一般如果有继承关系的用#import,如B是A的子类那么在B中声明A时用#import;
    (2) 另外就是如果有循环依赖关系,如:A->B,B->A这样相互依赖时,如果在两个文件的头文件中用#import分别声明对方,那么就会出现头文件循环利用的错误,这时在头文件中用@class声明就不会出错;
    (3)还有就是自定义代理的时候,如果在头文件中想声明代理的话如@interface SecondViewController:UIViewController时应用#import不然的话会出错误,注意XXXXDelegate是自定义的。
     

    ----------------------------------------------------------------------------------------------------------------------------

    类目

    NSString+SayHi.h

    #import <Foundation/Foundation.h>
    
    @interface NSString (SayHi)
    
    //@property(nonatomic,retain)NSString *name;
    
    -(void)sayHi;
    @end

    NSString+SayHi.m

    #import "NSString+SayHi.h"
    
    @implementation NSString (SayHi)
    
    //@dynamic name;?
    -(void)sayHi
    {
        [self stringByAppendingFormat:@" and bill"];
        NSLog(@"%@ hello world",self);
    }
    @end

    NSMutableArray+Revert.h

    #import <Foundation/Foundation.h>
    
    @interface NSMutableArray (Revert)
    -(void)revert;
    @end

    NSMutableArray+Revert.m

    #import "NSMutableArray+Revert.h"
    
    @implementation NSMutableArray (Revert)
    -(void)revert
    {
        int count = self.count;
        for ( int i = 0; i < count/2; i++)
        {
            [self exchangeObjectAtIndex:i withObjectAtIndex:count-i-1];
        }
    }
    @end

    延展

    Teacher.h

    #import <Foundation/Foundation.h>
    
    @interface Teacher : NSObject
    
    -(void)onClass:(NSString *)aClassName;
    
    @end

    Teacher.m

    #import "Teacher.h"
    /*
    //声明定义私有方法
    @interface Teacher ()
    {
        NSString *_name;
    }
    @property(nonatomic,retain)NSString *name;
    -(void)prepareClass:(NSString *)aClassName;
    @end
    */
    
    @implementation Teacher
    //@synthesize name = _name;
    
    -(void)prepareClass:(NSString *)aClassName//5.0+新语法,.h没声明的方法就是私有方法
    {
        //备课
        NSLog(@"prepare Class %@",aClassName);
    }
    
    -(void)onClass:(NSString *)aClassName
    {
        //self.name = @"jobs";//对类里
        //备课
        //[self prepareClass:aClassName];
        //上课
        //NSLog(@"%@ teaching %@",self.name,aClassName);
        NSLog(@"teaching %@",aClassName);
    }
    
    
    @end

    Teacher_PrivateClass.h

    #import "Teacher.h"
    
    @interface Teacher ()
    -(void)privateMethod;
    @end

     AppDelegate.m

    NSString *str = @"jobs";
        [str sayHi];
        
        //str.name = @"bill";
        
        NSArray *arr = @[@"1",@"2",@"3",@"4"];//ios5.0+出新语法
        NSMutableArray *marr = [NSMutableArray arrayWithArray:arr];
        
        [marr revert];//倒置
        NSLog(@"mArr = %@",marr);//数组输出是(),字典是{},set是{()}
        
        //延展
        Teacher *t = [[Teacher alloc]init];
        [t onClass:@"ios"];
    
        //[t prepareClass:@"html"];不能调用私有方法//ios早些版本是可以执行.说明没有私有方法,属于伪私有

     ----------------------------------------------------------------------------------------------------------------------------

    协议2

    RentDelegate.h

    /*
     @overview:学生定义的租房协议
     @autuor:huen
     @time:2014-2-10
     协议不承载信息(成员变量)
     */
    
    #import <Foundation/Foundation.h>
    
    @protocol RentDelegate <NSObject>//遵循于NSObject协议,相当现实于协议再引进其他协议
    
    @required
    -(void)findHouse:(NSString *)aHouse//参数即房子条件信息,几居几钱,代理传值
           withMoney:(int)aMoney;
    
    @optional//可选
    -(BOOL)hasNewHouse;
    
    @end

    Student.h

    #import <Foundation/Foundation.h>
    #import "RentDelegate.h"
    
    @interface Student : NSObject 
    {
        NSString *_name;
    }
    @property(nonatomic,assign)id<RentDelegate> delegate;
    @property(nonatomic,retain)NSString *name;
    //租房
    -(void)rentHouse;
    @end

    Student.m

    #import "Student.h"
    
    @implementation Student
    @synthesize name = _name,delegate = _delegate;
    
    //租房
    -(void)rentHouse
    {
        //让中介帮助学生找房
        if ([self.delegate conformsToProtocol:@protocol(RentDelegate)])
        {
        [self.delegate findHouse:@"one big" withMoney:1000]; //代理传值,将学生资源传给代理
        }
        
        //中介推荐租房信息
        if ([self.delegate conformsToProtocol:@protocol(RentDelegate)])
        {
            if ([self.delegate respondsToSelector:@selector(hasNewHouse)])
            {
                [self.delegate hasNewHouse];
            }
        }
    }
    
    @end

    Mediator.h

    import <Foundation/Foundation.h>
    #import "RentDelegate.h"
    @interface Mediator : NSObject <RentDelegate>
    {
        NSString *_name;
    }
    @property(nonatomic,retain)NSString *name;
    
    
    @end

    Mediator.m

    #import "Mediator.h"
    
    @implementation Mediator
    @synthesize name = _name;
    
    //收集房源
    -(int)collectHouses
    {
        return 5;
    }
    
    #pragma mark -RentDelegate-
    //实现协议中方法
    -(void)findHouse:(NSString *)aHouse withMoney:(int)aMoney
    {
        if ([self collectHouses] <= 0)
        {
            return;
        }
        NSLog(@"%@ has found %@ house with %d money",self.name,aHouse,aMoney);
    }
    
    -(BOOL)hasNewHouse
    {
        NSLog(@"has new house");
        return YES;
    }
    @end

    AppDelegate.m

    Mediator *m = [[Mediator alloc]init];
        m.name = @"jobs";
        
        Student *s = [[Student alloc]init];
        s.name = @"bill";
        
        s.delegate = m;
        [s rentHouse];

     ----------------------------------------------------------------------------------------------------------------------------

    SaleHuse.h

    #import <Foundation/Foundation.h>
    
    @protocol SaleHouse <NSObject>
    
    //@required
    -(void)saleHouse;
    -(void)payMoney;
    @end

    HouseSaler.h

    #import <Foundation/Foundation.h>
    
    #import "SaleHouse.h"
    
    @class Landlord;
    
    @interface HouseSaler : NSObject <SaleHouse>
    {
        Landlord *_customer;
    }
    
    @property(assign,nonatomic)Landlord *customer;
    
    -(void)registerInfo:(Landlord *)aCustomer;
    @end

    HouseSaler.m

    #import "HouseSaler.h"
    #import "Landlord.h"
    @implementation HouseSaler
    @synthesize customer = _customer;
    -(void)saleHouse { NSLog(@"我是中介,我替登记者卖房"); [self payMoney]; } -(void)payMoney { NSLog(@"我是中介,我卖了房了"); [self.customer receiveMoney]; } -(void)registerInfo:(Landlord *)aCustomer { self.customer = aCustomer; self.customer.delegate = self;//注册 } @end

    Landlord.h

    #import <Foundation/Foundation.h>
    #import "HouseSaler.h"
    @interface Landlord : NSObject
    {
        id<SaleHouse> _delegate;//代理(实现协议的对象)
    }
    
    @property(nonatomic,assign)id<SaleHouse> delegate;
    
    -(void)saleHouse;
    -(void)receiveMoney;
    
    @end

    Landlord.m

    #import "Landlord.h"
    
    @implementation Landlord
    @synthesize delegate = _delegate;
    
    -(void)saleHouse
    {
        NSLog(@"我是房东,我已经将房子登记到中介了");
    
        if ([self.delegate conformsToProtocol:@protocol(SaleHouse)])//注意:要中介中心登记注册后才有代理
        {
            [self.delegate saleHouse];
        }
        
    }
    
    -(void)receiveMoney
    {
        NSLog(@"我是房东,钱我收下了,谢谢中介了");
    }
    @end

    AppDelegate.m

    Landlord *landlord = [[Landlord alloc]init];
        
        HouseSaler  *houseSaler = [[HouseSaler alloc]init];
        
        [houseSaler registerInfo:landlord];//房东到中介注册成客户
        [landlord saleHouse];

     ----------------------------------------------------------------------------------------------------------------------------

    协议继承协议:

    1.创建一个定义协议1的BaseClass类,并回调协议中的方法.

    BaseClass.h

    #import <Foundation/Foundation.h>
    @protocol BaseClassDelegate;
    
    @interface BaseClass : NSObject
    
    @property(nonatomic,assign)id <BaseClassDelegate>delegate;
    -(void)oldmethod;
    
    @end
    
    
    
    @protocol BaseClassDelegate <NSObject>
    
    -(void)oldmessage:(NSString *)str;
    
    @end

    BaseClass.m

    #import "BaseClass.h"
    
    @implementation BaseClass
    @synthesize  delegate;
    
    -(void)oldmethod
    {
        [delegate oldmessage:@"BaseClass oldmethod called"];
    }
    @end

    2.创建一个BaseClass的子类SubClass,且定义协议2,并回调协议1和协议2中的代理方法

    SubClass.h

    #import <Foundation/Foundation.h>
    #import "BaseClass.h"
    
    @protocol SubClassDelegate;
    
    @interface SubClass : BaseClass
    @property(nonatomic,assign)id <SubClassDelegate>subdelegate;
    -(void)newmethod;
    @end
    
    
    
    
    @protocol SubClassDelegate <NSObject,BaseClassDelegate>
    @optional
    -(void)newmessage:(NSString *)str;
    
    @end

    SubClass.m

    #import "SubClass.h"
    
    @implementation SubClass
    @synthesize subdelegate;
    -(void)oldmethod
    {
        [super.delegate oldmessage:@"SubClass oldmethod called"];
    }
    
    
    -(void)newmethod
    {
        [super.delegate oldmessage:@"SubClass newmethod called"];
        [self.subdelegate newmessage:@"SubClass newmethod called"];
    }
    
    @end

    AppDelegate.m

        BaseClass *b = [[BaseClass alloc]init];
        b.delegate = self;
        [b oldmethod];
        
        SubClass *s = [[SubClass alloc]init];
        s.delegate = self;//因为对象是动态的所以不能继承下来
        s.subdelegate = self;
        [s oldmethod];
        [s newmethod];
    -(void)oldmessage:(NSString *)str
    {
        NSLog(@"oldmessage:%@",str);
    }
    
    -(void)newmessage:(NSString *)str
    {
        NSLog(@"newmessage:%@",str);
    }
  • 相关阅读:
    数据导入
    数据库导入导出命令
    题库
    struts2的配置文件简洁
    修改oralce11g 字符集为ZHS16GBK
    Linux上安装JDK+Tomcat
    Android中adb的使用
    【转】Android获取IP的方法,并可以判断手机是否联网
    Android中R.java没有自动生成问题
    Android中SQLiteOpenHelper的理解
  • 原文地址:https://www.cnblogs.com/huen/p/3533097.html
Copyright © 2020-2023  润新知