Как реализовать пользовательское прерывание NSApplication: поведение в Какао? - PullRequest
3 голосов
/ 04 августа 2010

Я пытаюсь реализовать пользовательское поведение завершения в приложении Какао. Обычно, когда мое приложение завершается корректно, оно выполняет окончательную очистку базы данных во время выполнения и затем завершает работу. Это происходит внутри AppDelegate (делегат NSApplication) всякий раз, когда вызывается [NSApp terminate:aSender]:

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
    // database cleanup...
    return NSTerminateNow;
}

Если во время выполнения возникает ошибка (например, файл базы данных был удален), я сообщаю об ошибке пользователю и даю ему возможность восстановить (вернуть файл и повторить попытку) или выйти. Если выбрано Quit, я хочу выйти из приложения, пропуская очистку базы данных все вместе, так как это больше невозможно. По сути, я бы хотел что-то вроде этого:

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
    BOOL gracefulTermination = ...;

    if (gracefulTermination == YES)
    {
        // Database cleanup....
    }

    return NSTerminateNow;
}

Проблема, конечно же, заключается в получении значения для gracefulTermination .

Есть ли способ передать пользовательскую переменную в NSApp при вызове terminate:, например, infoDict, и затем получить ее внутри applicationShouldTerminate:?

Если нет, есть ли лучший способ выполнить пользовательское поведение завершения?


Насколько я знаю, когда terminate: вызывается каким-то другим объектом, это происходит:

  1. [NSApp terminate:self]; вызывается foo (a.k.a. self ).
  2. NSApp отправляет своего делегата: [aDelegate applicationShouldTerminate:self]; ( self - это NSApp, а не foo ).
  3. aDelegate получает сообщение и выполняет applicationShouldTerminate:, если реализовано.

foo , кажется, куда-то исчезает, и к тому времени, когда aDelegate получает сообщение, оно исчезает навсегда, и только NSApp появляется в качестве отправителя. Это не позволяет мне передавать infoDict внутри foo или просто простой infoDict, aDelegate, содержащий пользовательское поведение terminate:.


Я знаю, что можно выйти без использования [NSApp terminate:...] с чем-то вроде exit(). Хотя из того, что я читал, это не одобряется, потому что это не кошерно для Какао. Кроме того, это также предотвратит любые другие операции очистки внутри applicationShouldTerminate:, операции, которые не должны быть пропущены даже при небрежном выходе.

1 Ответ

3 голосов
/ 04 августа 2010

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

Предполагая, что ваш представитель приложения не может получить доступ к этой информации каким-либо другим способом (скажем, завершение, вызванное объектом, влияет на то, может ли оно произойти), это кажется самым простым решением: подкласс NSApplication, присвойте ему terminationInfo свойство и переопределение terminate:, чтобы установить это свойство и вызвать super.

...