I'm trying to get my Wink Hub working with Pubnub subscriptions in my iOS app, but all I ever get is a PNUnexpectedDisconnectCategory status in the didReceiveStatus callback.
Here is the code:
class AppDelegate: UIResponder, UIApplicationDelegate, PNObjectEventListener {
var window: UIWindow?
var client: PubNub
override init() {
let configuration = PNConfiguration(publishKey: "", subscribeKey: "fake-key")
client = PubNub.clientWithConfiguration(configuration)
super.init()
client.addListener(self)
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
client.subscribeToChannelGroups(
["sensor-channel0",
"sensor-channel1"],
withPresence: false)
return true
}
func client(client: PubNub, didReceiveMessage message: PNMessageResult) {
print("receivedMessage")
}
func client(client: PubNub, didReceiveStatus status: PNStatus) {
if status.category == .PNUnexpectedDisconnectCategory {
print("disconnected")
// This event happens when radio / connectivity is lost.
}
}
The subscribe and channel keys are taken straight from the device subscription data returned by the Wink API, so I am not sure what I am doing wrong. Any help would be appreciated!
I'm implementing some 3D touch quick actions for my iOS 9 app in swift, and I have a curious issue. When my app is in the background and I launch with the quick action, everything goes as planned. When my app is totally dead (i.e. I killed it from the multitasking menu), and I launch with the quick action, the app crashes. I'm having trouble debugging this as once I kill the app, the debug session in Xcode gets detached. Is there a way for me to connect to the app to debug like normal, or is there something in my code that would be causing it? Thanks in advance.
Code:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
var launchedFromShortCut = false
//Check for ShortCutItem
if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey] as? UIApplicationShortcutItem
{
launchedFromShortCut = true
self.handleShortCutItem(shortcutItem)
}
return !launchedFromShortCut
}
func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void)
{
self.handleShortCutItem(shortcutItem)
}
func handleShortCutItem(shortcutItem: UIApplicationShortcutItem)
{
//Get type string from shortcutItem
if let shortcutType = ShortcutType.init(rawValue: shortcutItem.type)
{
//Get root navigation viewcontroller and its first controller
let rootNavigationViewController = window!.rootViewController as? UINavigationController
if let rootViewController = rootNavigationViewController?.viewControllers.first as! LaunchViewController?
{
//Pop to root view controller so that approperiete segue can be performed
rootNavigationViewController?.popToRootViewControllerAnimated(false)
switch shortcutType
{
case .Compose:
rootViewController.shouldCompose()
break
}
}
}
}
Thanks!
In Xcode, open Product -> Schemes -> Edit Schemes
In your Run Scheme, change the Launch setting to 'Wait for executable to be launched'
Now, if you turn on debugging and run your app, Xcode will wait for you to launch your app from the home screen so you are able to test launching it using a 3D Touch Shortcut Item.
I finally got this working. Here's what my AppDelegate.swift file ended up as;
class AppDelegate: UIResponder, UIApplicationDelegate {
// Properties
var window: UIWindow?
var launchedShortcutItem: UIApplicationShortcutItem?
func applicationDidBecomeActive(application: UIApplication) {
guard let shortcut = launchedShortcutItem else { return }
handleShortcut(shortcut)
launchedShortcutItem = nil
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
var shouldPerformAdditionalDelegateHandling = true
// If a shortcut was launched, display its information and take the appropriate action
if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey] as? UIApplicationShortcutItem {
launchedShortcutItem = shortcutItem
// This will block "performActionForShortcutItem:completionHandler" from being called.
shouldPerformAdditionalDelegateHandling = false
}
return shouldPerformAdditionalDelegateHandling
}
func handleShortcut( shortcutItem:UIApplicationShortcutItem ) -> Bool {
// Construct an alert using the details of the shortcut used to open the application.
let alertController = UIAlertController(title: "Shortcut Handled", message: "\"\(shortcutItem.localizedTitle)\"", preferredStyle: .Alert)
let okAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(okAction)
// Display an alert indicating the shortcut selected from the home screen.
window!.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
return handled
}
func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
completionHandler(handleShortcut(shortcutItem))
}
Much of this was taken from Apple's sample code for UIApplicationShortcuts, and while I'm having my app launch an alert to prove that it is recognizing the proper shortcut was chosen, this could be adapted to your code to pop the view controller.
I think the func applicationDidBecomeActive was the critical part that I was missing, and removing the self.handleShortCut(shortcutItem) from didFinishLaunchingWithOptions (otherwise it was calling handleShortCut twice, it seemed).
For Swift 4.2
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
var isLaunchedFromQuickAction = false
if let shortcutItem = launchOptions?[UIApplication.LaunchOptionsKey.shortcutItem] as? UIApplicationShortcutItem {
isLaunchedFromQuickAction = true
handleQuickAction(shortcutItem: shortcutItem)
}
return isLaunchedFromQuickAction
}
I tried all the above, and it didn't solve the problem
than I tried handling the shortcut after delay in handleShortcut method:
self.performSelector("action1", withObject: self, afterDelay: 0.5)
and added a method for every action, and it worked like a charm
Replace your didfinishlaunching method with this one.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
if let shortcutItem =
launchOptions?[UIApplicationLaunchOptionsShortcutItemKey]
as? UIApplicationShortcutItem {
handleShortcut(shortcutItem)
return false
}
return true
}
XCode 11.6, Swift 5
We can attach a process at runtime. XCode will wait until the process is started and will get attached to it when an App is launched manually.
XCode -> Debug -> Attach to process by PID or Name -> ("Enter the name of an app in the pop-up")
Directions:
Make sure an application is freshly installed on a device or a simulator.
Kill the application.
In XCode attach the name of the process as mentioned above.
Open the application through the desired shortcut
P.S: If you are using SceneDelegate a shortcutItem can be found in
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
switch connectionOptions.shortcutItem?.localizedTitle {
case "Search":
break
case "DoSomething":
break
default:
break
}
}
Happy Debugging :)
Using: XCode 7, iPhone 5 (iOS 8.3), WiFi, Reachability (check the internet connection).
While my app is in background and I click to open my app it checks the conncetion and load some functions and in 1 of the functions I try to sign:
imageView.image = UIImage(named: "imagename")
error: fatal error: unexpectedly found nil while unwrapping an Optional value
This happens only when my app change an IBOutlet value in applicationWillEnterForeground with function to primary view controller
self.viewController.functionName()
class AppDelegate: UIResponder, UIApplicationDelegate {
var viewController:ViewController = ViewController()
func applicationWillEnterForeground(application: UIApplication) {
self.viewController.checkConn()
}
}
checkConn() check the connection with Reachability and change IBOutlets values like .image and .text
Is there any way to fix it?
After a lot of tests I found this method which works great:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var viewController:ViewController?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
viewController = self.window!.rootViewController as? ViewController
return true
}
func applicationWillEnterForeground(application: UIApplication) {
viewController!.checkConn()
}
}
I am assuming that this is where your crash is happening.
imageView.image = UIImage(named: "imagename")
If you are using "Images.xcassets" to manage your image files. Make sure that "imagename" exists.
I am integrating chartboost into my sprite kit game and have successfully integrated bridging files into my swift code. Now in my app delegate I have the following:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
let kChartboostAppID = "5554c8680d60255c6a0f4af4"
let kChartboostAppSignature = "1d0e271cd054c9a63473d2f1212ca33a2922a19f"
Chartboost.startWithAppId(kChartboostAppID, appSignature: kChartboostAppSignature, delegate: self)
Chartboost.cacheMoreApps(CBLocationHomeScreen)
return true
}
class func showChartboostAds()
{
Chartboost.showInterstitial(CBLocationHomeScreen);
}
func didFailToLoadInterstitial(location: String!, withError error: CBLoadError) {
}
the startWithId line gives me an error that it cant invoke this method with these arguments ( String, String, AppDelegate). This used to work fine on my objective c code.. Anyone knows how to fix this?
class AppDelegate: UIResponder, UIApplicationDelegate, ChartboostDelegate
Edit (from Lalit's comment below)
In startWithAppId the delegate is set to self, so you have to set the class AppDelegate as the delegate, which is done using:
ChartboostDelegate(protocol)
I have scenario where my app receives an application:openURL:sourceApplication call from an extension and I want to open a tab in my tabBar and once its fully loaded then sendNext to a signal that the tabBar will be listening to once its loaded.
so sequence of events would be something like:
AppDelegate receives an OpenURL call
AppDelegate requests tabBar to load/open a tab called RemindersViewController
RemindersViewController RACSubject called RemindersLoadedSignal which i send to it a next value of true once the view has complete loading and binding
AppDelegate listens to the RemindersLoadedSignal and when it receives next from it it will emit its next signal to openURLSubject.
RemindersViewController listening to openURLSubject will perform some action since now its loaded and the signal was emitted.
class AppDelegate: UIResponder, UIApplicationDelegate {
let openURLSubject = RACSubject()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
RemindersLoadedSignal.subscribeNextAs({ (loaded:NSBool) -> () in
println("This subscription works for some reason")
})
return true
}
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
myTabBar.selectTabWithClass(RemindersViewController.self)
//SendNext to openURLSubject once the tab is loaded
RemindersLoadedSignal.subscribeNextAs({ (loaded:NSBool) -> () in
println("This subscription Never gets called")
self.openURLSubject.sendNext(reminderURLRequest)
})
return true
}
}
let RemindersLoadedSignal = RACSubject()
class RemindersViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
bindViewModel()
}
func bindViewModel(){
sharedAppDelegate().openURLSubject.subscribeNextAs { (request:OpenURLRequest) -> () in
println("got url request")
}
RemindersLoadedSignal.sendNext(NSBoolTrue)
}
}
I dont understand how the subscription in didFinishLaunchingWithOptions works and the one in application:openURL:... doesnt.
I ended up loading the view with doNext and Zipping the signal with the RemindersLoadedSignal.
If you see any potential problems with that please let me know.
Thanks
.doNext { (_:AnyObject!) -> Void in
if let myTabBar = self.window?.rootViewController as? UITabBarController {
myTabBar.selectTabWithClass(RemindersViewController.self)
}
}
.zipWith(RemindersLoadedSignal)