Подтвердить что ты не робот

Цель C: Как написать персонализированный пользовательский Init

Очень простой вопрос, но в моем коде есть ошибка, на которую может ответить только одно предположение: мой класс не создается!

Я не много писал в Objective C за какое-то время, и я никогда не был действительно хорош, поэтому, пожалуйста, укажите даже наиболее болезненно очевидное.

Я использую:

ObjectSelectionViewController *length = [[ObjectSelectionViewController alloc] initWithMeasureType:0];
ObjectSelectionViewController *mass = [[ObjectSelectionViewController alloc] initWithMeasureType:1];
ObjectSelectionViewController *volume = [[ObjectSelectionViewController alloc] initWithMeasureType:2];

NSLog(@"%@", [length measurementType]);
NSLog(@"%@", [mass measurementType]);
NSLog(@"%@", [volume measurementType]);

NSLogs возвращаются независимо от того, какое измерение было назначено последним, независимо от отдельных распределений и inits.

Вот конструктор класса ObjectSelectionViewController:

#import "ObjectSelectionViewController.h"

@implementation ObjectSelectionViewController

NSString *measurementType;

-(ObjectSelectionViewController*) initWithMeasureType:(int)value
{
switch (value) {
    case 0: // Length
        measureType = @"Length";
        break;

    case 1: // Mass
        measureType = @"Mass";
        break;

    case 2: // Volume
        measureType = @"Volume";
        break;
}
return self;
}

-(NSString*) measurementType
{
return measureType;
}

Спасибо за помощь, это сводит меня с ума!

4b9b3361

Ответ 1

Вам нужно сделать measureType переменную экземпляра, так что каждый объект этого типа, который вы создаете, имеет свою собственную копию:

@interface ObjectSelectionViewController : NSViewController {
    NSString * measureType;    // Declare an NSString instance variable
}

- (id) initWithMeasureType: (int)value;

@end

Как бы то ни было, существует только одна копия переменной, и каждый раз, когда вы создаете экземпляр нового объекта, его значение изменяется. Поскольку каждый экземпляр ссылается на одну и ту же копию, все они получают одинаковое значение:

ObjectSelectionViewController *length = [[ObjectSelectionViewController alloc] initWithMeasureType:0];
NSLog(@"%@", [length measurementType]);     // Prints "Length"
ObjectSelectionViewController *mass = [[ObjectSelectionViewController alloc] initWithMeasureType:1];
NSLog(@"%@", [length measurementType]);    // Prints "Mass"

Вам также необходимо изменить свой метод init..., как упоминалось другими респондентами:

- (id) initWithMeasureType: (int)value {

    // Call superclass initializer
    self = [super init];
    if( !self ) return nil;

    switch (value) {
        case 0: // Length
            measureType = @"Length";
            break;

        case 1: // Mass
            measureType = @"Mass";
            break;

        case 2: // Volume
            measureType = @"Volume";
            break;
    }

    return self;
}

Поскольку вы назначаете литеральную строку переменной экземпляра, вам не нужно беспокоиться об управлении своей памятью; если вы делаете что-то более сложное, вы, вероятно, добьетесь успеха, объявив property. Еще одно замечание: методы инициализации всегда должны возвращать id, общий указатель объекта, чтобы позволить подклассам работать правильно.

Ответ 2

Сначала нужно вызвать [super init], например:

-(id) initWithMeasureType:(int)value
{
    if ((self = [super init]))
    {
        switch (value) {
            case 0: // Length
                measureType = @"Length";
                break;

            case 1: // Mass
                measureType = @"Mass";
                break;

            case 2: // Volume
                measureType = @"Volume";
                break;
        }
    }
    return self;
}

Ответ 3

Конструкторы - это соглашение в Objective-C, а не функция языка. Так, например, нет автоматического вызова родительских конструкторов (так же, как вы не ожидали бы, что какой-либо другой переопределенный метод вызовет его родительские реализации). Точно так же имена, используемые для конструкторов, являются просто соглашениями, поэтому компилятор ничего не знает о init. Имея это в виду, то, что вы действительно хотите в качестве своего конструктора:

-(id) initWithMeasureType:(int)value
{
    if((self = [super init]))
    {
        switch (value) {
            case 0: // Length
                measureType = @"Length";
                break;

            case 1: // Mass
                measureType = @"Mass";
                break;

            case 2: // Volume
                measureType = @"Volume";
                break;
        }
    }
return self;
}

Предполагая, что measureType - это переменная экземпляра (объявленная как часть интерфейса, вообще говоря), а не глобальная, тогда она должна делать то, что вы хотите.

Ответ 4

В вашем пользовательском методе инициализации вам просто нужно начать с:

self = [super init];

Ответ 5

- (id) initWithMeasureType: (int)value {

// Call superclass initializer
self = [super init];
if( !self ) return nil;

switch (value) {
    case 0: // Length
        measureType = @"Length";
        break;

    case 1: // Mass
        measureType = @"Mass";
        break;

    case 2: // Volume
        measureType = @"Volume";
        break;
}

return self;

}