Задача C NSString Проблема - PullRequest
       25

Задача C NSString Проблема

0 голосов
/ 20 декабря 2010

У меня есть следующий код в моей программе. я пытаюсь добавить каждую цифру, нажатую на строку NSString. я получаю сообщение об ошибке после добавления строки во второй раз. ошибка сообщение отправлено на освобожденный объект. я знаю, что это проблема управления памятью. я не выпустил промежуточный итог. Кто-нибудь знает, почему промежуточный итог освобождается? Заранее спасибо.

-(IBAction)digitPressed:(UIButton *)sender
{
       NSString *digit = [[sender titleLabel] text];
       subtotal=[subtotal stringByAppendingString:digit];
       NSLog(@"appended string is :%@",subtotal);
}

-(void)ViewDidLoad
{
  subtotal = [[NSString alloc]init];

}

Ответы [ 4 ]

5 голосов
/ 20 декабря 2010

Ваш viewDidLoad должен начинаться со строчной буквы v. Вы также должны объявить свойство retain для вашей строки subtotal, а затем использовать сеттеры для его присвоения, чтобы у вашего контроллера представления был свой собственный указатель на строку, и он не будет случайно освобожден при переходе в пул автоматического выпуска .

В вашем заголовочном файле:

@property (nonatomic, retain) NSString *subtotal;

В вашем файле реализации:

-(IBAction)digitPressed:(UIButton *)sender
{
    NSString *digit = [[sender titleLabel] text];
    self.subtotal = [subtotal stringByAppendingString:digit];
    NSLog(@"appended string is :%@",subtotal);
}

-(void)viewDidLoad
{
    self.subtotal = @"";
}

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

Но если у вас есть строка, которая постоянно изменяется, было бы лучше использовать NSMutableString, поскольку Джейкоб Релкин упоминает . Он предназначен для изменения, поэтому вы не будете создавать и уничтожать неизменяемые NSString объекты.

4 голосов
/ 20 декабря 2010

Две вещи:

1 - Ваш viewDidLoad метод неверен, имя - viewDidLoad, и вам нужно вызвать реализацию суперкласса, вызвав [super viewDidLoad]

2 - Эта строка неверна:

subtotal = [NSString alloc]init];

Вы пропустили ведущий [ символ:

subtotal = [[NSString alloc]init];

Суть stringByAppendingString: заключается в том, что возвращаемый NSString является автоматически выпущенным , поэтому вы должны либо retain возвращенное NSString , либо сделать вашу переменную экземпляра NSMutableString и звоните appendString:

@interface YourViewController : UIViewController {
   //...
   NSMutableString *subtotal;
}
@property (nonatomic, retain) NSMutableString *subtotal;
@end

@implementation YourViewController 

@synthesize subtotal;

- (void) dealloc {
  [subtotal release];
  //...
  [super dealloc];
}

- (void) viewDidLoad {
   [super viewDidLoad];
   subtotal = [[NSMutableString alloc] init];
}
-(IBAction)digitPressed:(UIButton *)sender {
   NSString *digit = [[sender titleLabel] text];
   [subtotal appendString: digit];         
   NSLog(@"appended string is :%@",subtotal);
}

//...

@end
2 голосов
/ 20 декабря 2010

Вы правы, что вы не release subtotal, но вы тоже никогда не retain.У вас есть пара проблем с управлением памятью.Во-первых, вы должны освободить старое значение subtotal, прежде чем присваивать ему новое значение, а во-вторых, вы должны retain это новое значение.Пример с минимальными изменениями того, что у вас есть сейчас:

-(IBAction)digitPressed:(UIButton *)sender
{
   NSString *digit = [[sender titleLabel] text];
   [subtotal autorelease];
   subtotal = [[subtotal stringByAppendingString:digit] retain];
   NSLog(@"appended string is :%@",subtotal);
}
0 голосов
/ 20 декабря 2010

Вам нужно прочитать Какао Правила управления памятью .Эта строка:

   subtotal = [subtotal stringByAppendingString:digit];

Имеет две вещи, которые имеют отношение к правилам управления памятью.

  1. Это дает вам строку, которая вам не принадлежит , так как метод не начинается с new или alloc или содержит copy.Это означает, что в будущем он исчезнет без вашего ведома.Если вы хотите прекратить это, вы заявляете о своем праве собственности, сохраняя его.

  2. Он перезаписывает ссылку на предыдущее значение промежуточного итога.Если вы владели этим объектом, теперь он просочился.Вы должны сначала выпустить его.

Чтобы исправить код:

Сначала удалите

subtotal = [[NSString alloc]init];

из viewDidLoad.Это бессмысленно, так как просто устанавливает промежуточный итог для пустой строки.Используйте это вместо этого:

subtotal = @"";

Постоянные строковые литералы никогда не исчезают, так как, хотя технически вы должны сохранить его, вы можете забыть, что без каких-либо плохих последствий.необходимо освободить старое значение строки, потому что вы собираетесь заменить его.Есть два способа сделать это.Либо сохраните его во временную переменную и отпустите после добавления, либо выполните автоматическое восстановление перед добавлением.Также вам нужно сохранить новое значение.например,

NSString* temp = [subtotal];
subtotal = [subtotal stringByAppendingString: digit];
[subtotal retain];
[temp release];

или

[subtotal autorelease];
subtotal = [subtotal stringByAppendingString: digit];
[subtotal retain];

Вы также должны убедиться, что промежуточный итог выпущен в dealloc

Сказав все это, гораздо лучше использоватьсвойства, чтобы сделать как можно больше управления памятью.Объявите свойство в @interface таким образом:

@property (copy) NSString* subtotal; // string properties should normally be copy

В реализации вам необходимо его синтезировать.Тогда viewDidLoad содержит

[self setSubtotal: @""];

, а ваше действие содержит

[self setSubtotal: [[self subtotal] stringByAppendingString: digit]];

Вам все еще нужно release в dealloc.

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