类目、延展、协议

@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);
}
原文地址:https://www.cnblogs.com/huen/p/3533097.html