我目前正在使用Swift 3,SpriteKit和Xcode 8 beta开发游戏。我试图通过info.plist从主屏幕实现静态3D Touch Quick Actions。目前,主屏幕上的动作显得很好,但不要转到右边的SKScene - 转到初始场景或最后打开的场景(如果应用程序仍然打开),这意味着场景没有被更改。我已尝试过各种方法在switch语句中设置场景,但似乎没有一个方法可以正常呈现SKScene,因为行window!.rootViewController?.present(gameViewController, animated: true, completion: nil)
仅适用于UIViewController。
此代码的各个部分来自各种教程,但我通过调查确定破损的部分是正在呈现的场景(除非我错了),因为它不应该如果零件损坏,甚至可以加载任何场景。
我有什么方法可以从AppDelegate呈现SKScene或根据switch语句设置开场景?
的AppDelegate
import UIKit
import SpriteKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
guard !handledShortcutItemPress(forLaunchOptions: launchOptions) else { return false } // ADD THIS LINE
return true
}
}
extension AppDelegate: ShortcutItem {
/// Perform action for shortcut item. This gets called when app is active
func application(_ application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
completionHandler(handledShortcutItemPress(forItem: shortcutItem))
}
}
extension AppDelegate: ShortcutItemDelegate {
func shortcutItem1Pressed() {
Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(loadShopScene), userInfo: nil, repeats: false)
}
@objc private func loadShopScene() {
let scene = ShopScene(size: CGSize(width: 768, height: 1024))
loadScene(scene: scene, view: window?.rootViewController?.view)
}
func shortcutItem2Pressed() {
Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(loadGameScene), userInfo: nil, repeats: false)
}
@objc private func loadGameScene() {
let scene = GameScene(size: CGSize(width: 768, height: 1024))
loadScene(scene: scene, view: window?.rootViewController?.view)
}
func shortcutItem3Pressed() {
// do something else
}
func shortcutItem4Pressed() {
// do something else
}
func loadScene(scene: SKScene?, view: UIView?, scaleMode: SKSceneScaleMode = .aspectFill) {
guard let scene = scene else { return }
guard let skView = view as? SKView else { return }
skView.ignoresSiblingOrder = true
#if os(iOS)
skView.isMultipleTouchEnabled = true
#endif
scene.scaleMode = scaleMode
skView.presentScene(scene)
}
}
3DTouchQuickActions.swift
import Foundation
import UIKit
/// Shortcut item delegate
protocol ShortcutItemDelegate: class {
func shortcutItem1Pressed()
func shortcutItem2Pressed()
func shortcutItem3Pressed()
func shortcutItem4Pressed()
}
/// Shortcut item identifier
enum ShortcutItemIdentifier: String {
case first // I use swift 3 small letters so you have to change your spelling in the info.plist
case second
case third
case fourth
init?(fullType: String) {
guard let last = fullType.components(separatedBy: ".").last else { return nil }
self.init(rawValue: last)
}
public var type: String {
return Bundle.main.bundleIdentifier! + ".\(self.rawValue)"
}
}
/// Shortcut item protocol
protocol ShortcutItem { }
extension ShortcutItem {
// MARK: - Properties
/// Delegate
private weak var delegate: ShortcutItemDelegate? {
return self as? ShortcutItemDelegate
}
// MARK: - Methods
/// Handled shortcut item press first app launch (needed to avoid double presses on first launch)
/// Call this in app Delegate did launch with options and exit early (return false) in app delegate if this method returns true
///
/// - parameter forLaunchOptions: The [NSObject: AnyObject]? launch options to pass in
/// - returns: Bool
func handledShortcutItemPress(forLaunchOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
guard let launchOptions = launchOptions, let shortcutItem = launchOptions[UIApplicationLaunchOptionsKey.shortcutItem] as? UIApplicationShortcutItem else { return false }
handledShortcutItemPress(forItem: shortcutItem)
return true
}
/// Handle shortcut item press
/// Call this in the completion handler in AppDelegate perform action for shortcut item method
///
/// - parameter forItem: The UIApplicationShortcutItem the press was handled for.
/// - returns: Bool
func handledShortcutItemPress(forItem shortcutItem: UIApplicationShortcutItem) -> Bool {
guard let _ = ShortcutItemIdentifier(fullType: shortcutItem.type) else { return false }
guard let shortcutType = shortcutItem.type as String? else { return false }
switch shortcutType {
case ShortcutItemIdentifier.first.type:
delegate?.shortcutItem1Pressed()
case ShortcutItemIdentifier.second.type:
delegate?.shortcutItem2Pressed()
case ShortcutItemIdentifier.third.type:
delegate?.shortcutItem3Pressed()
case ShortcutItemIdentifier.fourth.type:
delegate?.shortcutItem4Pressed()
default:
return false
}
return true
}
}
答案 0 :(得分:1)
您的代码无效,因为在您的app委托中,您创建了一个新的GameViewController实例,而不是引用当前的实例
let gameViewController = GameViewController() // creates new instance
我正在完成你在我的两款游戏中使用3d touch快速动作所做的事情。我直接从appDelegate加载场景,不要尝试为此更改gameViewController场景。
我为此使用可重复使用的助手。假设您在info.plist中正确设置了所有内容。 (我在枚举中使用小写字母,以便在info.plist中使用.first,.second等结束您的项目),删除之前用于3d touch快速操作的所有应用委托代码。 在项目中创建一个新的.swift文件并添加此代码
这是快速的3代码。
import UIKit
/// Shortcut item delegate
protocol ShortcutItemDelegate: class {
func shortcutItemDidPress(_ identifier: ShortcutItemIdentifier)
}
/// Shortcut item identifier
enum ShortcutItemIdentifier: String {
case first // I use swift 3 small letters so you have to change your spelling in the info.plist
case second
case third
case fourth
private init?(fullType: String) {
guard let last = fullType.componentsSeparatedByString(".").last else { return nil }
self.init(rawValue: last)
}
public var type: String {
return (Bundle.main.bundleIdentifier ?? "NoBundleIDFound") + ".\(rawValue)"
}
}
/// Shortcut item protocol
protocol ShortcutItem { }
extension ShortcutItem {
// MARK: - Properties
/// Delegate
private weak var delegate: ShortcutItemDelegate? {
return self as? ShortcutItemDelegate
}
// MARK: - Methods
func didPressShortcutItem(withOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
guard let shortcutItem = launchOptions?[.shortcutItem] as? UIApplicationShortcutItem else { return false }
didPressShortcutItem(shortcutItem)
return true
}
/// Handle item press
@discardableResult
func didPressShortcutItem(_ shortcutItem: UIApplicationShortcutItem) -> Bool {
guard let _ = ShortcutItemIdentifier(fullType: shortcutItem.type) else { return false }
switch shortcutItem.type {
case ShortcutItemIdentifier.first.type:
delegate?.shortcutItemDidPress(.first)
case ShortcutItemIdentifier.second.type:
delegate?.shortcutItemDidPress(.second)
case ShortcutItemIdentifier.third.type:
delegate?.shortcutItemDidPress(.third)
case ShortcutItemIdentifier.fourth.type:
delegate?.shortcutItemDidPress(.fourth)
default:
return false
}
return true
}
}
比你的app delegate用这个方法创建一个扩展(你在代码中错过了这个)
extension AppDelegate: ShortcutItem {
/// Perform action for shortcut item. This gets called when app is active
func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
completionHandler(didPressShortcutItem(shortcutItem))
}
比你需要调整AppDelegate中的didFinishLaunchingWithOptions方法看起来像这样
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
...
return !didPressShortcutItem(withOptions: launchOptions)
}
最后创建另一个确认ShortcutItem委托的扩展名
extension AppDelegate: ShortcutItemDelegate {
func shortcutItemDidPress(_ identifier: ShortcutItemIdentifier) {
switch identifier {
case .first:
let scene = GameScene(size: CGSize(width: 1024, height: 768))
loadScene(scene, view: window?.rootViewController?.view)
case .second:
//
case .third:
//
case .fourth:
//
}
}
func loadScene(scene: SKScene?, view: UIView?, scaleMode: SKSceneScaleMode = .aspectFill) {
guard let scene = scene else { return }
guard let skView = view as? SKView else { return }
skView.ignoresSiblingOrder = true
#if os(iOS)
skView.isMultipleTouchEnabled = true
#endif
scene.scaleMode = scaleMode
skView.presentScene(scene)
}
}
我通常在另一个帮助器中拥有的加载场景方法,这就是我将视图传递给func的原因。
希望这有帮助。