用OBJC编程 4 - Customizing Existing Classes
通过Category为类增加方法#import "XYZPerson.h"
@interface XYZPerson (XYZPersonNameDisplayAddtions)
- (NSString *)lastNameFirstNameString;
@end
// ----------------------
#import "XYZPerson+XYZPersonNameDisplayAddtions.h"
@implementation XYZPerson (XYZPersonNameDisplayAddtions)
- (NSString *)lastNameFirstNameString{
return [NSString stringWithFormat:@"%@ %@", self.lastName, self.firstName];
}
@end
//-------------------------------
#import "XYZPerson+XYZPersonNameDisplayAddtions.h"
@implementation SomeObject
-(void) someMethod{
XYZPerson *person = [[XYZPerson alloc] initWithFirstName:@"John", lastName:@"Doe"];
NSLog(@"The people is %@", [person lastNameFirstNameString]);
}
@end
Category 可以增加任何的实例方法和类方法,但是通常不适合增加Property,虽然语法上可以声明一个Property,但不能通过Category增加一个实例变量。这意味着不能synthesize任何实例变量, 也没有存取方法。 你可以写自己的accessor,但是不能keep track property,它们存储在原始的类里。避免名字冲突Category 的新增方法可能会导致名字冲突,在运行时可能会出现未知的行为,为了避免这种情况,需要增加前缀@interface NSSortDescriptor (XYZAdditions)
+ (id)xyz_sortDescriptorWithKey:(NSString *)key ascending:(BOOL)ascending;
@end
// ------ use it -------
NSSortDescriptor *descriptor = [NSSortDescriptor xyz_sortDescriptorWithKey:@"name" ascending:YES];
类扩展类似分类,但只能用于编译时有源码情况,并且必须写在实现文件里,因此不能通过这个为框架类扩展。扩展语法类似分类@interface ClassName ()
{
id _someCustomInstanceVariable;
}
@property NSObject *extraProperty;
@end
也叫匿名分类。不像分类那样,扩展可以增加属性和实例变量。编译器会自动synthesize accessor方法。如果你增加方法,必须实现在主要的@implementation代码块里。可以用扩展来声明私有属性和方法@interface XYZPerson:NSObject
@proerty (readonly) NSString *uniqueIdentifier;
-(void)assignUniqueIdentifier;
@end
/// ---------------------
@interface XYZPerson ()
@property (readwrite) NSString *uniqueIdentifier;
@end
@implementation XYZPerson
// ,,,
@end
像上面那样重复声明uniqueIdentifier为readwrite,每一个运行时的XYZPerson对象都将存在一个setter。任何访问私有方法,或者set一个readonly属性的行为,编译器都会产生错误,但是可以通过动态运行时特性避免编译器错误,诸如调用NSObject的performSelector方法。如果你打算构建私有方法或属性,你可以声明一个分离的头文件来声明扩展,诸如XYZPerson.h和XYZPersonPrivate.h分类和扩展并不是定制一个类的唯一途径,也不是最好方法,要考虑可否使用子类化或者委托的方法来实现。