简体   繁体   中英

SwiftUI and UIKit interfacing with UIViewController requirements in older APIs

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.

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()
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM