我来自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
哪个不起作用。我得到了"[__NSArrayI addObject:]: unrecognized selector sent to instance "
和"NSInvalidArgumentException"
。在互联网上搜索后,我将构造函数中的单行更改为:
self.mItems = [self.mItems init];
它有效,但为什么?从Java开发人员的角度来看,第一个比第二个更有意义。我有另一条线,它与第一条线相同,但它正在工作(不在构造函数中)。有人可以向我解释一下吗?
答案 0 :(得分:28)
首先,您应该遵守Objective-C编码约定。在Objective-C中,类没有构造函数,它们具有初始化程序。在Objective-C中,初始化程序调用超类的初始化程序,因此它应如下所示:
- 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];
或:
// assign to instance variable directly with owned object
mItems = [[NSMutableArray alloc] init];
Apple有时不鼓励在初始化程序中使用访问器方法,因为它可以摆弄KVO之类的东西,但是一致使用访问器方法可以确保正确的对象所有权和内存管理。 将初始化代码中的行更改为:
self.mItems = [self.mItems init];
没有。调用初始化方法时(通常在分配之后),所有实例变量都自动设置为nil。所以你所做的只是:
self.mItems = [nil init];
只是:
self.mItems = nil;
并且,如果没有先分配实例,请不要使用init
,也不要多次使用init
。
如果你不让超类初始化,那么它可能在其他方面表现为问题。做一个构建&分析并确保您已解决分析仪指出的任何问题。
答案 1 :(得分:6)
由于objective-c是c的超集,它基本上是带有一些“OO”语法糖的c。在创建(或使用!)对象之前,必须在堆中为它分配空间。你用[Class alloc]
做到这一点。下一步是初始化该空间。 alloc返回一个指向堆中该空间的指针,您可以使用init初始化它;)
所以你打电话给Class *myObjc = [[Class alloc] init];
。
如果你使用继承(自从你继承自NSOBject以来你继续使用),你必须确保你的超类正确地初始化了所有内容,即调用super。为确保没有出现运行时错误,请检查self!= nil,使用if(self)隐式执行
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
答案 2 :(得分:3)
您应致电super
并将结果分配到self
方法中的init
:
- (id)init
{
self = [super init];
if (self) {
self.mItems = [[NSMutableArray alloc] init];
}
return self;
}
答案 3 :(得分:0)
另一种方法是从NSArray创建NSMutableArray:
NSMutableArray *myMutableArray = [NSMutableArray arrayWithArray:myArray];