【问题标题】:How to stop function while it is running如何在运行时停止功能
【发布时间】:2013-08-11 14:30:33
【问题描述】:

我正在使用 Applescript 在 Xcode 上编写 Mac 应用程序。
我做了一个不会永远停止的函数,但我无法停止它。
当我按下位于窗口上的按钮时,它就会启动。
由于此功能不会停止,因此按钮似乎永远被按下。
我必须使用“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
对不起,我是日本人,英语写得不好。

【问题讨论】:

    标签: xcode macos applescript exit


    【解决方案1】:

    基本上,您的应用程序界面在您的应用程序主线程上进行控制和更新。因此,如果您运行一些绑定主线程的代码,那么您的界面将没有机会自我更新,直到代码完成。因此,要解决您在后台线程中运行代码的问题,您的界面将能够自行更新。

    我不知道您是否可以在 AppleScriptObjC 中执行此操作,因为我对它不太熟悉。这是我在objective-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。一个快速的谷歌搜索出现了this post

    【讨论】:

    • 我成功地停止了我的功能。 NSThread's detachNewThreadSelector_toTarget_withObject_("someHandler", self, missing value)你回答的正是我想做的。谢谢!
    • 实际上,我无法以这种方式成功停止该功能。我正在寻找另一种方式...
    • property NSThread : class "NSThread" NSThread's detachNewThreadSelector_toTarget_withObject_("function", me, missing value) 此代码成功!
    • 顺便说一句,我如何创建和排空发布池?你能用native-Objc写一下怎么做吗?
    • 我收到了这个错误:[NSAutoreleasePool retain]: Cannot retain an autorelease pool
    【解决方案2】:

    现在你的代码在循环,像界面这样重要的东西永远不会更新。如果您调用 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
    

    【讨论】:

    • 谢谢,此代码在我的示例中有效,但我的实际项目使用“延迟 1200”,因此此代码在其中不起作用。我不知道如何在“延迟”命令中停止该功能。但我将在另一个项目中使用此代码。谢谢。
    • @usingsystem8 你应该使用一个 NSTimer,它会在触发时调用下一个函数,而不是延迟
    猜你喜欢
    • 1970-01-01
    • 2020-05-05
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-12
    • 1970-01-01
    • 2021-09-24
    相关资源
    最近更新 更多