OpenURL in APPDelegate NSString & # 8594; conversion error String (Swift & iOS8)

I am currently developing an application for iOS that integrates Facebook, and I have a little problem exploring this with Swift (I have no problems with ObjC).

The fact is that this is a method that runs in appDelegate when exiting another APP (in this case, FB in WebBrowser):

func application( application: UIApplication, openURL url: NSURL, sourceApplication: NSString, annotation: AnyObject) -> Bool { let appString : String = sourceApplication as String // Try to convert format => EXCEPTION let appString : String = String(sourceApplication) // 'SSS' Suggestion: EXCEPTION println(sourceApplication) // Try to print the value => EXCEPTION return FBAppCall.handleOpenURL(url, sourceApplication:sourceApplication, withSession:session) // With Parse => EXCEPTION } 

And inside this method, I am having real problems with the 'sourceApplication' parameter. I try to use it, I get an exception. I am trying to convert it, another exception ... I can’t even register its value because it crashes when accessing its value. Changing the parameter type in the function signature in String did not work.

This is the error I get:

EXEC_BAD_ACCESS

And I was able to track until I was able to read this, which is definitely a valuable hint:

ObjectiveC.NSString.__conversion (ObjectiveC.NSString)() -> Swift.String

Could this be an iOS8 bug? Have any of you had this problem and / or does she know how to solve it?

+1
source share
4 answers

You made two mistakes:

  • Function declaration from application Delegate func application(application: UIApplication!, openURL url: NSURL!, sourceApplication: String!, annotation: AnyObject!) -> Bool : sourceApplication is an optional String value, not an NSString.

  • Since sourceApplication is optional, it can return nil (in your case, returns nil ). The casting type Zero to String is unsafe, so it fails.

Solutions:

  • In your case, type casting is not required. Return value String .
  • Use optional casting operator type how? to type cast ie safely

if let appString = sourceApplication { println(appString as? String) }

+1
source

This works for me (using FacebookSDK):

 func application(application: UIApplication, openURL url: NSURL, sourceApplication: NSString?, annotation: AnyObject) -> Bool { var wasHandled:Bool = FBAppCall.handleOpenURL(url, sourceApplication: sourceApplication) return wasHandled } 
+1
source

I do not understand this in the playground. There may be an iOS 8 bug, as you suggest. But for the sake of trying, can you try

 let appString : String = String(sourceApplication) 
0
source

For FB Messenger , I did here to improve management in AppDelegate. Most of the ideas were taken directly from the FB iOS documentation and transferred to Swift.

Why did I feel that I should write an additional answer? I have some experience with Swift, but I felt like I spent enough time trying to get the right set of code to do what I wanted with FB Messenger. Hope the source code is useful to someone, just to fix a lot of bits and parts and save some time.

NOTE. This does not include all the AppDelegate life cycle methods that you will need / need, but hopefully it starts

 @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, FBSDKMessengerURLHandlerDelegate { var window: UIWindow? var messengerUrlHandler: FBSDKMessengerURLHandler? var cancelContext : FBSDKMessengerURLHandlerCancelContext? var composerContext : FBSDKMessengerURLHandlerOpenFromComposerContext? var replyContext: FBSDKMessengerURLHandlerReplyContext? // Facebook Messenger enum MessengerShareMode : Int { case MessengerShareModeCancel case MessengerShareModeSend case MessengerShareModeComposer case MessengerShareModeReply } // shareMode holds state indicating which flow the user is in. // Return the corresponding FBSDKMessengerContext based on that state. var shareMode : MessengerShareMode? /* * Initialize the FB messenger handler and set self as the delegate. */ func application(application: UIApplication, willFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool { YARAppearance.setAppearance() let rootController = TabBarController() self.window = UIWindow(frame: UIScreen.mainScreen().bounds) self.window!.rootViewController = rootController self.window!.makeKeyAndVisible() // Facebook messenger handling self.messengerUrlHandler = FBSDKMessengerURLHandler() if (self.messengerUrlHandler != nil) { self.messengerUrlHandler!.delegate = self } return true } /* * Handle the cancel context flow. */ func messengerURLHandler(messengerURLHandler: FBSDKMessengerURLHandler!, didHandleCancelWithContext context: FBSDKMessengerURLHandlerCancelContext!) { self.cancelContext = context self.shareMode = .MessengerShareModeCancel } /* * When people enter your app through the composer in Messenger, * this delegate function will be called. */ func messengerURLHandler(messengerURLHandler: FBSDKMessengerURLHandler!, didHandleOpenFromComposerWithContext context: FBSDKMessengerURLHandlerOpenFromComposerContext!) { self.composerContext = context self.shareMode = .MessengerShareModeComposer } /* * When people enter your app through the "Reply" button on content * this delegate function will be called. */ func messengerURLHandler(messengerURLHandler: FBSDKMessengerURLHandler!, didHandleReplyWithContext context: FBSDKMessengerURLHandlerReplyContext!) { self.replyContext = context self.shareMode = .MessengerShareModeReply } /* * Handle URL calls from external applications, particularly Messenger */ func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool { let wasHandled:Bool = self.messengerUrlHandler!.openURL(url, sourceApplication: sourceApplication) return wasHandled } /* * A way to access the context objects elsewhere */ func getContextForShareMode() -> FBSDKMessengerContext? { // shareMode holds state indicating which flow the user is in. // Return the corresponding FBSDKMessengerContext based on that state. if (shareMode == .MessengerShareModeSend) { // Force a send flow by returning a broadcast context. return FBSDKMessengerBroadcastContext() } else if (shareMode == .MessengerShareModeComposer) { // Force the composer flow by returning the composer context. return self.composerContext! } else if (shareMode == .MessengerShareModeReply) { // Force the reply flow by returning the reply context. return self.replyContext! } return nil } } 
0
source

Source: https://habr.com/ru/post/1203160/


All Articles