APP中的openURL转换错误NSString - >字符串(Swift& iOS8)

时间:2014-06-16 09:36:21

标签: ios swift appdelegate ios8 openurl

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

问题是,当来自另一个APP(在这种情况下是WebBrowser中的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'参数的问题。我尝试使用它,我得到一个例外。我尝试转换它,另一个例外...甚至无法记录其值,因为它在访问其值时崩溃。将函数签名中的参数类型更改为String既不起作用。

这是我得到的错误:

EXEC_BAD_ACCESS

我已经能够追踪,直到我能读到它,这绝对是一个有价值的暗示:

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

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

4 个答案:

答案 0 :(得分:1)

你犯了两个错误:

  1. app Delegate的函数声明为func application(application: UIApplication!, openURL url: NSURL!, sourceApplication: String!, annotation: AnyObject!) -> Bool:sourceApplication是一个可选的String值,而不是NSString。

  2. 由于sourceApplication是可选的,因此可能会返回 nil 值(在您的情况下返回 nil )。键入 nil 字符串是不安全的,因此它会崩溃。

  3. 解决方案:

    1. 在您的案例中不需要类型转换因为返回的值是字符串类型
    2. 使用可选的表单类型强制转换操作符作为?来安全地键入强制转换,即
    3. if let appString = sourceApplication { println(appString as? String) }

答案 1 :(得分:1)

这对我有用(使用FacebookSDK):

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

答案 2 :(得分:0)

我不会在操场上看到这个。可能是你建议的iOS 8错误 但是为了尝试,你可以试试

let appString : String = String(sourceApplication)

答案 3 :(得分:0)

对于FB Messenger ,这是我在AppDelegate中更好地处理的方法。大多数想法都直接来自FB IOS documentation并移植到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
}
}