OC提供了一种与众不同的方式--Category,可以动态的为已经存在的类添加新的行为(方法)
这样可以保证类的原始设计规模较小,功能增加时再逐步扩展。
使用Category对类进行扩展时,不需要创建子类
Category使用简单的方式,实现了类的相关方法的模块化,把不同的类方法分配到不同的分类文件中
()代表着一个分类 ()中的代表者分类的名称
也可以为系统子类的类添加一些扩展方法
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这个协议
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