Objective c 如何在Objective C中初始化NSMutableArray?

Objective c 如何在Objective C中初始化NSMutableArray?,objective-c,nsmutablearray,Objective C,Nsmutablearray,我来自Java背景,正在学习Objective C。我正在尝试创建一个具有字符串数组和成员函数的类来修改数组。我的代码如下所示: @implementation TAWChapter @synthesize mSubject; @synthesize mItems; - (id) init{ self.mItems = [[NSMutableArray alloc] init]; return self; } - (void) setSubject:(NSString

我来自Java背景,正在学习Objective C。我正在尝试创建一个具有字符串数组和成员函数的类来修改数组。我的代码如下所示:

@implementation TAWChapter

@synthesize mSubject;

@synthesize mItems;

- (id) init{
    self.mItems = [[NSMutableArray alloc] init];
    return self; 
}

- (void) setSubject:(NSString *)subject{
    self.mSubject = subject; 
}

- (void) addItem:(NSString *)item{
    [self.mItems addObject:@"asdf"]; 
}

@end
- init
{
    self = [super init];
    if (!self) return nil;

    // set up other stuff here 

    return self;
}
这没用。我收到一个
“[\uu NSArrayI addObject:]:发送到实例的无法识别的选择器”
和一个
“NSInvalidArgumentException”
。在互联网上搜索后,我将构造函数中的单行更改为:

self.mItems = [self.mItems init];

成功了,但为什么?从Java开发人员的角度来看,第一个比第二个更有意义。我还有另一行,它和第一行一样,但它在工作(不是在构造函数中)。有人能给我解释一下吗?

您应该调用
super
并在
init
方法中将其结果分配给
self

- (id)init
{
    self = [super init];
    if (self) {
        self.mItems = [[NSMutableArray alloc] init];
    }
    return self;
}

由于objective-c是c的超集,它基本上是c,带有一些“OO”语法。在创建(或使用)对象之前,必须在堆中为其分配空间。您可以使用
[Class alloc]
执行此操作。下一步是初始化该空间。alloc返回指向堆中该空间的指针,您可以使用init;)初始化该空间

所以你调用
Class*myObjc=[[Class alloc]init]

如果您使用继承(这是因为您从NSOBject继承),那么必须确保您的超类正确初始化了所有内容,这就是对super的调用。要确保没有出现运行时错误,请检查self!=nil,使用if(self)隐式执行此操作

使用此代码:

@implementation TAWChapter

@synthesize mSubject, mItems;

- (id)init
{
    self = [super init];
    if (self) {
        mItems = [[NSMutableArray alloc] init];
    }
    return self;
}

- (void) setSubject:(NSString *)subject{
    mSubject = subject; 
}

- (void) addItem:(NSString *)item{
    [mItems addObject:item]; 
}

@end
  • 首先,您应该遵守Objective-C编码约定。在Objective-C中,类没有构造函数,它们有初始化器。在Objective-C中,初始化器调用超类的初始化器,因此它应该如下所示:

    @implementation TAWChapter
    
    @synthesize mSubject;
    
    @synthesize mItems;
    
    - (id) init{
        self.mItems = [[NSMutableArray alloc] init];
        return self; 
    }
    
    - (void) setSubject:(NSString *)subject{
        self.mSubject = subject; 
    }
    
    - (void) addItem:(NSString *)item{
        [self.mItems addObject:@"asdf"]; 
    }
    
    @end
    
    - init
    {
        self = [super init];
        if (!self) return nil;
    
        // set up other stuff here 
    
        return self;
    }
    
  • 其次,除非您使用的是ARC,否则可能会出现内存泄漏。初始值设定项的第一行将您拥有的对象指定给也可能拥有所有权的属性。您应该使用以下任一选项:

    // property takes care of ownership
    self.mItems = [NSMutableArray array];
    
    或:

    苹果有时不鼓励在初始化器中使用访问器方法,因为它可以处理诸如KVO之类的事情,但一致使用访问器方法可以确保适当的对象所有权和内存管理

  • 将初始化器中的行更改为:

    self.mItems = [self.mItems init];
    
    什么都不做。当调用initialiser方法时(通常是在分配之后),所有实例变量都会自动设置为nil。因此,您所做的只是:

    self.mItems = [nil init];
    
    这只是:

    self.mItems = nil;
    
    而且,在没有首先分配实例的情况下,不要使用
    init
    ,也不要多次使用
    init

  • 如果不让超类自己初始化,那么它可能会在其他方面表现为问题。进行构建和分析,并确保已解决分析人员指出的任何问题


  • 另一种方法是从NSArray创建NSMutableArray:

    NSMutableArray *myMutableArray = [NSMutableArray arrayWithArray:myArray];
    

    答案可能已经解决了这个问题,但在看到
    mItems
    属性的声明之前,我们无法确定。