@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):规定一套标准
一.
- 协议定义了应该实现什么,但不关心怎样实现(只有一个.h文件).
- OC的协议就是@protocol声明的一组方法列表
- 什么时候用到协议?当要办一件事,时间尚未成熟,但还是想去完成,就委托某人去走这件事,同时委托人定义了一套双方间的标准.
二.确认协议(相当于签字)
- 确认协议从某种程度上约束了类或对象的行为(方法),同时也让该类的行为得到拓展.
- 协议能实现多继承(如:学生确认租房协议成为中介)
- 哪个类确认了协议,就要实现协议中规定的方法
三.
- 协议分:必须协议@required和可选协议@optional,相当于中介找房子行为必须实现,推荐房源行为可实现可不实现.
- 使用[对象 conformsToProtocol:@protocol(SelerProtocol)]判断是否遵循协议
四.协议特点
- 可以规范类的行为
- 利于系统设计(ui体验)
- 利于团队开发
- 协议应用于代理
五.代理模式
- A想做某件事,但时间时机条件不成熟时,B就是A实现(做)这件事,在这个过程中,B就是A的代理(人).A委托B去做这件事,A应该声明一套协议(一系列方法)来约束B的行为,同时B要确认A的协议并实现协议上的事情(方法).
- 应用于两个对象传递信息(传值),即A声明协议中方法的信息(参数)传给代理
- 传值的意义:当资源分散到2个类时,A将它拥有的资源告诉B,结合B的资源去达到某种目的.
- 代理模式的方向性?
六.
委托和委托方双方的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来处理。
七.
----------------------------------------------------------------------------------------------------------------------------
类目
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); }