Как мне увеличить NSTimer для времени в метке? - PullRequest
1 голос
/ 15 февраля 2011

Я начинающий разработчик iPhone, так что будьте спокойны за меня.

Я пытаюсь разработать простое приложение, которое будет показывать время, а затем тикать каждую секунду. Мне кажется, что я что-то упускаю из-за управления памятью, но мои навыки слишком свежи, чтобы действительно понять, чего мне не хватает.

Я создаю ярлык прямо в главном окне (действительно простое приложение) и пытаюсь обновить ярлык до NSTimer. Вот мой кусок кода, он все еще немного грязный.

@synthesize label, theDate;
@synthesize window;

- (void)tick 
{
    theDate = [[NSDateFormatter alloc] init];
    [theDate setDateFormat:@"hh:mm:ss"];
    NSString* currentTime = [theDate stringFromDate:[NSDate date]];
    label.text = [[NSString alloc] initWithFormat:@"%d",currentTime];
    [currentTime release];
}

- (BOOL)application:(UIApplication *)application 
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions     
{
    CGRect rect = CGRectMake(10, 200, 300, 20);
    label = [[UILabel alloc] initWithFrame:rect];
    label.textAlignment = UITextAlignmentCenter;
    [self.window addSubview:label];
    [NSTimer scheduledTimerWithTimeInterval:1.0f 
                                     target:self 
                                   selector:@selector(tick) 
                                   userInfo:nil 
                                    repeats:YES];
    [self.window makeKeyAndVisible];

    return YES;
}

@synthesize 'd ivars @property s в файле .h, и ивы высвобождаются в dealloc.
Спасибо!

Ответы [ 3 ]

1 голос
/ 15 февраля 2011

Вы не должны выпускать currentTime. Вы не получили его через что-то с «new», «alloc», «retain» или «create» в имени, так что вы не являетесь его владельцем. То, что вы делаете, это выделяете несвязанную строку и передаете ее в label.text, а затем не можете ее освободить. Предлагаю заменить эти три строки просто:

NSString* currentTime = [theDate stringFromDate:[NSDate date]];
label.text = currentTime;

Это зависит от UILabel, чтобы сохранить строку, если она хочет сохранить ее (я ожидаю, что так и будет, но это деталь реализации и ни одна из наших задач в любом случае), и вы не являетесь ее владельцем, поэтому можете просто оставить ее истечь в пуле авто-релиза.

В том же методе вы также создаете NSFormatter с именем 'theDate' и не можете его освободить. На самом деле, вы, кажется, немного запутались в методах получения и установки, что неудивительно, поскольку здесь присутствует немного наследия Objective-C. Если вы делаете что-то вроде:

theData = ...whatever...;

Затем вы непосредственно скопируете значение, указанное в переменную, согласно обычному оператору C '='. Там нет магии Objective-C там. Является ли и как вы объявили свою собственность (в значительной степени, см. Примечание) не имеет значения.

Если вам что-то нравится:

self.theData = ...whatever...;

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

[self setTheData:...whatever...];

Таким образом, вы получите вызов метода и ваш фактический установщик будет использован. Сеттер будет делать все, что вы ему сказали, через @ property / @ synthesize (т.е. сохранять, копировать или назначать). Следовательно, в dealloc вы склонны видеть либо:

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

Или:

- (void)dealloc
{
    self.property1 = nil;
    self.property2 = nil;
    [super dealloc];
}

Которые имеют тот же общий эффект со свойствами 'retain' (хотя последний фактически выпускает оригинал, затем сохраняет 'nil', любое сообщение 'nil' не имеет никакого эффекта).

Та же путаница, возможно, влияет на использование вами ярлыка, но то, что вы делаете в данный момент, технически правильно. Если бы вы использовали 'self.label =' вместо прямого присваивания, то вам нужно было бы передать объект с автоматическим выпуском или объект, который вы знаете, как выпустить позже.

Дополнение: стоит проверить NSZombies и инструмент Leaks в Instruments; первая поможет вам узнать, когда и как вы обращаетесь к освобожденным объектам, вторая поможет вам определить, когда у вас происходит утечка памяти. Guard Malloc также полезен для первых, но имеет гораздо большие накладные расходы, и я не уверен, насколько хорошо он работает с iOS в настоящее время.

(примечание: в современных 64-битных средах и средах ARM переменные экземпляра являются динамическими с практическим эффектом, заключающимся в том, что вы можете объявлять их чисто с помощью @property и @synthesize, не помещая их иначе в объявление @interface; если вы если вы сделаете это, то, очевидно, наличие или отсутствие @property повлияет на работу прямого доступа.

1 голос
/ 15 февраля 2011

У вас есть ряд проблем с памятью:

  • Вы выделяете theDate, но не освобождаете его, поэтому он просачивается.
  • Вы выпускаете currentTimeнесмотря на отсутствие ссылки на владельца, вы, скорее всего, увидите сбои в пуле автоматического выпуска.
  • Вы выделяете значение, присвоенное label.text, но не освобождаете его;либо label.text является сохраняющим свойством, и в этом случае вы теряете эту строку, дважды сохраняя ее, либо label.text не сохраняет, в этом случае вы теряете строку, никогда не освобождая ее (за исключением самого последнего, в dealloc)

Я настоятельно рекомендую вам прочитать Руководство по управлению памятью от Apple .

Кроме того, независимо от проблем с памятью, вы используете %d чтобы попытаться показать строку вместо %@, чтобы вы получили числовое значение адреса указателя, а не содержимое строки.

0 голосов
/ 15 февраля 2011
  1. Поместите эту строку (theDate = [[NSDateFormatter alloc] init];) в applicationDidFinishLoading.Так что дата будет выделена один раз.
  2. Замените вашу функцию тиков на эту: -

    • (void) tick {theDate = [[NSDateFormatter alloc] init];[theDate setDateFormat: @ "чч: мм: сс"];NSString * currentTime = [theDate stringFromDate: [NSDate date]];label.text = currentTime;}
...