Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to Action bright CocoaAction #40

Open
liyanhuadev opened this issue Aug 11, 2016 · 10 comments
Open

How to Action bright CocoaAction #40

liyanhuadev opened this issue Aug 11, 2016 · 10 comments
Milestone

Comments

@liyanhuadev
Copy link

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

@ashfurrow
Copy link
Member

Neat idea! What do you think, @alexvbush?

@alexvbush
Copy link
Member

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 notifications@github.com 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
#40 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAS_JbhELJp52F5Cov8AQbF-IGp6moBSks5qezq3gaJpZM4Jh4Pd
.

@alexvbush
Copy link
Member

@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 #26 in proposed toCocoaAction method.

What do you think?

@liyanhuadev
Copy link
Author

liyanhuadev commented Aug 12, 2016

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.

@ashfurrow
Copy link
Member

Looks great! That's exactly the reasoning behind the decision. What parts of your code do you think should be added to this codebase?

@alexvbush
Copy link
Member

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...

@yoavschwartz
Copy link

yoavschwartz commented Sep 5, 2017

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()
                }

@ashfurrow
Copy link
Member

Hi @yoavschwartz – I don't think there's been any progress but someone should try again using Swift 4? Anyone available?

@yoavschwartz
Copy link

yoavschwartz commented Sep 5, 2017

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
    }
}

@adamsmaka
Copy link

adamsmaka commented Sep 19, 2017

extension Action where Input == Void {
    func asCocoaAction() -> CocoaAction {
        return CocoaAction { [weak self] _ in
            return self?.execute(()).map { _ in Void() } ?? .empty()
        }
    }
}

@mosamer mosamer added this to the Release-4.0 milestone Nov 2, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants