Как остановить функцию во время ее работы

Я кодирую приложение для Mac на Xcode с помощью Applescript.
Я создал функцию, которая не останавливается навсегда, но я не могу ее остановить.
Она запускается, когда я нажимаю кнопку, расположенную в окне. < br> Поскольку эта функция не останавливается, кнопка кажется нажатой бесконечно.
И мне нужно принудительно выйти с помощью «Command + Option + Escape». (Даже если вы выполните это действие, это приложение не может быть остановлено.)
Я хочу отпустить кнопку до запуска функции, и я хочу безопасно остановить эту функцию, нажав другую кнопку.
Это мой пример. Чтобы остановить это, нажмите кнопку «Стоп» в Xcode.

property parent : class "NSObject"
property mylabel : missing value

on applicationWillFinishLaunching_(aNotification)
    -- Insert code here to initialize your application before any files are opened
end applicationWillFinishLaunching_

on myStartButtonHandler_(sender)
    my myForeverFunction()
end myStartButtonHandler_

on myStopButtonHandler_(sender)
    --How can I stop "myForeverFunction"?
end myStopButtonHandler_

on myForeverFunction()
    set a to 0
    repeat 100 times
        set a to a+1
        mylabel's setStringValue_(a)
        delay 1
    end repeat
end myForeverFunction

on applicationShouldTerminate_(sender)
    -- Insert code here to do any housekeeping before your application quits 
return current application's NSTerminateNow
end applicationShouldTerminate_

Это файл проекта -> https://dl.dropboxusercontent.com/u/97497395/test.zip
Извините, я японец, я не очень хорошо пишу по-английски.


person subdiox    schedule 09.08.2013    source источник


Ответы (2)


В основном интерфейс вашего приложения контролируется и обновляется в основном потоке ваших приложений. Поэтому, если вы запустите какой-то код, который связывает основной поток, ваш интерфейс не сможет обновиться, пока код не будет завершен. Чтобы исправить это, вы запускаете код в фоновом потоке, и, таким образом, ваш интерфейс сможет обновляться.

Я не знаю, можно ли это сделать в AppleScriptObjC, потому что я не слишком хорошо с ним знаком. Вот как я это делаю в объекте-c. Я создаю обработчик (someHandler), а затем запускаю этот код. Обратите внимание, что, поскольку этот обработчик не запускается в основном потоке, который имеет автоматически сгенерированный пул выпусков, вам придется создать и осушить пул выпусков в своем обработчике.

[NSThread detachNewThreadSelector:@selector(someHandler) toTarget:self withObject:nil];

ИЗМЕНИТЬ: вот пул автозапуска, о котором вы спрашивали. В среде с подсчетом ссылок сделайте это так ...

-(void)someHandler {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    // do your stuff here

    [pool drain];
}

С автоматическим подсчетом ссылок (ARC) вы бы сделали это следующим образом ...

-(void)someHandler {
    @autoreleasepool {
        // do your stuff here
    }
}

Поэтому я не уверен, что относится к AppleScriptObjC. Быстрый поиск в Google нашел этот пост.

person regulus6633    schedule 10.08.2013
comment
Мне удалось остановить работу. NSThread's detachNewThreadSelector_toTarget_withObject_("someHandler", self, missing value) То, что вы ответили, было именно тем, что я хотел сделать. Спасибо! - person subdiox; 11.08.2013
comment
Собственно, остановить функцию таким образом у меня не получилось. Я ищу другой способ ... - person subdiox; 11.08.2013
comment
property NSThread : class "NSThread" NSThread's detachNewThreadSelector_toTarget_withObject_("function", me, missing value) Этот код успешно работает! - person subdiox; 11.08.2013
comment
Кстати, как я могу создать и осушить пул релизов? Не могли бы вы написать, как это сделать в native-Objc? - person subdiox; 11.08.2013
comment
У меня такая ошибка: [NSAutoreleasePool retain]: Cannot retain an autorelease pool - person subdiox; 12.08.2013
comment
Почему вы пытаетесь его сохранить? В моем коде этого нет, так что и вам не стоит. Когда вы выполняете aloc / init, он сохраняется, поэтому вы просто сливаете его, когда закончите с ним ... что высвободило все в пуле и освободило сам пул. - person regulus6633; 12.08.2013
comment
NSThread's detachNewThreadSelector_toTarget_withObject_("function", me, missing value) обычно успешно работает, но иногда зависает. Поскольку я не знаю, как использовать NSAutoreleasePool, в качестве альтернативы я использовал performSelectorInBackground_withObject_("function", AppDelegate). Этот код работает отлично. - person subdiox; 12.08.2013
comment
Я создал новую тему - ›http://stackoverflow.com/questions/18199982/how-to-use-nsautoreleasepool-in-applescriptobjc - person subdiox; 13.08.2013

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

on doEventFetch()
    repeat
        tell current application's NSApp to set theEvent to nextEventMatchingMask_untilDate_inMode_dequeue_(((current application's NSLeftMouseDownMask) as integer) + ((current application's NSKeyDownMask) as integer), missing value, current application's NSEventTrackingRunLoopMode, true)
        if theEvent is missing value then
            exit repeat
        else
            tell current application's NSApp to sendEvent_(theEvent)
        end if
    end repeat
end doEventFetch

on loopFunc()
    repeat
        #Repeat stuff here...
        doEventFetch()
    end repeat
end loopFunc
person scohe001    schedule 11.08.2013
comment
Спасибо, этот код работает в моем примере, но в моем реальном проекте используется задержка 1200, поэтому этот код в нем не работает. Я не знаю, как остановить функцию в команде задержки. Но я буду использовать этот код в другом проекте. Спасибо. - person subdiox; 11.08.2013
comment
@ usingsystem8 Вместо задержки вы должны использовать NSTimer, который будет вызывать следующую функцию при срабатывании - person scohe001; 11.08.2013