NSObject是cocoa中的老祖宗,所有类都继承自它。今天来研究下它。下面是NSObject的官方文档:
+ initialize
+ load
+ alloc
+ allocWithZone:
– init
– copy
+ copyWithZone:
– mutableCopy
+ mutableCopyWithZone:
– dealloc
+ new
+ class
+ superclass
+ isSubclassOfClass:
+ instancesRespondToSelector:
+ conformsToProtocol:
– methodForSelector:
+ instanceMethodForSelector:
+ instanceMethodSignatureForSelector:
– methodSignatureForSelector:
+ description
– autoContentAccessingProxy
– performSelector:withObject:afterDelay:
– performSelector:withObject:afterDelay:inModes:
– performSelectorOnMainThread:withObject:waitUntilDone:
– performSelectorOnMainThread:withObject:waitUntilDone:modes:
– performSelector:onThread:withObject:waitUntilDone:
– performSelector:onThread:withObject:waitUntilDone:modes:
– performSelectorInBackground:withObject:
+ cancelPreviousPerformRequestsWithTarget:
+ cancelPreviousPerformRequestsWithTarget:selector:object:
– forwardingTargetForSelector:
– forwardInvocation:
+ resolveClassMethod:
+ resolveInstanceMethod:
– doesNotRecognizeSelector:
– awakeAfterUsingCoder:
– classForCoder
– classForKeyedArchiver
+ classFallbacksForKeyedArchiver
+ classForKeyedUnarchiver
– replacementObjectForCoder:
– replacementObjectForKeyedArchiver:
+ setVersion:
+ version
– finalize
首先先看alloc静态方法,调用alloc返回一个该类对象的内存指针。之后还需要调用init方法来初始化该对象。具体形式如下所示:
TheClass *newObject = [ [ TheClass alloc ] init];
- (id)init{
self = [super init];
if(self){
//Initalize self.
}
return self;
}
接下来看一下copy,深浅拷贝就不在此赘述了。要调用copy方法就得实现-(id)copyWithZone方法(copy会自动调用该方法)。实现-(id)copyWithZone方法得先遵循NSCopying协议(定义在了NSObject.h里)。好接下来看一下如何实现深拷贝:
/*Car.h*/
#import
@interface Car : NSObject
@property double price;
- (void)showMyPrice;
- (id)initWithPrice:(double)price;
@end
/*Car.m*/
#import "Car.h"
@implementation Car
{
Car *other;
}
- (void)showMyPrice{
NSLog(@"my price is %f",self.price);
}
- (id)init {
self = [super init];
if(self){
self.price = 150000;
}
return self;
}
- (id)initWithPrice:(double)price{
self = [super init];
if (self){
self.price = price;
}
return self;
}
- (id)copyWithZone:(NSZone *)zone{
Car *car = [[Car alloc] init];
car.price = self.price;
return car;
}
@end
/*main*/
#import
#import "Car.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Car *car = [[Car alloc] initWithPrice:260000];
[car showMyPrice];
Car *bus = [car copy];
[bus showMyPrice];
car.price=90900;
[car showMyPrice];
[bus showMyPrice];
}
return 0;
}
结果:
2014-04-07 21:36:38.340 NSObjectLearning[2235:303] my price is 260000.000000
2014-04-07 21:36:38.342 NSObjectLearning[2235:303] my price is 260000.000000
2014-04-07 21:36:38.342 NSObjectLearning[2235:303] my price is 90900.000000
2014-04-07 21:36:38.343 NSObjectLearning[2235:303] my price is 260000.000000
mutableCopy VS copy
mutableCopy更多是针对集合类而言,copy和mutablecopy方法,顾名思义,copy就是复制了一个imutable的对象,而mutablecopy就是复制了一个mutable的对象。以下将举几个例子来说明:
NSMutableString *string = [NSMutableString stringWithString: @"origion"];
NSString *stringCopy = [string copy];
NSMutableString *mStringCopy = [string copy];
NSMutableString *stringMCopy = [string mutableCopy];
[mStringCopy appendString:@"mm"];//error
[string appendString:@" origion!"];
[stringMCopy appendString:@"!!"];
+ (BOOL)instancesRespondToSelector:(SEL)aSelector方法是用来判断该类是否支持一个方法
if([CarinstanceMethodForSelector:@selector(hello)]==YES)
NSLog(@"yes");
else
NSLog(@"NO");
//验证对象支持一个方法
//验证对象支持一个方法}
(methodForSelector摘自http://www.cnblogs.com/GnagWang/archive/2012/06/14/2549422.html)
利用NSObject类中的methodForSelector:方法,可以获得一个指向方法实现的指针,并可以使用该指针直接调用方法实现, 当一个消息要被发送给某个对象很多次的时候,可以直接使用methodForSelector:来进行优化,其中,methodForSelector:是由Cocoa Runtime System提供的,而不是Objective-C本身的语言特性。这里需要注意转换过程中函数类型的正确性,包括返回值和参数,而且这里的前两个参数需要显示声明为id和SEL。
type void setterFunc void (*setter)(id, SEL, BOOL);
//
void (*setter)(id, SEL, BOOL);
int i;
setterFunc setterFun = (setterFunc)[target
methodForSelector:@selector(setFilled:)];
for ( i = 0; i < 1000, i++ )
setter(targetList[i], @selector(setFilled:), YES);
//
一个Objective-C方法本质上是一个拥有至少两个参数(self和_cmd)的C函数,可以利用class_addMethod向一个类添加一个方法。比如对于下面的函数, 类别应该就是用的这个东西吧。
向一个对象发送它不处理的消息是一个错误,不过在报错之前,Runtime System给了接收对象第二次的机会来处理消息。在这种情况下,Runtime System会向对象发一个消息,forwardInvocation:,这个消息只携带一个NSInvocation对象作为参数——这个NSInvocation对象包装了原始消息和相应参数。
通过实现forwardInvocation:方法(继承于NSObject),可以给不响应的消息一个默认处理方式。正如方法名一样,通常的处理方式就是转发该消息给另一个对象:
//
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if ([someOtherObject respondsToSelector:[anInvocation selector]])
[anInvocation invokeWithTarget:someOtherObject];
else
[super forwardInvocation:anInvocation];
}
//
对于不识别的消息(在dispatch table中找不到),forwardInvocation:就像一个中转站,想继续投递或者停止不处理,都由开发人员决定
我们可以通过NSObject的一些方法获取运行时信息或动态执行一些消息:
class 返回对象的类;
isKindOfClass 和 isMemberOfClass检查对象是否在指定的类继承体系中;
respondsToSelector 检查对象能否相应指定的消息;
conformsToProtocol 检查对象是否实现了指定协议类的方法;
methodForSelector 返回指定方法实现的地址。
performSelector:withObject 执行SEL 所指代的方法。