Как инициализировать NSMutableArray в Objective C?
Я исхожу из фона 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 первый имеет больше смысла, чем второй. И у меня есть другая строка, такая же, как и первая, но она работает (не в конструкторе). Может кто-нибудь объяснить это мне, пожалуйста?
Ответы
Ответ 1
-
Прежде всего, вы должны придерживаться условных обозначений 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];
делает ничего. Когда вы вызываете свой метод инициализации (как правило, сразу после его выделения), все переменные экземпляра автоматически устанавливаются на нуль. Итак, что вы делаете, просто:
self.mItems = [nil init];
который справедлив:
self.mItems = nil;
и не используйте init
без предварительного выделения экземпляра и никогда не используйте init
более одного раза.
-
Если вы не позволяете инициализировать суперкласс, он может проявляться как проблемы в других областях. Сделайте Сборка и анализ и убедитесь, что вы устранили все проблемы, на которые указывает анализатор.
Ответ 2
Так как objective-c является надмножеством c, в основном c с некоторым синтаксическим сахаром "OO". Прежде чем вы сможете создать (или использовать!) Объект, вы должны выделить место для него в куче. вы делаете это с помощью [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
Ответ 3
Вы должны вызвать super
и назначить его результат self
в вашем методе init
:
- (id)init
{
self = [super init];
if (self) {
self.mItems = [[NSMutableArray alloc] init];
}
return self;
}
Ответ 4
Другим способом может быть создание NSMutableArray из NSArray:
NSMutableArray *myMutableArray = [NSMutableArray arrayWithArray:myArray];