gpt4 book ai didi

swift - 3D Touch Quick Actions 无法与 SpriteKit 一起正常工作

转载 作者:行者123 更新时间:2023-11-28 16:16:13 26 4
gpt4 key购买 nike

我目前正在使用 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
}
}

最佳答案

您的代码无法正常工作,因为在您的应用委托(delegate)中您创建了一个新的 GameViewController 实例,而不是引用当前实例

let gameViewController = GameViewController() // creates new instance

在我的 2 个游戏中,我正在使用 3d 触摸快速操作来做您想要做的事情。我直接从 appDelegate 加载场景,不要为此尝试更改 gameViewController 场景。

我为此使用了一个可重用的助手。假设您在 info.plist 中正确设置了所有内容。 (我在枚举中使用小写字母,所以在 info.plist 中以 .first、.second 等结束你的项目),删除你之前为 3d touch 快速操作而拥有的所有应用程序委托(delegate)代码。在您的项目中创建一个新的 .swift 文件并添加此代码

这是 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
}
}

然后在您的应用委托(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 委托(delegate)

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)
}
}

我通常在另一个助手中使用的加载场景方法,这就是为什么我将 View 传递给函数的原因。

希望这对您有所帮助。

关于swift - 3D Touch Quick Actions 无法与 SpriteKit 一起正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39054864/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com