Распределение переменных экземпляра? - PullRequest
3 голосов
/ 09 сентября 2009

Может кто-нибудь сказать мне, если переменная экземпляра NSString "planetName" должна быть выделена / освобождена мной (как в примере ниже) или это сделано, когда экземпляр класса создается / выделяется?

Насколько я понимаю, int и float не обязательно должны быть, но я не уверен насчет NSString и NSArray ...

@interface PlanetClass : NSObject {
        NSString *planetName;
}
- (NSString *)planetName;
- (void)setPlanetName:(NSString *)value;
@end

Вот так ...

- (id) init {
        [super init];
        planetName = [[NSString alloc] init];
return self;
}

- (void) dealloc {
        [planetName release];
        [super dealloc];
}

** ---------------------------------- ** РЕДАКТИРОВАТЬ: РЕДАКТИРОВАТЬ: Вот еще одна версия ** ---------------------------------- **

int main(int argc, const char *argv[]) {

        // ** Allocated here
        PlanetClass *newPlanet_01 = [[PlanetClass alloc] init];
        NSString *newPlanetName = [NSString alloc] init];

        // ** Set the instance variable pointer here
        newPlanetName = @"Jupiter";
        [newPlanet_01 setPlanetName:newPlanetName];

        // ** Released here
        [newPlanet_01 release];
        return 0;
}

Тогда бы методы init и dealloc были бы такими ...

- (id) init {
        [super init];
        return self;
}

- (void) dealloc {
        // Always release the current copy of planetName 
        // pointed to by the class instance.
        [planetName release]
        [super dealloc];
}

Метод setPlanetName будет выглядеть следующим образом ...

- (void)setPlanetName:(NSString *)newPlanetName {
        if (planetName != newPlanetName) {
               [planetName release];
               planetName = [newPlanetName copy];
        }
}

PS: я не использую свойства или синтезирую, я еще не дошел до этого.

ура -gary-

Ответы [ 4 ]

3 голосов
/ 09 сентября 2009

Ваш код действителен, но, вероятно, нет причин инициализировать planetName пустой строкой. Одной из приятных особенностей Objective-C является то, что вы можете отправлять сообщения нулевому объекту без последствий. Если ваш класс инициализирован и вы никогда не вызываете -setPlanetName:, planetName будет иметь значение nil (переменные экземпляра всегда инициализируются как nil), поэтому, когда ваш -dealloc метод вызывает [planetName release], ничего не произойдет.

Обычно рекомендуется использовать -copy при установке переменной экземпляра NSString и -retain при установке большинства других объектов в качестве переменных экземпляра. Таким образом, ваш -setPlanetName: метод будет выглядеть примерно так:

- (void)setPlanetName:(NSString *)newPlanetName {
  NSString *tempPlanetName = [newPlanetName copy];
  [planetName release];
  planetName = tempPlanetName;
}
1 голос
/ 10 сентября 2009

У вас все еще есть проблема с вашим новым кодом.

В своей основной функции вы отпускаете newPlanetName, но это немного неправильно. Ваш PlanetClass сохранил его с помощью setPlanetName: метода, но ваш PlanetClass никогда не выпустит его снова, пока не изменится название планеты. Не должно быть, чтобы вызывающий setPlanetName: держал строку, ваши классы обязаны правильно с ней справиться.

Ваш старый dealloc метод верен. Оно должно выпустить имя планеты, потому что оно вам больше не нужно. Ваш основной метод не должен выпускать имя планеты, потому что строка, возвращаемая stringWithString:, не принадлежит вам, а вы отдаете ее PlanetClass, чтобы позаботиться.

Итак, оставьте свой старый dealloc метод и удалите [newPlanetName release] из основной функции, и с вами все будет в порядке.

В качестве ярлыка вы можете даже вызвать [newPlanet_01 setPlanetName:@"Jupiter"] и вообще покончить с переменной newPlanetName в вашей основной функции.

1 голос
/ 09 сентября 2009

planetName - это указатель , который, подобно int или float , не требует выделения или инициализации.

Точно так же, как вы можете назначать значения для типа int или float, вы можете указывать planetName на разные экземпляры строки или на ничто.

Когда вы начнете свой класс, planetName будет равен нулю (не указывая ни на что). Если вы указываете planetName на экземпляр строки, вы должны сохранить эту строку и освободить в dealloc.

Другими словами, это:

planetName = [[NSString alloc] init];

ненужно и бессмысленно.

В вашем методе setPlanetName вам необходимо освободить существующую строку, на которую указывает planetName, назначить planetName новой строке, а затем сохранить новая строка.

Ваш dealloc метод правильный.

0 голосов
/ 09 сентября 2009

Ваш код выглядит хорошо. Подклассы NSObject (включая NSString) должны иметь память, управляемую объектом, которому они принадлежат. В этом случае владельцем является PlanetClass.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...