在ViewController文件里
#import "ViewController.h"
#import "Tool.h"
#import "Tool+Tool_Category.h"
#import "MyClass.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//类目,延展,协议
#pragma mark -------------------类目------------------------
/*
类目
定义:为现有工程中的类和系统类添加新的方法
作用:在类目中添加新的方法及属性 和 在原类中添加方法及属性是一样的,都能够被类和类的子类调用,这样可以快速便利地维护和开发项目.
note:如何在类目中为原类添加新的方法及属性?
*/
Tool *tool = [[Tool alloc] init];
//这是键值访问,即KVC
[tool setValue:@"Yong" forKey:@"_name"];
[tool setProperty2:@"property2"];//给类目的property2赋值
[tool function1];
[tool function2];
[tool function3];
MyClass *myClass = [MyClass new];
[myClass setValue:@"Chen" forKey:@"property3"];//给延展的property3赋值
/*
非正式协议:由于几乎所有的类都继承于NSObject(其余的继承于NSProxy),由于NSObject的特殊性,所以NSObject的类目声明称为'非正式协议'.创建一个NSObject的类目而不实现,称为'创建一个非正式协议'.
*/
//-(BOOL)respondsToSelector这个方法可以检查当前对象是否能够响应selector方法
if ([myClass respondsToSelector:@selector(test1)])
{
[myClass test1];
}
if ([myClass respondsToSelector:@selector(test2)])
{
[myClass test2];
}
在Tool.h文件里
#import <Foundation/Foundation.h>
@interface Tool : NSObject
{
NSString *_name;
}
//原类的属性
@property(nonatomic,strong)NSString *propert1;
//原类中的方法
-(void)function1;
@end
#pragma mark ---------------类目------------------
//在类目中为原类添加新的属性及方法
/*
类目就是为已存在的类添加新的方法.但是不能添加实例变量.
类目的使用场景
1.类包含了很多个方法实现,而这些方法需要不同团队的成员来实现.
2.当你在使用基础类目中的类时,你不想继承这些类而指向添加一些方法时.
类目能实现上面的需求,当然也有使用类目时需要注意的问题
1.类目可以访问原始类的实例变量,但不能添加实例变量,如果想添加实例变量,那就通过继承创建子类来实现.
2.类目可以重载原始类的方法,但是不推荐这么做,这样会覆盖原始类的方法,如果确实要重载,那就通过继承创建子类来实现.
3.和普通接口有所区别的是,在类目的实现文件中的实例方法只要你不去调用它你可以不用实现声明的所有方法
*/
@interface Tool (ToolCategory)
/*
在一般情况下,我们是不能向Category添加属性的,只能添加方法,但有些情况下,我们是确实需要向Category中添加属性,而且系统的API也有一些在Category中添加属性的情况.那么这到底怎么实现的呢?
ios运行时机制
ios运行时机制,简单来说,就是苹果为开发者提供的一套在运行时动态创建类,属性,方法的API.它是一套纯C语言的API,使用相应的API就可以通过Category给一个原本存在的类添加属性.
*/
@property(nonatomic,strong)NSString *property2;
-(void)function2;
//通过类目重载原类方法
-(void)function1;
在Tool.m文件里
#import "Tool.h"
#import <objc/runtime.h>
@implementation Tool
-(void)function1
{
NSLog(@"我是functiaon1");
}
@end
@implementation Tool (ToolCategory)
-(void)function2
{
//类目可以访问原类的实例变量
NSLog(@"%@",_name);
NSLog(@"I am function2");
NSLog(@"property2 = %@",[self property2]);//调用property2
}
#pragma mark -----------------合成类目中的属性---------------
-(void)setProperty2:(NSString *)property2
{
/*
<#id object#> :给哪个对象的属性赋值
<#const void *key#> :属性对应的key
<#id value#> :设置属性值为value
<#objc_AssociationPolicy policy#> :使用的策略,是一个枚举值,手机开发一般都选择NONATOMIC
如下取值:
OBJC_ASSOCIATION_ASSIGN = 0 //assign策略
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1 //retain策略
OBJC_ASSOCIATION_COPY_NONATOMIC = 3 //copy策略
OBJC_ASSOCIATION_RETAIN = 01401
OBJC_ASSOCIATION_COPY = 01403
*/
objc_setAssociatedObject(self, @selector(property2), property2, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSString *)property2
{
return objc_getAssociatedObject(self, @selector(property2));
}
-(void)function1
{
NSLog(@"我是通过类目重载的function1");
}
@end
在MyClass.h文件里
#import <Foundation/Foundation.h>
#import "NSObject+Nsobject_Category.h"
//不能在这里导入延展的头文件,在.m文件导入
//#import "MyClass_MyClass_Extension.h"
@interface MyClass : NSObject
@end
在MyClass.m文件里
#import "MyClass.h"
#import <objc/runtime.h>
#import "MyClass_MyClass_Extension.h"
#pragma mark ----------------延展-------------
/*
延展的作用就是定义自己的私有方法
形式和类目相同,不必新创建文件,只是把类目的interface文件放在你需要扩展的类的.m文件里
*/
@interface MyClass ()
@property(nonatomic,retain)NSString *property3;
-(void)testExtension;
@end
@implementation MyClass
-(void)test1
{
NSLog(@"I am test1");
}
-(void)test2
{
NSLog(@"I am test2");
[self testExtension];
NSLog(@"property3 = %@",[self property3]);
[self myClassExtension2];
}
//延展的实现
-(void)testExtension
{
NSLog(@"I am 延展");
}
//OC运行时设置延展中的属性
-(void)setProperty3:(NSString *)property3
{
objc_setAssociatedObject(self, @selector(property3), property3, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSString *)property3
{
return objc_getAssociatedObject(self, @selector(property3));
}
-(void)myClassExtension2
{
NSLog(@"我是延展2");
}
@end