Macos SKView在更改屏幕参数时压碎应用程序

Macos SKView在更改屏幕参数时压碎应用程序,macos,sprite-kit,Macos,Sprite Kit,即使是在最小的应用程序中,也非常小: import Cocoa import SpriteKit @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { @IBOutlet weak var window: NSWindow! @IBOutlet weak var skView: SKView! // in MainMeny.xib of the template SpriteKit ap

即使是在最小的应用程序中,也非常小:

import Cocoa
import SpriteKit

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet weak var window: NSWindow!
    @IBOutlet weak var skView: SKView! // in MainMeny.xib of the template SpriteKit app
}
如果我在
系统首选项中更改屏幕分辨率(例如从1920 x 1080更改为1600 x 900,或从后面更改),则当我将鼠标悬停在
SKView
上时,会出现旋转的海滩球,并且无法再与窗口交互(例如调整窗口大小)。令人沮丧的是,我在控制台(无论是系统还是Xcode)中什么也没有得到,也不是每次都会发生,尽管大多数情况下都会发生。视图是否来自
xib
或是否以编程方式创建都没有区别

任何线索都欢迎

如果有人能证实他们也看到了这一点,我也将非常感激


(在OS X 10.10.3上的debug Xcode 6.3.2中构建,包括调试和发布)

由于这是用这样一个最小的应用程序复制的,而且没有人响应,因此我不得不继续假设这是一个
SpriteKit
错误。如果人们确认他们也看到了这一点,我会提交一份bug报告。同时,我无法提交我的应用程序,因为我知道只要用户更改显示配置,它就会崩溃。然而,要避免撞车却相当棘手

首先,应用程序在调用
NSApplication
applicationIDChangeScreenParameters(:)
之前崩溃。为了更快地捕获事件,我们可以使用
CGDisplayRegisterReconfigurationCallback
。这是一个C函数,其第一个参数(a
CFunctionPointer
)目前无法在Swift中构造。要使用它,我必须下降到C和Objective-C:

显示配置更改。h

#import <Foundation/Foundation.h>

extern NSString * DisplayConfigurationWillChange;
extern NSString * DisplayConfigurationDidChange;

extern void StartNotificationsOnDisplayConfigurationChange();
extern void StopNotificationsOnDisplayConfigurationChange();
不要忘记将其导入
-bridgeing Header.h

#import "DisplayConfigurationChanges.h"
现在,我们可以随时发布
DisplayConfigurationWillChange
DisplayConfigurationDidChange
通知,并在任何地方观察它们,包括应用程序的Swift端:

AppDelegate.swift

import Cocoa
import SpriteKit

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet weak var window: NSWindow!

    func displayWillChange() {
        println("display will change \(NSScreen.mainScreen()!.frame.size)")
    }

    func applicationDidChangeScreenParameters(notification: NSNotification) {
        println("display did change \(NSScreen.mainScreen()!.frame.size)")
    }

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        StartNotificationsOnDisplayConfigurationChange()
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "displayWillChange", name: DisplayConfigurationWillChange, object: nil)
    }

    func applicationWillTerminate(notification: NSNotification) {
        StopNotificationsOnDisplayConfigurationChange()
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
}
在应用程序运行时(无任何
SKView
s),更改
系统首选项中的显示分辨率将打印:

display will change (1920.0, 1080.0)
display did change (1600.0, 900.0)

如果我们现在添加一个
SKView
,应用程序将崩溃,只打印上面的第一行。但这就是成功!这意味着我们确实及时收到了更改通知,可以采取一些措施。

事实证明,我们唯一能做的“改变”就是重新启动应用程序!(如果您想知道如何做到这一点,请参阅。)谢天谢地,在我们的例子中,这对用户来说没有什么影响,但仍然远远不够理想。
display will change (1920.0, 1080.0)
display did change (1600.0, 900.0)