์
๋ฐ์ดํธ ํ Pod weblogin์ด ios 10 ๋ฒ์ ์์ ์ปดํ์ผ๋์ง ์์์ต๋๋ค.
11.0 ๋ฒ์ ์ ios๋ก ๋ณ๊ฒฝํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ํ์๋ฉ๋๋ค.
InstagramLoginWebView
์์ฑ์ ์ฌ์ฉํ์ธ์.InstagramLoginWebViewProtocol
ํด๋ก์ ์์ฑ์ ์ฌ์ฉํ์ธ์.InstagramLoginWebViewDelegate๋ฅผ InstagramLoginWebViewProtocol๋ก ๋ณ๊ฒฝํ์ ๋:
๋ด ์ฝ๋:
ํด๋์ค LoginViewController: UIViewController {
var loginWebView: InstagramLoginWebView! = nil
override func viewDidLoad() {
super.viewDidLoad()
loginWebView = InstagramLoginWebView(frame: self.view.frame)
self.view.addSubview(loginWebView!)
loginWebView?.loginDelegate = self **-- Cannot assign value of type 'LoginViewController' to type 'InstagramLoginWebViewDelegate?'**
self.loginWebView?.loadInstagramLogin(isNeedPreloadForCookieSync: true) **--Argument passed to call that takes no arguments**
}
}
extension LoginViewController : InstagramLoginWebViewProtocol { --'InstagramLoginWebViewProtocol'์ ์ฌ์ฉํ๋ ค๋ฉด 'LoginViewController'๊ฐ 'UIView'์์ ์์๋์ด์ผ ํฉ๋๋ค.
func userLoggedSuccessfully() {
print("User Logged Successfully")
DispatchQueue.main.async {
self.loginWebView.removeFromSuperview()
}
}
์๋ ํ์ธ์ @ ์ดํํธ
InstagramLoginWebView
๋ ์ง๋ ์
๋ฐ์ดํธ์์ ๋ง์ด ๋ณ๊ฒฝ๋์์ผ๋ฉฐ iOS 10.*
๋ํ ์ง์์ ๋นํธํ์ฑ์ผ๋ก ์ธํด ์ค๋จ๋์ด์ผ ํ์ต๋๋ค.
loginDelegate
์ ๋ ์ด์ ์ ์๋์ง ์์ง๋ง ์ฌ์ ํ ์๋ํฉ๋๋ค.
์ต์ํ ๋์์ ์ป์ผ๋ ค๋ฉด loginWebView
์ ๋ค์ ์์ฑ์ ์ค์ ํ๊ธฐ
didReachEndOfLoginFlow
๋ redirected
์ฒ๋ผ ํธ์ถ๋๋ _ํด๋ก์ _์
๋๋ค.didSuccessfullyLogIn
๋ _delegate_์ userLoggedSuccessfully()
๋์ฒดํ๋ _closure_์
๋๋ค.completionHandler
๋ _delegate_์ webViewFinishedToLoadUser(sessionChache:handler:)
๋์ฒดํ๋ _closure_์
๋๋ค.1.7.*
๋ํ ์
๋ฐ์ดํธ๋ ์ฝ๋์
๋๋ค.
class LoginViewController: UIViewController {
var loginWebView: InstagramLoginWebView!
override func viewDidLoad() {
super.viewDidLoad()
loginWebView = InstagramLoginWebView(frame: self.view.frame,
didSuccessfullyLogIn: { [weak self] in DispatchQueue.main.async { self?.loginWebView.removeFromSuperview() }},
completionHandler: { sessionCache, handler in /* do whaterver you need to */ })
view.addSubview(loginWebView)
loginWebView.loadInstagramLogin()
}
}
๋ฐ๋ผ์ ํ์ฅ InstagramLoginWebViewDelegate๋ฅผ InstagramLoginWebViewProtocol๋ก ๋ณ๊ฒฝํ๊ณ 'InstagramLoginWebViewProtocol'์ ์ฌ์ฉํ๋ ค๋ฉด 'LoginViewController'๊ฐ 'UIView'์์ ์์๋์ด์ผ ํฉ๋๋ค.
์ํธ:
ํ์ฅ LoginViewController : InstagramLoginWebViewDelegate {
func userLoggedSuccessfully() {
print("User Logged Successfully")
}
func webViewFinishedToLoadUser(sessionCache: SessionCache, handler: APIHandlerProtocol) {
print("Loading user with sessioncache is successful")
do{
let encoder = JSONEncoder()
let data = try encoder.encode(sessionCache)
let sessionCacheString = String(data: data, encoding: .utf8)
}catch {
print("Whoops, an error occured: \(error)")
}
}
InstagramLoginWebViewProtocol
์ค์ํด์๋ ์๋ฉ๋๋ค .
internal
ํ์ํ์ง ์์ ๋ด ์๋ชป์
๋๋ค. ์ฃ์กํฉ๋๋ค.
์ด๊ฒ์ด ํ์ํ ๋ชจ๋ ์ฝ๋์
๋๋ค. ์๋์ InstagramLoginWebViewProtocol
. ์๋์ InstagramLoginWebViewDelegate
.
import UIKit
import SwiftyInsta
class LoginViewController: UIViewController {
var loginWebView: InstagramLoginWebView!
override func viewDidLoad() {
super.viewDidLoad()
loginWebView = InstagramLoginWebView(frame: view.frame,
didReachEndOfLoginFlow: nil,
didSuccessfullyLogIn: { [weak self] in
// I would actually put this in `didReachEndOfLoginFlow`,
// so the user never sees their timeline blinking.
DispatchQueue.main.async {
self?.loginWebView.removeFromSuperview()
}
},
completionHandler: { sessionCache, _ in
print("Loading user with sessioncache is successful")
do {
let encoder = JSONEncoder()
let data = try encoder.encode(sessionCache)
let sessionCacheString = String(data: data, encoding: .utf8)
} catch {
print("Whoops, an error occured: \(error)")
}
})
view.addSubview(loginWebView)
loginWebView.loadInstagramLogin()
}
}
@sbertix ๋ชจ๋ ๋์์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค.
ํ์ง๋ง ์ธ์คํ๊ทธ๋จ ๋ก๊ทธ์ธ ํ์ด์ง๊ฐ ๋ก๋๋์ง ์๊ณ ํ๋ฉด์ ํฐ์ ํ์ด์ง๋ง ํ์๋ฉ๋๋ค.
์ด๊ฒ์ด ํ์ํ ๋ชจ๋ ์ฝ๋์ ๋๋ค. ์๋์
InstagramLoginWebViewProtocol
. ์๋์InstagramLoginWebViewDelegate
.
@effecttwins ๋ ์์์ ์์ฑํ ์ฝ๋๋ฅผ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์ต๋๋ค. loadInstagramLogin()
๋ฅผ ํธ์ถํ๋ ๊ฒ์ ์์ง ๋ง์ญ์์ค.
๋ง ๊ทธ๋๋ก ์ด๋ฏธ ๊ตฌํ๋์ด ์์ต๋๋ค ๐
ํจ๊ณผ๊ฐ์๋ค
๋ค, ๋ชจ๋ ์ฝ๋๋ฅผ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ๊ณ loadInstagramLogin์ ํธ์ถํ์ต๋๋ค. :)
InstagramLoginWebViewProtocol ๋ฐ InstagramLoginWebViewDelegate๋ ์ญ์ ๋จ
์ฝ์์์ ์ด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ด ํ๋ก์ ํธ์ ๊ด๋ จ์ด ์๋์ง ํ์คํ์ง ์์ต๋๋ค.
์๋น์ค com.apple.WebKit.Networking์ ์ ํธ๋ฅผ ๋ณด๋ผ ์ ์์: 113: ์ง์ ๋ ์๋น์ค๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.
์ฃ์กํฉ๋๋ค. ๋ด ์ฝ๋์์ loginWebView
๋ฅผ view
์ ์ถ๊ฐํ ์ ์ด ์์ต๋๋ค.
์์ ํ์ต๋๋ค. ๋ค์ ํ์ธํ์ญ์์ค. ์ด์ @effecttwins์์ ์๋ํด์ผ ํฉ๋๋ค.
๋น์ ์ ๊ต์ฅํฉ๋๋ค @sbertix
์ง๊ธ ์๋ ์ค์
๋๋ค
๋ชจ๋ ๋์ ์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค
์๋ ํ์ธ์ @sbertix
MVVM ํจํด์ ๋ฐ๋ฅด๊ณ ์๋๋ฐ ๋ด ๋ณด๊ธฐ์ ๋ด viewController๊ฐ ๋ค๋ฅธ ํ์ผ์ ์์ผ๋ฉด ์ด๋ป๊ฒ ๋ฉ๋๊น? ๋ณด๊ธฐ๋ ๋ณด๊ธฐ ์ปจํธ๋กค๋ฌ์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด์ง ์์์ผ ํฉ๋๋ค. InstagramLoginWebView ์ด๊ธฐํ ํ didSuccessfullyLogIn
๊ธฐ๋ฅ์ ์ ๊ทผํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
๋น์ ์ ํ ํ์๊ฐ ์์ต๋๋ค init
InstagramLoginWebView
์ didSuccessfullyLogIn
(์ด๊ฒ์ ์ ํ ์ฌํญ์
๋๋ค).
๊ทธ๋ฆฌ๊ณ ๋ค๋ฅธ _closures_๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋: ์ผ๋จ ๊ฐ์ง๊ณ ์์ผ๋ฉด ๋จ์ํ ๋ค๋ฅธ ๊ฐ์ ํ ๋นํ ์ ์์ต๋๋ค.
@anonrig
์ฌ์ญค๋ด๋ ๋ ๊น์? ์๋ฅผ ๋ค์ด์ฃผ์ค ์ ์๋์? @sbertix :)
ํ์ ํ๋. ์ฝ๋์ ๋ํ ์ถ๊ฐ ์ ๋ณด๋ฅผ ๋ณด๋ผ ์ ์์ต๋๊น? ์๋ฅผ ๋ค์ด ๋ชจ๋ธ๊ณผ ๋ทฐ๊ฐ ์ค์ ๋๋ ๋ฐฉ์์ ๋๋ค.
๊ทธ๋ ๋ฌผ๋ก !
1.7.x ์ด์ ์๋ delegates
์ฌ์ฉํ์ฌ ViewController ์์ค์์ ๋ก๊ทธ์ธ ์ฑ๊ณต ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ์ต๋๋ค.
๋ณด๊ธฐ ๋ณด๊ธฐ:
final class LoginWebView: UIView {
// MARK: - Properties
var bag = DisposeBag()
private(set) lazy var webView: InstagramLoginWebView = InstagramLoginWebView(frame: UIScreen.main.bounds)
private(set) lazy var closeButtonLabel: UILabel = {
let label: UILabel = .create(text: "Close".localized(), numberOfLines: 1, textAlignment: .center, textColor: .white, font: .light(size: 16))
label.isUserInteractionEnabled = true
return label
}()
private(set) lazy var closeButtonBarItem: UIBarButtonItem = UIBarButtonItem(customView: closeButtonLabel)
// MARK: - Initialization
init() {
super.init(frame: .zero)
[webView].forEach(addSubview(_:))
webView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
๋ณด๊ธฐ ์ปจํธ๋กค๋ฌ ์:
final class LoginWebViewController: UIViewController, View, ErrorDisplayer {
// MARK: - Properties
private lazy var viewSource = LoginWebView()
private(set) var bag: DisposeBag
private(set) var viewModel: LoginWebViewModel
private(set) var completionObservable = PublishSubject<(SessionCache?, APIHandlerProtocol?)?>()
// MARK: - Initialization
init() {
bag = DisposeBag()
viewModel = LoginWebViewModel()
super.init(nibName: nil, bundle: nil)
bindErrorHandling()
observeDatasource()
}
// MARK: - Life cycle
override func loadView() {
view = viewSource
view.backgroundColor = .white
}
override func viewDidLoad() {
super.viewDidLoad()
viewSource.webView.loginDelegate = self
viewSource.webView.loadInstagramLogin(isNeedPreloadForCookieSync: true)
// viewSource.webView.didSuccessfullyLogIn
configureNavBar(with: "Login".localized(), prefersLargeTitle: false)
navigationItem.rightBarButtonItem = viewSource.closeButtonBarItem
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
LoginWebViewModel
์ด ๋ฌด์์ธ์ง ์ ํํ ๋ชจ๋ฅด์ง๋ง... ๋ชฉํ๊ฐ ๋ชจ๋ ๊ฒ์ completeObservable
๋ฃ๋ ๊ฒ์ด๋ผ๋ฉด ๊ฐ๋จํ ํ ์ ์์ต๋๋ค.
final class LoginWebView: UIView {
// MARK: - Properties
var bag = DisposeBag()
private(set) lazy var webView: InstagramLoginWebView = InstagramLoginWebView(frame: UIScreen.main.bounds, completionHandler: nil)
private(set) lazy var closeButtonLabel: UILabel = {
let label: UILabel = .create(text: "Close".localized(), numberOfLines: 1, textAlignment: .center, textColor: .white, font: .light(size: 16))
label.isUserInteractionEnabled = true
return label
}()
private(set) lazy var closeButtonBarItem: UIBarButtonItem = UIBarButtonItem(customView: closeButtonLabel)
// MARK: - Initialization
init() {
super.init(frame: .zero)
[webView].forEach(addSubview(_:))
webView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
final class LoginWebViewController: UIViewController, View, ErrorDisplayer {
// MARK: - Properties
private lazy var viewSource = LoginWebView()
private(set) var bag: DisposeBag
private(set) var viewModel: LoginWebViewModel
private(set) var completionObservable = PublishSubject<(SessionCache?, APIHandlerProtocol?)?>()
// MARK: - Initialization
init() {
bag = DisposeBag()
viewModel = LoginWebViewModel()
super.init(nibName: nil, bundle: nil)
bindErrorHandling()
observeDatasource()
}
// MARK: - Life cycle
override func loadView() {
view = viewSource
view.backgroundColor = .white
}
override func viewDidLoad() {
super.viewDidLoad()
viewSource.webView.completionHandler = { [weak self] cache, handler in
self?.completionObservable.accept((cache, handler))
}
viewSource.webView.loadInstagramLogin()
// viewSource.webView.didSuccessfullyLogIn
configureNavBar(with: "Login".localized(), prefersLargeTitle: false)
navigationItem.rightBarButtonItem = viewSource.closeButtonBarItem
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
InstagramLoginWebView
init(frame:)
๋ฅผ init(frame:completionHandler:)
๋ก ๋ณ๊ฒฝํ ๋ค์ completionHandler
๋ฅผ ์
๋ฐ์ดํธํ์ฌ ์ฃผ์ ์ ๊ฐ์ ํธ์ํ์ต๋๋ค.
@sbertix ๊ฐ์ฌ