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 <Foundation/Foundation.h> @interface Car : NSObject<NSCopying> @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 <Foundation/Foundation.h> #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 所指代的方法。