Day20 Plugin 从零开始到上架 - 取得授权码(iOS)

接下来我们先切到iOS,换去处理iOS是如何取得权杖的

目标

与Androi 步骤一样,须先取得INSTAGRAM_CLIENT_ID、INSTAGRAM_CLIENT_SECRET 和 REDIRECT_URI 後,透过这些资料打开WebView,来取得短期权杖最後所需要的授权码code

iOS端

先建立一个AccessTokenViewController来取得权杖,同样须先把之前取得资讯传入,打开WebView後依照流程及能取得授权码,之後再透过AccessTokenViewModel用这些资料取得权杖(下一篇内容)

class AccessTokenViewController: UIViewController, WKUIDelegate, WKNavigationDelegate{
    
    var webView: WKWebView!
    var delegate: DismissBackDelegate?
    
    var clientId: String?
    var clientSecret: String?
    var redirectUri: String?
    
    private let viewModel = AccessTokenViewModel()
    private var cancellable: AnyCancellable? = nil
    var loadSpinner: UIActivityIndicatorView!
    
    override func loadView() {
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.navigationDelegate = self
        webView.uiDelegate = self
        view = webView
    }
    override func viewDidLoad() {
        super.viewDidLoad()

        clientId = Bundle.main.object(forInfoDictionaryKey: "INSTAGRAM_CLIENT_ID") as? String
        clientSecret = Bundle.main.object(forInfoDictionaryKey: "INSTAGRAM_CLIENT_SECRET") as? String
        redirectUri = Bundle.main.object(forInfoDictionaryKey: "REDIRECT_URI") as? String
        
        if clientId != nil && redirectUri != nil {
            let urlString = "https://www.instagram.com/oauth/authorize?client_id=\(clientId!)&redirect_uri=\(redirectUri!)&scope=user_profile,user_media&response_type=code"

            let myURL = URL(string:urlString)
            let myRequest = URLRequest(url: myURL!)
            webView.load(myRequest)
        }else{
            print("Need to set Secrets.xcconfig first.")
        }
        
        cancellable = viewModel.$state.sink { [weak self] state in
            self?.render(state)
        }
        
        loadSpinner = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.medium)
        loadSpinner.color = .gray
        webView.addSubview(loadSpinner)
        
        view = webView
        
    }
    
    override func viewDidLayoutSubviews() {
        loadSpinner.center = webView.center
    }
    
    private func render(_ state: AccessTokenViewModel.State?) {
        switch state {
        case .isLoading:
            print("isLoading")
            loadSpinner.startAnimating()
        case .failed(let error):
            print("failed \(error)")
        case .loaded(let response):
            userInfoResponse = response
            DispatchQueue.main.async {
                self.dismiss(animated: true, completion: nil)
            }
        case .none:
            print("none")
        }
    }
    
    deinit {
        delegate?.dismissBack(userInfoResponse: userInfoResponse)
    }
    
    func webView(
        _ webView: WKWebView,
        decidePolicyFor navigationAction: WKNavigationAction,
        decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        
        if let frame = navigationAction.targetFrame,
           !frame.isMainFrame {
            decisionHandler(.cancel)
            return
        }
        
        guard let url = navigationAction.request.url else {
            decisionHandler(.allow)
            return
        }
        
        if url.absoluteString.starts(with: "\(redirectUri!)?code=") {
            decisionHandler(.cancel)
            let requestURLString = url.absoluteString

            print("Response uri:", requestURLString)
            if let range = requestURLString.range(of: "\(redirectUri!)?code=") {
                let code = String(requestURLString[range.upperBound...].dropLast(2))
                viewModel.getAccessToken(clientId: clientId!, clientSecret: clientSecret!, code: code, redirectUri: redirectUri!)
            }
        }
        else {
            decisionHandler(.allow)
        }
    }
}

<<:  [NestJS 带你飞!] DAY20 - File Upload

>>:  Day20 Combine 07 - Operators 其他常用操作符

[Day 29] Leetcode 15. 3Sum (C++)

前言 到了倒数第二天啦~ 大概Day 21开始有一系列的sum题目,一直说要接续完成,终於今天又回归...

Progressive Web App 离线後备页面: 玩过 Chrome 小恐龙游戏了吗 (11)

离线後备页面介绍 (offline fallback page) 离线後备页面提供用户在网路不稳定的...

【Day12】[资料结构]-树Tree

树(Tree)属於一种非线性结构,是一种上下阶层关系,举例: 组织架构图、家族谱、赛程表等,类似一棵...

【Day 25】JavaScript ajax

AJAX 是什麽? 维基提及,AJAX 英文为 Asynchronous JavaScript An...

[Day10] 第十章-专案开启前的User Story (软件工程分享)

前言 在前面总结完laravel的技巧後 今天想要跟各位分享 开启一个专案的时候 会进行什麽步骤 U...