Вопрос о том, когда и где выпустить объект - PullRequest
1 голос
/ 07 июля 2010

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


AlertUtility.h:
@interface AlertUtility : NSObject {
}
- (void) displayAlert;
@end

AlertUtility.m:
@implementation AlertUtility {
- (void) displayAlert {
   UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:... message:... 
      delegate:self cancelButtonTitle:... otherButtonTitles:nil] autorelease];
   [alert show];
}

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
   // Create another view controller and display its views
   [self release] // Release current object because I'm not releasing it where I create it
}

}

Где мне нужно использовать это оповещение (т.е. в MyViewController), у меня есть следующее:

<code>
MyViewController.m:
AlertUtility *utility = [[AlertUtility alloc] init];
[utility displayAlert];

Как вы можете видеть, я не выпускаю здесь служебный объект (что мне следует, так как он у меня есть), а скорее в методе didDismissWithButtonIndex класса AlertUtility.Я явно что-то здесь упускаю.

Я попытался автоматически выпустить служебный объект, но к тому времени, когда метод didDismissWithButtonIndex «вызывается» для служебного объекта, этот объект уже был освобожден (из-за автоматического выпуска).

Я пытался сделать метод displayAlert статическим (и вызывал его с помощью [AlertUtility displayAlert];), но затем didDismissWithButtonIndex никогда не вызывался.

Должен ли я просто освободить текущий объект из didDismissWithButtonIndexметод, как я делаю сейчас, или есть способ освободить его в MyViewController вместо этого (без создания свойства AlertUtility для текущего класса)?

Спасибо!

РЕДАКТИРОВАТЬ Должен ли я использовать шаблон Singleton вместо этого, может быть?

Ответы [ 3 ]

1 голос
/ 07 июля 2010

Вызов [self release] - это большое нет-нет, потому что ни у одного объекта нет информации о том, что другой объект ссылается на него.Система хранения предназначена для обеспечения того, чтобы, если ObjA нуждался в ObjB, этот ObjB оставался в памяти, пока ObjA больше не нуждается в нем.Если ObjB освобождает себя, вся система выходит из строя.

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

Итак, все в порядке:

AlertUtility *utility = [[AlertUtility alloc] init];
[utility displayAlert];
[utility release];   // released here, but still alive

Это не проблема, если объект AlertUtility еще жив после выпуска.Релиз не обязательно убивает объект.Это просто говорит о том, что объект, отправляющий сообщение об освобождении, больше не нуждается в освобожденном объекте.Каждый сохраняющий объект просто обязан сбалансировать все удержания (включая неявные, такие как init) с выпуском.В прошлом, что удерживающий объект не имеет никакого интереса и не несет ответственности за то, поддерживает ли система освобожденный объект живым или нет.

В конце концов, любой отдельный объект может быть сохранен несколькими сохраняющимися объектами, каждый из которых не знает другого.В этом случае AlertUtility сохраняется один раз ViewController с init. Затем он снова сохраняется UIAlert в качестве делегата. ( Редактировать: UIAlert назначает ему делегата ) Когда ViewController выпускает AlertUtilityобъект, он останется живым до тех пор, пока это нужно UIAlert, и наоборот.

Поскольку объект UIAlert сохраняется при отображении UIWindow, это означает, что объект AlertUtility будет оставаться живым до тех пор, пока не будет отклонен UIAlert. (Изменить: это действительно только для представления, но не для делегата AlertUtility)

Обычно у вас не будет делегата UIAlert, существование которого зависит исключительно от существования самого UIAlert. Обычно делегат UIAlert является контроллером представления, который вызывает предупреждение.Таким образом, вам не нужно беспокоиться о смерти делегата до того, как он завершит задачу, связанную с предупреждением.

0 голосов
/ 07 июля 2010

Вы можете использовать это вместо:

void displayAlert(NSString *title, NSString *message)
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
        message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
    [alert release];
}

Или просто:

#define MY_ALERT(TITLE, MESSAGE) \
[[[[UIAlertView alloc] initWithTitle:TITLE \
                             message:MESSAGE \
                            delegate:nil \
                   cancelButtonTitle:@"OK" \
                   otherButtonTitles:nil] autorelease] show]

А потом напиши:

MY_ALERT(nil, @"Press, OK!");
0 голосов
/ 07 июля 2010

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

// AlertUtility.h:
@interface AlertUtility : NSObject {
}
- (void) displayAlert;
@end

// AlertUtility.m:
@implementation AlertUtility {
- (void) displayAlert {
   UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:... message:... 
      delegate:self cancelButtonTitle:... otherButtonTitles:nil] autorelease];
   [alert show];
   [self retain];   // explicitly retain this (self) object
}

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
   // Create another view controller and display its views
   [self release] // Release current object because you retained it earlier here
}

}

и более поздние версии:

 // MyViewController.m:
    AlertUtility *utility = [[AlertUtility alloc] init];
    [utility displayAlert];
    [utility release];   // released here, but still alive

Редактировать: удаление выпуска по предупреждению, поскольку оно было автоматически выпущено.

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