3

The scenario:

I have a simple SwiftUI view that looks like this:

struct AuthView: View { var body: some View { VStack { Button(action: handleLogin) { Text("Login to twitter") } } } private func handleLogin() { // do login stuff here } } 

Now ideally in the handleLogin function I would simply perform an OAuth request and handle logging in, etc. However, I am using a library I found on GitHub for demo purposes.

This library has a method authorize(callBackUrl: URL, presentingController: UIViewController) which when called presents a safari controller which allows the user to login to twitter. However, to call authorize you need to pass in a controller which conforms to SFSafariViewControllerDelegate. From my current basic understanding is that View type from SwiftUI isn't a view controller and moreover could not conform to the SFSafariViewControllerDelegate since it's a struct.

I looked at the Interfacing with UIKit tutorial from Apples site, and they seem to create a UIViewControllerRepresentable type and then from the View type return this "controller" in the body of the View. This allows them to use PageViewController from UIKit. However, this isn't entirely the use case I have or need. I simply need to be able to somehow convert my simple View into a UIViewController. Would UIHostingController be the thing to use here, and if so, how would this dependency be injected or should the view even know/use a controller?

Mostly my confusion lies on not yet knowing what the best practices are for SwiftUI. The View type seems to replace the use of UIViewController in UIKit, but then how does the conversion work when interfacing with UIKit?

If anyone has any ideas or would like to discuss this I'd appreciate it! Thanks.

1
  • Probably this is a situation where the library you are using needs to change; Does it need a UIViewController or does it need an SFSafariViewControllerDelegate? Asking for the former that conforms to the latter when it just needs the latter is probably a poor design. Commented Jun 7, 2019 at 2:16

1 Answer 1

2

I'm pretty sure there is a better way to solve this, but you might get inspiration with the following.

Just to give you some context. I'm creating a fast prototype to implement Uber Authorization and I achieved it like this:

// // ContentView.swift // // Created by Daniel Tello on 05/11/19. // Copyright © 2019 Daniel Tello. All rights reserved. // import SwiftUI import UberCore struct ContentView: View { var body: some View { VStack { Button(action: uberLogin) { Text("Uber") } } } } func uberLogin() { let scopes: [UberScope] = [.profile, .places, .request] let presentingView = UIApplication.shared.windows.last?.rootViewController let loginManager = LoginManager(loginType: .native) loginManager.login(requestedScopes: scopes, presentingViewController: presentingView) { (accessToken, error) -> () in if accessToken != nil { NSLog("Got an AccessToken!") } else { // Error if let error = error { NSLog(error.localizedDescription) } else { NSLog("An Unknown Error Occured") } } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.