APPDelegate中的openURL转换错误NSString – > String(Swift和iOS8)

我目前正在开发一个整合了Facebook的iOS应用程序,而我在使用Swift(使用ObjC时没有任何问题)进行调查时遇到了一些问题。

事情是,这是从另一个应用程序(在这种情况下,在Web浏览器中的FB)来appDelegate中执行的方法:

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 } 

而在这个方法中,我遇到了'sourceApplication'参数的麻烦。 我尝试使用它,我得到一个例外。 我尝试转换它,另一个例外…甚至不能logging它的值,因为它访问它的值时崩溃。 将函数签名中的参数types更改为String不起作用。

这是我得到的错误:

EXEC_BAD_ACCESS

而且我已经能够追踪到,直到我可以读这个,这绝对是一个有价值的提示:

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

它可能是一个iOS8的错误? 你们中的任何人都有这个问题,或者知道如何解决这个问题?

你犯了两个错误:

  1. 从应用程序委托的函数声明是func application(application: UIApplication!, openURL url: NSURL!, sourceApplication: String!, annotation: AnyObject!) -> Bool :sourceApplication是一个可选的String值不是NSString。

  2. 由于sourceApplication是一个可选的,它可能会返回值(在你的情况下返回 )。 types铸造string是不安全的,因此它是崩溃。

解决scheme

  1. 您的情况下不需要types转换由于返回的值是stringtypes
  2. 使用可选的表单types转换运算符为? 安全地input即可

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

这是为我工作(与FacebookSDK):

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

我没有在操场上得到这个。 可能是你build议的iOS 8的错误但为了尝试,你可以尝试

 let appString : String = String(sourceApplication) 

对于FB Messenger来说 ,我在AppDelegate中做了一些更好的处理。 大部分想法直接从FB IOS文档中获取并移植到Swift。

为什么我觉得我应该写一个额外的答复? 我已经有了一些Swift的经验,但是觉得我浪费了足够的时间来尝试使用FB Messenger来做正确的代码。 希望原始代码对某人有用,只是为了巩固许多零碎,并节省一些时间。

注意:这不包括所有你需要的AppDelegate生命周期方法,但希望这是一个开始

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