Help us understand the problem. What is going on with this article?

SwiftUIでASWebAuthenticationSession

導入

新卒でSwiftはじめて3ヶ月が経ちました。あっという間です…
今回はSwiftUIでTwitter連携させたかったとき悩んだところが解消できたのでせっかくなので記事にしたいと思います。エンジニアっぽくなってきて楽しいです:relaxed:

したかったこと

  • SwiftUIのViewで作ったボタンをポチったらASWebAuthenticationSessionでTwitterとか連携するあの画面が出てきてサインインしたら閉じるやつが作りたい(語彙力)

できたやつ

AuthPresentationContextProver クラスはこちらの記事から拝借しました。ありがとうございます:clap:

import SwiftUI
import AuthenticationServices

class AuthPresentationContextProver: NSObject, ASWebAuthenticationPresentationContextProviding {
    private weak var viewController: UIViewController!

    init(viewController: UIViewController) {
        self.viewController = viewController
        super.init()
    }

    func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
        return viewController?.view.window! ?? ASPresentationAnchor()
    }
}

struct RenkeiButton: View {
    @State var session: ASWebAuthenticationSession?
    @State var presentationContextProvider: AuthPresentationContextProver?
    // リクエストトークンもらうマン
    func postOAuthRequestToken(success: 成功した時のHandler, failure: 失敗した時)
    // リクエストトークンから連携画面表示するマン
    func authStart(requestToken: とーくん) {
        let queryUrl = tokenで作る
        let callbackURLScheme = "ちょめちょめ"

        self.session = ASWebAuthenticationSession(url: queryUrl, callbackURLScheme: callbackURLScheme, completionHandler: { (url, error) in
            // callbackURLScheme + parameters のURLが帰ってくるのでちょめちょめする
            // キャンセルの時はエラーになる
        })
        let presentationContextProvider = AuthPresentationContextProver(viewController: UIHostingController(rootView: self))
        self.session?.presentationContextProvider = presentationContextProvider
        self.presentationContextProvider = presentationContextProvider
        self.session?.start()
    }

    var body: some View {
        Button(action: {
            self.postOAuthRequestToken(
                success: { (requestToken, response) in
                    self.authStart(token: requestToken)
                }, failure: { (error) in
                })
        }, label: {
            Text("連携や!!")
        })
    }
}

悩んでたとこ

iOS13ではpresentationContextProviderASWebAuthenticationPresentationContextProvidingとかいうProtocolを満たすNSObjectを設定をしていないと連携画面のモーダルが出ません…
Controllerベースで作れば簡単にできるけど…ってなってた時に@simorgh3196さんの記事を発見して、もしやUIHostingControllerで渡してやれば同じようにできる…?となってうまくいった次第です

UIHostingControllerで渡してやらなくても…

要は現在のwindowが知りたいので@shizさんのこちらの記事を参考に…

class AuthPresentationContextProver: NSObject, ASWebAuthenticationPresentationContextProviding {
    @Environment(\.window) var window

    func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
        return window ?? ASPresentationAnchor()
    }
}

とすることもできます。(この書き方いいんでしょうか…)

おわりに

SwiftUI、iOS13 まだまだBeta段階ですのでこの書き方もいずれ使えなくなるかもなので注意です!

SwiftUIたのしい!

devdazy
大学院19卒から初心者でiOSエンジニアに挑む田舎者です。
https://github.com/dazy1030
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした