3D touch quick actions preview view controller only one time
I'm guessing you're trying to present a view controller from a view controller that's not visible. You can use extensions like:
extension UIViewController {
func topMostViewController() -> UIViewController {
if self.presentedViewController == nil {
return self
}
if let navigation = self.presentedViewController as? UINavigationController {
return navigation.visibleViewController.topMostViewController()
}
if let tab = self.presentedViewController as? UITabBarController {
if let selectedTab = tab.selectedViewController {
return selectedTab.topMostViewController()
}
return tab.topMostViewController()
}
return self.presentedViewController!.topMostViewController()
}
}
extension UIApplication {
func topMostViewController() -> UIViewController? {
return self.keyWindow?.rootViewController?.topMostViewController()
}
}
You can place both of these in your app delegate.swift, above your app delegate class, to get the currently visible view controller. Then present the search view controller on that. For example:
func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
if shortcutItem.type == "com.traning.Search" {
let sb = UIStoryboard(name: "Main", bundle: nil)
let searchVC = sb.instantiateViewControllerWithIdentifier("searchVC") as! UINavigationController
let topViewController = UIApplication.sharedApplication.topMostViewController()
topViewController.presentViewController(searchVC, animated: false, completion: { () -> Void in
completionHandler(true)
})
}
}
3D Touch Quick Actions not working properly with SpriteKit
Your code is not working because in your app delegate you create a new instance of GameViewController instead of referencing the current one
let gameViewController = GameViewController() // creates new instance
I am doing exactly what you are trying to do with 3d touch quick actions in 2 of my games. I directly load the scene from the appDelegate, dont try to change the gameViewController scene for this.
I use a reusable helper for this. Assuming you set up everything correctly in your info.plist. (I use small letters in the enum so end your items with .first, .second etc in the info.plist), remove all your app delegate code you had previously for the 3d touch quick actions.
Than create a new .swift file in your project and add this code
This is swift 3 code.
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
}
}
Than in your app delegate create an extension with this method (you missed this in your code)
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))
}
Than you need to adjust the didFinishLaunchingWithOptions method in your AppDelegate to look like this
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
...
return !didPressShortcutItem(withOptions: launchOptions)
}
And than finally create another extension confirming to the 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)
}
}
The load scene method I normally have in another helper which is why I pass the view into the func.
Hope this helps.
3D Touch Shortcut Widget
There is a new Info.plist key UIApplicationShortcutWidget
which you need to set to the bundle identifier of your widget.
See the documentation at: https://developer.apple.com/library/prerelease/content/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html#//apple_ref/doc/uid/TP40009252-SW32
Related Topics
Swiftui Remove Transition of Fullscreen Cover
Change Color of Row Programmatically in Watchkit
Wkwebview Calayer to Image Exports Blank Image
How to Enable a Button in Different Cases in Swift
Non-Translucent UItabbar Creates Strange Grey Bar
How to Create Viewcontrollers Without Storyboard and Set One as Delegate of The Other One
How to Use Gpx File for UI Tests Only
Swiftui: Unable to Animate Images
How to Create Nested Dictionary Elements in Swift
How to Pause an Animation in Swiftui
Swift: Simple Dispatchqueue Does Not Run & Notify Correctly
Problems with Unified Logging, Staticstring, Customstringconvertible and Description
What Do Detached and Assigncurrentcontext Meaning
How to Pass a Completion Block to Another Class in Swift
Swift 3/4 Dash to Camel Case (Snake to Camelcase)
What Is The Reason to Store Subscription into a Subscriptions Set