首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SpriteKit窗口在"applicationDidFinishLaunching“方法退出之前不会重绘。

SpriteKit窗口在"applicationDidFinishLaunching“方法退出之前不会重绘。
EN

Stack Overflow用户
提问于 2015-01-15 13:59:47
回答 1查看 169关注 0票数 1

我使用Mac的SpriteKit (而不是iOS)来运行我的程序。

在"AppDelegate"-Class的“AppDelegate”方法的末尾,我将启动初始化所需的所有内容。有些方法不喜欢从后台线程调用,比如设置窗口标题、调整窗口大小和其他一些任务。所以所有这些事情都是在主线程中完成的。

然后是我的问题:我不能简单地在"applicationDidFinishLaunching“方法的末尾运行我的主程序,因为当我这样做时,"applicationDidFinishLaunching”方法在我的主程序退出之前不会退出。我的主程序没有退出,因为它在启动程序后直接在屏幕上显示了一些动画。

在这种情况下,"applicationDidFinishLaunching“方法不会退出,SpriteKit不会重新绘制窗口,所以我的动画运行,但我看到一个白色窗口。

退出我的程序后,"applicationDidFinishLaunching“方法也退出了,我看到了动画的最后一张图片。

因此,我意识到了一个解决办法:我现在在"applicationDidFinishLaunching“方法中进行初始化,然后启动一个后台线程来运行我的主程序。

"applicationDidFinishLaunching“在启动后台线程后退出,窗口将按预期更新。所有的一切运行良好的背景线程做动画。

而现在的问题,我无法解决:我需要隐藏菜单栏,不是直接启动程序,而是在一段时间后。

代码语言:javascript
复制
NSMenu.setMenuBarVisible(false)

当从主线程调用时,这样做没有问题,但是如果我从后台线程隐藏菜单栏,那么我可以隐藏它一次,使它可见一次,第二次隐藏它,以及当AppDelegate类中的异常第二次停止我的程序时:

代码语言:javascript
复制
Thread 1: EXC_BAD_ACCESS (code=EXC_i386_GPFLT)

我解决这个问题的想法是发布一个事件,这个事件是由主线程处理的。但是如果我发布一个键盘事件,事件处理也是在后台线程中完成的。

像由用户选择菜单,而不是以编程的方式选择的事件是从主线程中分配的,但是我没有找到一种方法将一个事件发送到主线程中,而不是包含sendEvent命令的线程中:

代码语言:javascript
复制
NSApplication.sharedApplication().sendEvent(event!) // Called from background-thread

有谁想过发送一个由主线程处理的事件吗?

完全在主线程中运行我的程序,没有问题,窗口内容根本没有绘制。第二个解决方案将是我最喜欢的,因为还有更多的东西,它们会在后台线程中产生问题。

也许我可以从另一种方法开始我的主程序,在"applicationDidFinishLaunching“完成之后的一段时间。

关于上述主题的一些更深层次的信息,但仍然没有解决办法:

我发现,存在一个函数"performSelectorOnMainThread“,它可以从像这样的called调用:

代码语言:javascript
复制
NSApplication.performSelectorOnMainThread(Selector(myFunctionToCall()), withObject: nil, waitUntilDone: true)

此调用编译,调用我的函数,但在后台线程中,而不是在主线程上,并转储一个错误:

代码语言:javascript
复制
2015-01-17 20:11:09.142 AudioDatabase[4449:2099588] +[NSApplication (null selector)]: unrecognized selector sent to class 0x7fff7b1d8be0

但是死刑还在继续。除了像NSApplication、NSObject、NSThread这样的类函数之外,我无法调用任何其他类型的函数。但我从来没有达到过主回路。

另一个想法是使用NSInvocation,但当我查看文档时,只有Objective部分出现。

如果可能的话,它将有助于简单地调用我的函数,无论参数是否在主线程中运行,并且可以在其中做一些事情。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-01-18 10:39:59

在后台线程中运行我的程序时,我发现了一种在主线程异步执行必要命令的方法。要做到这一点,您必须打电话:

代码语言:javascript
复制
dispatch_async(dispatch_get_main_queue())
{
    // This block runs in the main thread
}

所以我的问题是,在不破坏我的程序的情况下显示和隐藏菜单栏。下面是从后台线程调用的已完成的函数:

代码语言:javascript
复制
func m_MenuBarShow ()
{
    dispatch_async(dispatch_get_main_queue())
    {
        NSMenu.setMenuBarVisible(true) // Class func, must be called on the Class (NSMenu) and not on the Instance (NSApp.sharedApp.mainMenu)
    }
}

func m_MenuBarHide ()
{
    dispatch_async(dispatch_get_main_queue())
    {
        NSMenu.setMenuBarVisible(false) // Class func
    }
}

请注意,在使用这个块时有一个小的限制:这个块称为异步,这意味着您必须确保它已经完成,直到对结果做一些事情。在显示菜单栏的情况下,这没有问题。但是,如果您想要打开文件这样的操作,就必须处理这个问题。

我将解释这一点,作为我另一个问题的答案。请看一看:Open File Dialog crashes in Swift

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27965079

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档