NSObject 学习

   NSObject是cocoa中的老祖宗,所有类都继承自它。今天来研究下它。下面是NSObject的官方文档:

Initializing a Class

  • + initialize
  • + load

Creating, Copying, and Deallocating Objects

  • + alloc
  • + allocWithZone:
  • – init
  • – copy
  • + copyWithZone:
  • – mutableCopy
  • + mutableCopyWithZone:
  • – dealloc
  • + new

Identifying Classes

  • + class
  • + superclass
  • + isSubclassOfClass:

Testing Class Functionality

  • + instancesRespondToSelector:

Testing Protocol Conformance

  • + conformsToProtocol:

Obtaining Information About Methods

  • – methodForSelector:
  • + instanceMethodForSelector:
  • + instanceMethodSignatureForSelector:
  • – methodSignatureForSelector:

Describing Objects

  • + description

Discardable Content Proxy Support

  • – autoContentAccessingProxy

Sending Messages

  • – 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:

Forwarding Messages

  • – forwardingTargetForSelector:
  • – forwardInvocation:

Dynamically Resolving Methods

  • + resolveClassMethod:
  • + resolveInstanceMethod:

Error Handling

  • – doesNotRecognizeSelector:

Archiving

  • – awakeAfterUsingCoder:
  • – classForCoder
  • – classForKeyedArchiver
  • + classFallbacksForKeyedArchiver
  • + classForKeyedUnarchiver
  • – replacementObjectForCoder:
  • – replacementObjectForKeyedArchiver:
  • + setVersion:
  • + version

Deprecated Methods

  • – 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:@"!!"];


以上四个NSString对象所分配的内存都是不一样的。但是对于mStringCopy其实是个imutable对象,所以上述会报错。
对于系统的非容器类对象,我们可以认为,如果对一不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝)。如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的。


+ (BOOL)instancesRespondToSelector:(SEL)aSelector方法是用来判断该类是否支持一个方法

        if([CarinstanceMethodForSelector:@selector(hello)]==YES)

            NSLog(@"yes");

        else

            NSLog(@"NO");

//验证对象支持一个方法

//验证对象支持一个方法


if ([c1 respondsToSelector: @selector(print)]==YES) {


printf("c1 has a print method. /n");


}


(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 所指代的方法。



你可能感兴趣的:(IOS学习笔记)