2012-05-06 66 views
10

我来自Java背景,我正在学习Objective C.我正在尝试创建一个具有字符串数组和成员函数来修改数组的类。我的代码看起来像这样:如何在Objective C中初始化NSMutableArray?

@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 

哪没有工作。我得到了"[__NSArrayI addObject:]: unrecognized selector sent to instance ""NSInvalidArgumentException"。在互联网上搜索后,我将构造函数中的单行更改为:

self.mItems = [self.mItems init]; 

它工作正常,但是为什么?从Java开发人员的角度来看,第一个比第二个更有意义。而且我有另外一行,它与第一行相同,但它正在工作(不在构造函数中)。有人可以向我解释这个吗?

+1

这些问题的答案可能已经解决的问题,但直到我们看到了'mItems'属性的声明,我们不能肯定。 –

回答

27
  1. 第一总之,您应该遵守Objective-C编码惯例。在Objective-C中,类没有构造函数,它们有初始化器。在Objective-C,initialisers调用父类的初始化器,所以它应该是这样的:

    - init 
    { 
        self = [super init]; 
        if (!self) return nil; 
    
        // set up other stuff here 
    
        return self; 
    } 
    
  2. 其次,除非你正在使用ARC,你可能有一个内存泄漏。您的初始者的第一行将您拥有的对象分配给也可能拥有所有权的属性。您应该使用:

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

    或:

    // assign to instance variable directly with owned object 
    mItems = [[NSMutableArray alloc] init]; 
    

    苹果有时劝阻initialisers使用的存取方法,因为它可以用之类的东西志愿不甘示弱,但一贯使用的访问方法,确保正确的对象所有权和内存管理。

  3. 通过改变你的线在你的初始化器到:

    self.mItems = [self.mItems init]; 
    

    什么。当你调用初始化方法时(通常在分配它之后),所有实例变量都会自动设置为nil。所以,你在做什么就是:

    self.mItems = [nil init]; 
    

    这仅仅是:

    self.mItems = nil; 
    

    ,并没有使用init没有首先分配一个实例,并且从来不使用超过一次init更多。

  4. 如果您不让超类初始化自身,那么它可能会在其他方面出现问题。做一个构建&分析并确保你已经解决了分析仪指出的任何问题。

+0

非常好的回答:) – MJB

+0

非常感谢:-) – YannickSteph

2

你应该叫super及其结果在您的init方法分配给self

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

由于Objective-C的是C的超集,它基本上c。与一些“OO”语法糖。在创建(或使用!)对象之前,您必须在堆中为它分配空间。你用[Class alloc]这样做。下一步是该空间的初始化。 alloc返回一个指向堆中的空间的指针,它用init初始化;)

因此您可以拨打Class *myObjc = [[Class alloc] init];

如果你使用继承(你自从你从NSOBject继承后做的),你必须确保你的父类正确地初始化了所有东西,这就是对super的调用。为了确保你没有得到一个运行时错误,检查自=零,这与你如果(个体经营)

self.mItems = [self.mItems init]; // doesn't do anything, since you call the getter for mItems with self.mItems and try to init. then you try to set mItmes to itself. 

使用此代码做隐:

@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 
0

的另一种方式可以从NSArray中被创建的NSMutableArray:

NSMutableArray *myMutableArray = [NSMutableArray arrayWithArray:myArray];