How to Action bright CocoaAction
hi, thank you for you library.
i have a question:
let loadAction: Action<Void, String>
observer result:
loadAction.elements.subscribeNext { (result) in // do something }
and i can use rx_action
btn.rx_action = viewModel.loadAction.toCocoaAction()
What I want to do toCocoaAction
Neat idea! What do you think, @alexvbush?
I like the idea! As far as I recall CocoaAction's signature is Action<Void, Void> ... We need to figure out how to convert to that (I believe we can use that mapping trick you used Ash). I'll get back online tonight and look at it again On Thu, Aug 11, 2016 at 8:07 AM Ash Furrow [email protected] wrote:
Neat idea! What do you think, @alexvbush https://github.com/alexvbush?
— You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/RxSwiftCommunity/Action/issues/40#issuecomment-239190159, or mute the thread https://github.com/notifications/unsubscribe-auth/AAS_JbhELJp52F5Cov8AQbF-IGp6moBSks5qezq3gaJpZM4Jh4Pd .
@ashfurrow did you create CocoaAction as a typealias to Action<Void, Void> because that was the only way to use it in public var rx_action: CocoaAction? uibutton extension?
At first I thought - why do we even need CocoaAction if we could just use Action<Input, Element> where Input and Element are generics. But it seems like we can't do something like this in Swift:
public extension UIButton<Input, Element> {
....
public var rx_action: Action<Input, Element>? {
.....
}
}
the compiler complains with cannot specify non-generic type UIButton....
Also I found that there is a proposal for generic typealias for Swift 3 https://github.com/apple/swift-evolution/blob/master/proposals/0048-generic-typealias.md Looks cool and will be useful if it will be included.
If I'm correct that we can't have generics in UIButton extension than I think our best bet is to do something like what you did here https://github.com/RxSwiftCommunity/Action/issues/26 in proposed toCocoaAction method.
What do you think?
hey, i found a way, in ReactiveCocoa https://github.com/ReactiveCocoa/ReactiveCocoa/blob/master/ReactiveCocoa/Swift/ObjectiveCBridging.swift
public protocol ActionProtocol {
associatedtype Input
associatedtype Element
var action: Action<Input, Element> { get }
}
extension Action: ActionProtocol {
public var action: Action<Input, Element> {
return self
}
}
public extension ActionProtocol where Input == Void {
public func toCocoaAction() -> CocoaAction {
let voidAction = Action<Void, Void> { _ in
return Observable.create({ (observer) -> Disposable in
let dispose = self.action.execute(Void()).subscribe({ (event) in
switch event {
case .Next(_):
observer.onNext(Void())
case .Completed:
observer.onCompleted()
case .Error(let error):
observer.onError(error)
}
})
return dispose
})
}
return voidAction
}
}
So, i can use like this:
let requestAction = Action<Void, String> { () -> Observable<String> in
return Observable.just("request data") // mock
}
button.rx_action = requestAction.toCocoaAction()
requestAction.elements.subscribeNext { (result) in
print(result)
}
thank you for your help.
Looks great! That's exactly the reasoning behind the decision. What parts of your code do you think should be added to this codebase?
Spent some time looking into this the other day. It's so unfortunate that we can't have generics in protocols and extensions and have to do something like @liyanhuadev did...
Hi, is there anything new on this? I really enjoy using Action, but I would like a button to be able to hold an action that produces elements. But I cannot find a way to implement a toCocoaAction, or make the UIButton hold anything but a CocoaAction. How do you get around this? in the mean time I had to do
CocoaAction { _ in
self?.vm.onCreateAccountTap.execute()
return .just()
}
Hi @yoavschwartz – I don't think there's been any progress but someone should try again using Swift 4? Anyone available?
After talking to @fpillet, for future reference this is the best solution I came to, if anyone is facing the same problem
extension Reactive where Base: UIButton {
func bindAction<Output>(_ action: Action<Void,Output>) {
var button = base
let cocoaAction = CocoaAction {
action.execute()
return .just()
}
button.rx.action = cocoaAction
}
}
extension Action where Input == Void {
func asCocoaAction() -> CocoaAction {
return CocoaAction { [weak self] _ in
return self?.execute(()).map { _ in Void() } ?? .empty()
}
}
}