目标C:如何编写实例化自定义Init

Der*_*rek 12 objective-c ios

非常基本的问题,但我的代码中有一个错误,只能通过一个假设来回答:我的类没有被实例化!

在一段时间内,我没有在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]);
Run Code Online (Sandbox Code Playgroud)

无论单独的分配和内部,NSLog都会返回最后分配的测量值.

这是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;
}
Run Code Online (Sandbox Code Playgroud)

谢谢你的帮助,这让我发疯了!

Jos*_*ell 28

您需要创建measureType一个实例变量,以便您创建的此类型的每个对象都有自己的副本:

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

- (id) initWithMeasureType: (int)value;

@end
Run Code Online (Sandbox Code Playgroud)

实际上,只有一个变量副本,每次实例化一个新对象时,其值都会发生变化.由于每个实例都引用相同的副本,因此它们都具有相同的值:

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

您还需要更改init...其他回答者提到的方法:

- (id) initWithMeasureType: (int)value {

    // Call superclass's 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;
}
Run Code Online (Sandbox Code Playgroud)

由于您要为实例变量分配文字字符串,因此您无需担心管理其内存; 如果你做了更复杂的事情,你可能会通过声明一个属性来做得很好.另请注意:初始化方法应始终返回id一个通用对象指针,以允许子类正常工作.


Hol*_*nce 8

你需要先打电话[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;
}
Run Code Online (Sandbox Code Playgroud)


Tom*_*mmy 6

构造函数是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;
}
Run Code Online (Sandbox Code Playgroud)

假设measureType是一个实例变量(一般来说是声明为接口的一部分),而不是全局,那么应该做你想要的.

  • 初始化器应始终返回`id`以便正确处理子类化. (2认同)