0

現在、Swift 3、SpriteKit、および Xcode 8 ベータ版を使用してゲームを開発しています。ホーム画面からinfo.plistを介して静的3Dタッチクイックアクションを実装しようとしています。現在、アクションはホーム画面から正常に表示されますが、右の SKScene には移動しません。最初のシーンまたは最後に開いたシーン (アプリがまだ開いている場合) に移動します。これは、シーンが変更されていないことを意味します。switch ステートメント内でシーンを設定するさまざまな方法を試しましたが、行window!.rootViewController?.present(gameViewController, animated: true, completion: nil) が UIViewController でのみ機能するため、SKScene を表示するために適切に機能するものはないようです。

このコードのさまざまな部分はさまざまなチュートリアルからのものですが、調査の結果、破損した部分が提示されているシーンであることがかなり確信で​​きます (私が間違っていない限り)。 .

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

1 に答える 1

1

アプリのデリゲートで、現在のインスタンスを参照する代わりに GameViewController の新しいインスタンスを作成するため、コードが機能していません

let gameViewController = GameViewController() // creates new instance

2 つのゲームで 3D タッチ クイック アクションを使用して、あなたがやろうとしていることを正確に実行しています。appDelegate からシーンを直接ロードします。このために gameViewController シーンを変更しようとしないでください。

これには再利用可能なヘルパーを使用します。info.plist ですべてを正しく設定したと仮定します。(私は列挙型で小文字を使用しているため、info.plist では項目を .first、.second などで終了します)、以前に 3d タッチ クイック アクション用に持っていたすべてのアプリ デリゲート コードを削除します。プロジェクトに新しい .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
   }
}

アプリのデリゲートよりも、このメソッドで拡張機能を作成します (コードでこれを見逃しました)

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 に渡す理由です。

お役に立てれば。

于 2016-08-20T14:18:29.207 に答える