NSObject 学习

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

Initializing a Class

Creating, Copying, and Deallocating Objects

Identifying Classes

Testing Class Functionality

Testing Protocol Conformance

Obtaining Information About Methods

Describing Objects

Discardable Content Proxy Support

Sending Messages

Forwarding Messages

Dynamically Resolving Methods

Error Handling

Archiving

Deprecated Methods

   首先先看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:@"!!"];


以上四个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 所指代的方法。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值