objective-c中的指定初始化程序和便利初始化程序以及如何正确创建它们并将它们绑定在一起

Yan*_*Yan 7 initialization objective-c ios

我试图了解哪个应该被指定初始化器和哪个便利初始化器.我读了关于那个主题的苹果文档,但我仍然不确定.指定的初始化程序是否必须具有该类所需的所有值?例如,
这是我创建的第一个指定的初始化程序

-(id)initWithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck
{
    self = [super init];
    if (self) {
        for(int i = 0; i<=cardCount;i++){
            Card *card = [deck drawRandomCard];
            if (!card) {
                self = nil;
                break;
            }else{
                self.cards[i] = card;
            }
        }
    }

    return self;
}
Run Code Online (Sandbox Code Playgroud)

现在adde cardMatchMode属性到这个类,并希望在初始化程序中设置它.为了使类向后兼容并理解初始化器,我保留了我现在拥有的那个并创建另一个初始化器.

-(id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode
{

    _cardMatchMode = matchMode;
    return [self initWithCardCount:cardCount usingDeck:deck];;
}
Run Code Online (Sandbox Code Playgroud)

基于apple docs,方便初始化程序必须返回指定初始化程序的值,但问题是我可以在便捷初始化程序中设置此类的额外属性吗?我可以说self.cardMatchMode = matchMode; 还是自我还没有完全初始化?
它确实有效,但我只是想了解这是否是正确的代码,我可以在方便init中访问cardMatchMode属性,或者我必须要 -(id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode

作为指定的初始化程序和另一个方便的init和返工代码?谢谢!

/////更新

我在收到错误

-(id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode
Run Code Online (Sandbox Code Playgroud)

当我试图做self = [self initWithCardCount:(NSUInteger)cardCount usingDeck:(Deck*)deck; 错误时说你不能在init系列之外分配自己.我明白了问题是什么.init方法有小写w,它必须是大写的,所以它现在有效.这是我现在用于方便初始化程序的代码.

-(id)initWithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode
{
    self = [self initWithCardCount:cardCount usingDeck:deck];
    if (self){
        _cardMatchMode = matchMode;
    }
    return self;
}
Run Code Online (Sandbox Code Playgroud)

现在更有意义了.我调用指定的init调用super,然后设置cardMatchMode变量.

据我所知,有很多对象具有带额外参数的便利初始化程序,它只会调用指定的init.如果你看一下NSString,它有不同的初始化器和不同的参数.它可能正在调用init,它是指定的初始化程序.它是否正确?

Fre*_*red 16

指定的初始值设定项是调用其类的超类的指定初始值设定项的初始值设定项,因此它是唯一调用对象上的方法的初始值设定项super.班上没有其他的初始化者应该这样做; 这些辅助初始值设定项应使用调用指定的初始值设定项self.通常,指定的初始值设定项具有创建类的有用对象所需的所有参数.

简而言之,指定的初始化程序是唯一一个调用初始化程序的程序super,并且该类中的所有其他初始化程序都会调用指定的初始化程序(使用self).


iva*_*lev 7

根据Apple文档,指定的初始化程序

通常是init ...方法,它具有最多的参数并且可以完成大部分初始化工作.

所以在你的情况下,这将是- (id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode.所有其他初始化程序将使用较少的参数,在指定的初始化程序中填充缺少参数的默认值或其他推断值.

因此,每个便利初始化程序都会调用指定的初始化程序而不是超类的初始化程序.

方便指定的初始化程序对在您的情况下将如下所示:

/**
 Convenience initializers
*/
- (id)init
{
    self = [self initwithCardCount:kDefaultCardCount usingDeck:[Deck defaultDeck] cardMatchMode:kCardMatchModeDefault];
    return self;
}

- (id)initWithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck
{
    self = [self initwithCardCount:cardCount usingDeck:deck cardMatchMode:kCardMatchModeDefault]; 
    if (self) {

    }

    return self;
}

/**
 Designated initializer
*/
- (id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode
{
    self = [super init];
    if (self) {
        for (int i = 0; i <= cardCount; i++) {
            Card *card = [deck drawRandomCard];
            if (!card) {
                self = nil;
                break;
            }
            else {
                self.cards[i] = card;
            }
        }
        // Set card match mode here:
        _cardMatchMode = matchMode;
    }

    return self;
}
Run Code Online (Sandbox Code Playgroud)