touren / twitter-kit-ios

Twitter Kit is a native SDK to include Twitter content inside mobile apps.
Apache License 2.0
110 stars 80 forks source link

Login window will not dismiss in iOS13 #10

Closed bobbydank closed 4 years ago

bobbydank commented 4 years ago

I am trying to implement a Twitter login in a new app I am working on using TwitterKit. Everything is working on iOS 11 and iOS 12, but there seems to be problem with iOS 13. After logging in, the webview that logs in is supposed to dismiss, but it just spins at this current screen and does not dismiss. In fact, the loginCompletion it's self never fires, because neither of the print statements never fire. I think it has something to do with the modal presentation.

Expected behavior

Just as it reacts in iOS versions before 13. The login button is created. The user clicks it, the login window should appear, the user will login and the window will dismiss and completion code will run.

Actual behavior

Login button is clicked, the window appears and user logs in. However, the window does not dismiss. The login to Twitter appears to be successful. However the window doesn't automatically dismiss and the completion code does not run.

Steps to reproduce the behavior

This is right out of the box. I used pods to install the kit. Again. Everything works fine in versions of iOS earlier than 13. I posted an issue about this here: https://stackoverflow.com/questions/59653607/twitterkit-login-webview-not-dismissing-in-ios-13

weitieda commented 4 years ago

I have the same issue on Xcode 11.

I've noticed that in Twitter Developer account, the twitter app's callback URL should be set twitterkit-<my_key>, but still doesn't work...

Basically, the logInCompletion never got called... I've spend almost a day on this...

bobbydank commented 4 years ago

I have the callback url set to the same scheme. Won't dismiss.

weitieda commented 4 years ago

I have the callback url set to the same scheme. Won't dismiss.

I found iOS 13 sometimes have strange bugs. I'm wondering will this be iOS 13 related.

bobbydank commented 4 years ago

I'm 99% sure its iOS13. I fired up the code in an iOS 12 and iOS 11 simulator and everything worked fine. I am betting it has to do with the modal presentation.

weitieda commented 4 years ago

I'm 99% sure its iOS13. I fired up the code in an iOS 12 and iOS 11 simulator and everything worked fine. I am betting it has to do with the modal presentation.

I just tried another project with TwitterKit(development target 12.1), setup my Twitter App key and secret, that project works fine, which proved at least my Twitter app's setting is correct. But come back to iOS 13, Xcode 13.1, the login modal just doesn't dismiss and the login callback never got called.

So I'm pretty sure as well it's iOS13's problem.

HackingGate commented 4 years ago

Which window won't dismiss? SFSafariViewController or WKWebView?

I have a fork based on this fork that completely removed WKWebView. And my login window will dismiss.

If it is confirmed as a WKWebView problem. I will create a pull request.

weitieda commented 4 years ago

Which window won't dismiss? SFSafariViewController or WKWebView?

I have a fork based on this fork that completely removed WKWebView. And my login window will dismiss.

If it is confirmed as a WKWebView problem. I will create a pull request.

https://stackoverflow.com/questions/59653607/twitterkit-login-webview-not-dismissing-in-ios-13

There's a screenshot here

touren commented 4 years ago

@bobbydank @weitieda Could you please try the DemoApp in this project to see if having the same issue and are you guys using pod 'TwitterKit5' v5.0.3

Maybe take a look into #9 will help.

Tried DemoApp in Xcode 11.3.1 & simulator 13.3, can't reproduce the issue.

bobbydank commented 4 years ago

Yes. I used pod to install and it installed v5.0.3. The demo app worked, but on a new app created in xcode 11.3.1, the viewcontroller will not dismiss.

bobbydank commented 4 years ago

Here is a quick project I created for testing this. Webview still did not dismiss.

https://github.com/bobbydank/TwitterKit5Test/

You'll need to input your own key/secret into the info.plist and the appdelegate.swift

HackingGate commented 4 years ago

@bobbydank Remove SceneDelegate (or create project with Xcode 10) is a workaround to fix the issue.

The thread here seems to be related. https://forums.developer.apple.com/thread/121990

bobbydank commented 4 years ago

Thanks @HackingGate I had that thought, I haven't tried it yet, and I bet that would fix the problem. The kit should still be updated to Xcode 11 because I doubt SceneDelegate is going away.

touren commented 4 years ago

@bobbydank Thank you for mocking up a test project. It turns out that the test project, https://github.com/bobbydank/TwitterKit5Test/, uses SceneDelegate included in iOS13 and it blocks func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool.

A quick workaround is adding below function to SceneDelegate

    func scene(_ scene: UIScene,
               openURLContexts URLContexts: Set<UIOpenURLContext>) {
        if let context = URLContexts.first {
            TWTRTwitter.sharedInstance().application(UIApplication.shared, open: context.url, options: [UIApplication.OpenURLOptionsKey.sourceApplication: context.options.sourceApplication as Any])
        }
    }

More detail on SceneDelegate in iOS13

Will fix the TwitterKit later for the SceneDelegate issue.

bobbydank commented 4 years ago

That fixed it!! Thanks so much Touren!

touren commented 4 years ago

After upgraded to TwitterKit5 v5.1.0, you can add one line to scene:openURLContexts inside the scene delegate.

    func scene(_ scene: UIScene,
               openURLContexts URLContexts: Set<UIOpenURLContext>) {
        TWTRTwitter.sharedInstance().scene(scene, openURLContexts: URLContexts)
    }
LuisAcerv commented 4 years ago

How this would work on react native?

Mani-gloify commented 4 years ago

when I tried to login in simulator(iOS 13.5) it works fine but testing device(iOS 13.5) after dismissing app is getting crashed. can anyone tell me quick fix for this or how can we perform twitter login in browser/webview even twitter app is installed in iPhone ?

Fatal Exception: NSInvalidArgumentException -[NSNull hasPrefix:]: unrecognized selector sent to instance 0x1f76d7c00 hidden#5086

AAlboghdady commented 3 years ago

when I tried to login in simulator(iOS 13.5) it works fine but testing device(iOS 13.5) after dismissing app is getting crashed. can anyone tell me quick fix for this or how can we perform twitter login in browser/webview even twitter app is installed in iPhone ?

Fatal Exception: NSInvalidArgumentException -[NSNull hasPrefix:]: unrecognized selector sent to instance 0x1f76d7c00 hidden#5086

Did you solve this crash? Or did you find a solution for this issue?

KiranYechuri commented 3 years ago

when I tried to login in simulator(iOS 13.5) it works fine but testing device(iOS 13.5) after dismissing app is getting crashed. can anyone tell me quick fix for this or how can we perform twitter login in browser/webview even twitter app is installed in iPhone ? Fatal Exception: NSInvalidArgumentException -[NSNull hasPrefix:]: unrecognized selector sent to instance 0x1f76d7c00 hidden#5086

Did you solve this crash? Or did you find a solution for this issue?

No I didn't find any solution for that. Do you have any solution for this?

Satteganesh commented 2 years ago

@KiranYechuri @AAlboghdady @Mani-gloify if twitter kit version below 5 version , we are facing that issue, try to update pod with TwitterKit5 After install TwitterKit5 pod , if version is above 13 or above use sceneDelegate method like

 func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    guard let url = URLContexts.first?.url else {
        return
    }

        if let context = URLContexts.first {
                TWTRTwitter.sharedInstance().scene(scene, openURLContexts: URLContexts)
            }

}

// In loggin button action write your code like func loginTwitter() { TWTRTwitter.sharedInstance().logIn { (session, error) -> Void in

        if (session != nil) {
           let userId = session?.userID ?? ""
           let authToken = session?.authToken ?? ""
           let authTokenSecret = session?.authTokenSecret ?? ""
           let userName = session?.userName ?? ""
           } else {
           // your alert error

} } }