接下来我们先切到iOS,换去处理iOS是如何取得权杖的
与Androi 步骤一样,须先取得INSTAGRAM_CLIENT_ID、INSTAGRAM_CLIENT_SECRET 和 REDIRECT_URI 後,透过这些资料打开WebView,来取得短期权杖最後所需要的授权码code
先建立一个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 21开始有一系列的sum题目,一直说要接续完成,终於今天又回归...
离线後备页面介绍 (offline fallback page) 离线後备页面提供用户在网路不稳定的...
树(Tree)属於一种非线性结构,是一种上下阶层关系,举例: 组织架构图、家族谱、赛程表等,类似一棵...
AJAX 是什麽? 维基提及,AJAX 英文为 Asynchronous JavaScript An...
前言 在前面总结完laravel的技巧後 今天想要跟各位分享 开启一个专案的时候 会进行什麽步骤 U...