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

时间:2015-05-19 19:56:43

标签: 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 app
}

如果我在System Preferences中更改屏幕的分辨率(例如从1920 x 1080到1600 x 900,或者返回),当我将鼠标悬停在SKView上时,会出现旋转的沙滩球可以更长时间与窗口交互(例如,调整窗口大小)。令人沮丧的是,我在控制台(系统或Xcode)中什么也得不到,也不是每次都会发生这种情况。视图是来自xib还是以编程方式创建,没有区别。

任何线索都会非常受欢迎。

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

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

1 个答案:

答案 0 :(得分:0)

由于这是用这样一个最小的应用程序复制的,并且由于没有人响应,我被迫继续假设这是一个SpriteKit错误。如果人们确认他们也看到了这一点,我会提交错误报告。在此期间,我现在无法提交我的应用程序,因为我知道只要用户更改显示配置,它就会崩溃。然而,为了避免崩溃,证明是相当棘手的......

首先,应用程序在调用NSApplication的{​​{1}}之前崩溃。为了尽快发现事件,我们可以使用applicationDidChangeScreenParameters(:)。这是一个C函数,其第一个参数(CGDisplayRegisterReconfigurationCallback)目前无法在Swift中构造。要使用它,我必须下降到C和Objective-C:

<强> DisplayConfigurationChanges.h

CFunctionPointer

<强> DisplayConfigurationChanges.m

#import <Foundation/Foundation.h>

extern NSString * DisplayConfigurationWillChange;
extern NSString * DisplayConfigurationDidChange;

extern void StartNotificationsOnDisplayConfigurationChange();
extern void StopNotificationsOnDisplayConfigurationChange();

不要忘记在#import "DisplayConfigurationChanges.h" NSString * DisplayConfigurationWillChange = @"DisplayConfigurationWillChange"; NSString * DisplayConfigurationDidChange = @"DisplayConfigurationidChange"; void DisplayReconfigurationBlock (CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *userInfo) { if (flags & kCGDisplayBeginConfigurationFlag) { [[NSNotificationCenter defaultCenter] postNotificationName:DisplayConfigurationWillChange object:nil]; } else { [[NSNotificationCenter defaultCenter] postNotificationName:DisplayConfigurationDidChange object:nil]; } } void StartNotificationsOnDisplayConfigurationChange() { CGDisplayRegisterReconfigurationCallback(DisplayReconfigurationBlock, NULL); } void StopNotificationsOnDisplayConfigurationChange() { CGDisplayRemoveReconfigurationCallback(DisplayReconfigurationBlock, NULL); }

中导入它
-Bridging-Header.h

现在我们可以随时开始发布#import "DisplayConfigurationChanges.h" DisplayConfigurationWillChange通知,并随时随地观察,包括应用的Swift端:

<强> AppDelegate.swift

DisplayConfigurationDidChange

在应用程序运行时更改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) } } 中的显示分辨率(没有任何System Preferences)将打印:

SKView

如果我们现在添加display will change (1920.0, 1080.0) display did change (1600.0, 900.0) ,应用程序会崩溃,只打印上面的第一行。但这是成功的!这意味着我们确实得到了及时做出改变的通知。