Skip to content

Instantly share code, notes, and snippets.

@mono0926
Last active September 20, 2018 14:21
Show Gist options
  • Save mono0926/bee85426e199b9eef23692c5050bebae to your computer and use it in GitHub Desktop.
Save mono0926/bee85426e199b9eef23692c5050bebae to your computer and use it in GitHub Desktop.
Protocol OrientedなRxSwift化したUIAlertController
import Foundation
import RxSwift
private func getAllEnumValues<T: Hashable>(_: T.Type) -> [T] {
var i = 0
let iterator = AnyIterator<T> {
let next = withUnsafeBytes(of: &i) { $0.load(as: T.self) }
if next.hashValue != i { return nil }
i += 1
return next
}
return Array(iterator)
}
public protocol AlertActionType: Hashable {
var style: UIAlertActionStyle { get }
static var values: [Self] { get }
}
extension AlertActionType {
public static var values: [Self] { return getAllEnumValues(Self.self) }
}
public protocol AlertAction {
associatedtype AType: AlertActionType
func titie(for type: AType) -> String
}
public struct Alert {
private init() {}
public struct OkAction: AlertAction {
public let okTitle: String
init(okTitle: String = okString) {
self.okTitle = okTitle
}
public func titie(for type: ActionType) -> String {
switch type {
case .ok: return okTitle
}
}
public enum ActionType: String, AlertActionType {
case ok
public var style: UIAlertActionStyle {
switch self {
case .ok: return .default
}
}
}
}
public struct OkCancelAction: AlertAction {
public let okTitle: String
public let cancelTitle: String
init(okTitle: String = okString, cancelTitle: String = cancelString) {
self.okTitle = okTitle
self.cancelTitle = cancelTitle
}
public func titie(for type: ActionType) -> String {
switch type {
case .ok: return okTitle
case .cancel: return cancelTitle
}
}
public enum ActionType: String, AlertActionType {
case
ok,
cancel
public var style: UIAlertActionStyle {
switch self {
case .ok: return .default
case .cancel: return .cancel
}
}
}
}
}
extension UIViewController {
public func prompt<Action: AlertAction>(title: String?, message: String?, action: Action) -> Observable<Action.AType> {
return Observable.create { observer in
let alertView = UIAlertController(title: title, message: message, preferredStyle: .alert)
for type in Action.AType.values {
alertView.addAction(UIAlertAction(title: action.titie(for: type), style: type.style) { _ in
observer.on(.next(type))
})
}
self.present(alertView, animated: true, completion: nil)
return Disposables.create {
alertView.dismiss(animated:false, completion: nil)
}
}
}
public func prompt(title: String?, message: String?, okTitle: String = okString, didTap: (() -> ())? = {}) {
prompt(title: title, message: message, action: Alert.OkAction(okTitle: okTitle))
.subscribeOnMainThread { event in
switch event {
case .completed: didTap?()
case .error: joinusAssert(false)
case .next:break
}
}.disposed(by: rx_disposeBag)
}
public func promptWithCancel(title: String?,
message: String?,
okTitle: String = okString,
cancelTitle: String = cancelString,
didTap: (() -> ())? = {}) {
prompt(title: title,
message: message,
action: Alert.OkCancelAction(okTitle: okTitle, cancelTitle: cancelTitle))
.subscribeOnMainThread { event in
switch event {
case .completed: break
case .error: joinusAssert(false)
case .next(let action):
switch action {
case .ok:
didTap?()
case .cancel:
break
}
}
}.disposed(by: rx_disposeBag)
}
public func prompt(error message: String?, didTap: (() -> ())? = {}) {
prompt(title: errorOccuredString, message: message)
}
}
@rkolchakov
Copy link

色々ダメだ( ´・‿・`)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment