Ios objective-c中的指定初始值设定项和方便初始值设定项,以及如何正确创建它们并将它们连接在一起

Ios objective-c中的指定初始值设定项和方便初始值设定项,以及如何正确创建它们并将它们连接在一起,ios,objective-c,initialization,Ios,Objective C,Initialization,我试图了解哪个应该被指定为初始值设定项,哪个是方便的初始值设定项。我读过关于这个话题的苹果文档,但我仍然不确定。指定的初始值设定项是否必须具有类所需的所有值?例如 这是我创建的第一个指定初始值设定项 -(id)initWithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck { self = [super init]; if (self) { for(int i = 0; i<=cardCount;

我试图了解哪个应该被指定为初始值设定项,哪个是方便的初始值设定项。我读过关于这个话题的苹果文档,但我仍然不确定。指定的初始值设定项是否必须具有类所需的所有值?例如
这是我创建的第一个指定初始值设定项

-(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;
}
基于apple文档,便利初始值设定项必须返回指定初始值设定项的值,但问题是我可以在便利初始值设定项中设置此类的额外属性吗?我可以说
self.cardmachmode=matchMode或自身仍未完全初始化?
它确实可以工作,但我只是想了解这是否是正确的代码,我可以在便利init中访问cardMatchMode属性,或者我必须
-(id)initwithCardCount:(nsInteger)cardCount使用Deck:(Deck*)Deck cardMatchMode:(nsInteger)matchMode

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

/////更新

我在报告中遇到了一个错误

-(id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode
当我尝试使用Deck:(Deck*)Deck执行
self=[self initWithCardCount:(NSUInteger)cardCount;
错误表示无法在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;
}
现在这更有意义了。我调用了指定的init,它调用super,然后设置
cardMatchMode
变量


据我所知,很多对象都有带有额外参数的方便初始值设定项,它只会调用指定的init。如果你看NSString,它有不同参数的不同初始值设定项。它可能会调用指定初始值设定项的init。这对吗?

指定的初始值设定项er是调用其类的超类的指定初始值设定项的一个,因此它是唯一调用对象
super
上的方法的初始值设定项。类中的任何其他初始值设定项都不应该这样做;这些次初始值设定项应该使用
self
调用指定的初始值设定项。通常是指定的初始值设定项具有创建类的有用对象所需的所有参数


简而言之,指定的初始值设定项是唯一在
super
上调用初始值设定项的初始值设定项,类中的所有其他初始值设定项都调用指定的初始值设定项(使用
self
)。

根据苹果文档,指定的初始值设定项

通常是init…方法,它具有最多的参数,并执行大部分初始化工作

因此,在您的情况下,这将是
-(id)initwithCardCount:(nsInteger)cardCount usingDeck:(Deck*)Deck cardMatchMode:(nsInteger)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;
}
/**
简易初始化器
*/
-(id)init
{
self=[self initwithCardCount:kDefaultCardCount usingDeck:[Deck defaultDeck]cardMatchMode:kCardMatchModeDefault];
回归自我;
}
-(id)initWithCardCount:(nsInteger)使用Deck:(Deck*)Deck的cardCount
{
self=[self initwithCardCount:cardCount usingDeck:deck cardMatchMode:kCardMatchModeDefault];
如果(自我){
}
回归自我;
}
/**
指定初始值设定项
*/
-(id)initwithCardCount:(NSInteger)cardCount使用Deck:(Deck*)Deck cardMatchMode:(NSInteger)matchMode
{
self=[super init];
如果(自我){

对于(int i=0;感谢您的回复。我更新了,现在更有意义了。据我所知,只要只有指定的初始值设定项调用super,辅助值只调用应该工作的指定初始值。将通过先调用指定值,然后在辅助值中设置其余值来初始化该类的所有属性。谢谢对于回复。请查看我的更新答案。在这种情况下,我实际上不希望人们调用init,因为我想确保他们在初始化此类时传递参数。不会有默认参数。从长远来看,我想指定的和便利init有多少个参数并不重要,只要指定将调用super,便利将调用Specified。您听说过构造函数重载吗?指定的初始值设定项有点像Java中的实际构造函数,它接受大部分参数。然后,
便利初始值设定项
将调用
指定的初始值设定项
来完成这项工作,即调用
super init
/**
 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;
}