7

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

-(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;
}

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

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

    _cardMatchMode = matchMode;
    return [self initWithCardCount:cardCount usingDeck:deck];;
}

根据苹果文档,便利初始化程序必须返回指定初始化程序的值,但问题是我可以在便利初始化程序中设置此类的额外属性吗?我可以说self.cardMatchMode = matchMode; 还是 self 还没有完全初始化?
它确实有效,但我只是想了解这是否是正确的代码,并且我可以在方便的 init 中访问 c​​ardMatchMode 属性,否则我将不得不 -(id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode

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

/////更新

我在

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

当我尝试执行self = [self initWithCardCount:(NSUInteger)cardCount usingDeck:(Deck*)deck; 错误时,您无法在 init 系列之外分配 self 。我弄清楚了问题所在。init 方法有小写的 w 并且它必须是大写的,所以现在它可以工作了。这是我现在为我的便利初始化程序提供的代码。

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

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

据我了解,有很多对象都有带有额外参数的便利初始化程序,它只会调用指定的初始化程序。如果你看一下 NSString ,它有不同的初始化器和不同的参数。它可能正在调用指定的初始化程序 init。这个对吗?

4

2 回答 2

17

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

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

于 2013-08-07T20:09:36.397 回答
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;
}
于 2013-08-07T20:11:29.060 回答