iOS 使用全能的初始化方法

本文深入解析了NSDate类的各种初始化方法及其内部实现原理,探讨了它们之间的联系与区别,并通过实例展示了如何正确使用这些方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言 :在苹果的开发文档中我们发现 NSDate 这个类的初始方法:

- (instancetype)initNS_DESIGNATED_INITIALIZER;

- (instancetype)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)tiNS_DESIGNATED_INITIALIZER;

- (nullableinstancetype)initWithCoder:(NSCoder *)aDecoderNS_DESIGNATED_INITIALIZER;

+ (instancetype)date;

+ (instancetype)dateWithTimeIntervalSinceNow:(NSTimeInterval)secs;

+ (instancetype)dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval)ti;

+ (instancetype)dateWithTimeIntervalSince1970:(NSTimeInterval)secs;

+ (instancetype)dateWithTimeInterval:(NSTimeInterval)secsToBeAdded sinceDate:(NSDate *)date;

那么这些初始化方法之间的关系是怎样的呢?  还是说毫无关联。其实它们都使用了一个共同的初始化方法- (instancetype)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)ti NS_DESIGNATED_INITIALIZER;  我们可以使用NSRuntime 进去看看最终都会进入

这个初始化方法。我们把这个方法称为全能初始化方法。 这里就不介绍NSRuntime了。 那么apple 为什么要这样做呢?,在实际开发过程中我们应当如何使用和注意呢?

二: 实际使用

每个子类的全能初始化方法都应该调用起超类的对应的方法.并逐层向上。当底层数据存储机制改变时,只需修改此方法的代码就好.无需改动其他的初始化方法而且能减少消息的转发带来的消耗

 新建类

@interface EOCRectangle : NSObject<NSCoding>


@property (nonatomic,assign,readonly)float width;


@property (nonatomic,assign,readonly)float height;


- (instancetype)initWithWidth:(float) width

                    andHeight:(float )height;


@end


- (instancetype)initWithWidth:(float) width

                    andHeight:(float )height

{

    NSLog(@"rectangle init initWithWidthAndHeight");

    if (self=[superinit]) {

        _width=width;

        _height=height;

    }

    returnself;

}


/*

 但是开发者有可能直接调用了 init 方法 因为NSObject 是实现了init方法了的

 */


- (instancetype)init

{

    NSLog(@"rectangle init ");

    return [selfinitWithWidth:5.0f andHeight:10.0f];

}


当然如果你不写的话会使用默认的0 来代替 这样的长方形显然没有实际的意义。 但是如果你使用新的类 EOCSquare 继承自EOCRectangle

我们要求长和宽都相等。

@interface EOCSquare : EOCRectangle


- (instancetype)initWithDimension:(float)dimension;


@end


//  即时默认的 init方法 也要重写我们可以想象如果 没有重写

//  调用其父类的 initWithWidth 方法生成的 10 5 的正方形的例子

-(instancetype)init

{

    return [selfinitWithDimension:5.0f];

}


- (instancetype)initWithDimension:(float)dimension

{

    NSLog(@"square initWith dimension ---");

    return [superinitWithWidth:dimension andHeight:dimension];

}



//  很有可能用户会调用 initWithWidth andHeight方法

//  我们需要保证 square正方形 width height 是一致的

- (instancetype)initWithWidth:(float)width andHeight:(float)height

{

    NSLog(@"square init width and height ");

    float dimension=MAX(width, height);

    return [selfinitWithDimension:dimension];

    

}


其次要特别注意 NSCoding 这个地方


#pragma mark ---- initializer from NSCoding


在 EOCRectangle 中要这样写

/**

  NSCoding协议  序列化


 @param aDecoder aDecoder description

 @return return value description

 */


/*

 !!!!

 NSCoding 协议的初始化方法没有调用本类的全能初始化方法

 而是调用了超类的相关方法而且若超类 也实现了了NSCoding,

 则改为调用调用超类的 initWithCoder: 初始化方法

 

 */

- (id)initWithCoder:(NSCoder *)aDecoder

{

    if (self=[superinit]) {

        _width=[aDecoderdecodeFloatForKey:@"width"];

        _height=[aDecoderdecodeFloatForKey:@"height"];

    }

    returnself;

}



在 EOCSquare 中要这样写

#pragma mark ----  NSCoding 


/*

    !!!  由于父类中写了这个 initWithCoder 方法 

    所以我们

    initCoder 中也要遵守NSCoding协议 如果没有调用超类的同名方法.而是调用了自制的初始化方法

    或者超类的其他初始化方法 .那么EOCRectangle类的initWithCoder 方法就没机会执行

    于是 无法将 _width _height这两个实例 变量解码了

 */

- (id)initWithCoder:(NSCoder *)aDecoder

{

    if (self=[superinitWithCoder:aDecoder]) {

        

    }

    returnself;

}


大概的意思就是这样了。


















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值