Coder Social home page Coder Social logo

action's Introduction

CI

Action

This library is used with RxSwift to provide an abstraction on top of observables: actions.

An action is a way to say "hey, later I'll need you to subscribe to this thing." It's actually a lot more involved than that.

Actions accept a workFactory: a closure that takes some input and produces an observable. When execute() is called on the action, the workFactory gets passed this parameter and the action subscribes to the observable that gets returned.

An action:

  • Can only be executed while "enabled" (true if unspecified).
  • Only executes one thing at a time.
  • Aggregates next/error events across individual executions.

Oh, and it has this really Swift thing with UIButton that's pretty cool. It'll manage the button's enabled state, make sure the button is disabled while your work is being done, all that stuff ๐Ÿ‘

Usage

You have to pass a workFactory that takes input and returns an Observable. This represents some work that needs to be accomplished. Whenever you call execute(), you pass in input that's fed to the work factory. The Action will subscribe to the observable and emit the Next events on its elements property. If the observable errors, the error is sent as a Next even on the errors property. Neat.

Actions can only execute one thing at a time. If you try to execute an action that's currently executing, you'll get an error. The executing property sends true and false values as Next events.

action: Action<String, Bool> = Action(workFactory: { input in
    return networkLibrary.checkEmailExists(input)
})

...

action.execute("[email protected]")

Notice that the first generic parameter is the type of the input, and the second is the type of observable that workFactory creates. You can think of it a bit like the action's "output."

You can also specify an enabledIf parameter to the Action initializer.

let validEmailAddress = emailTextField.rx.text.map(isValidEmail)

action: Action<String, Bool> = Action(enabledIf: validEmailAddress, workFactory: { input in
    return networkLibrary.checkEmailExists(input)
})

Now execute() only does the work if the email address is valid. Super cool!

(Note that enabledIf isn't the same as the enabled property. You pass in enabledIf and the action uses that (combined with its current executing state) to determine if it's currently enabled.)

What's really cool is the UIButton extension. It accepts a CocoaAction, which is just Action<Void, Void>.

button.rx.action = action

Now when the button is pressed, the action is executed. The button's enabled state is bound to the action's enabled property. That means you can feed your form-validation logic into the action as a signal, and your button's enabled state is handled for you. Also, the user can't press the button again before the action is done executing, since it only handles one thing at a time. Cool. Check out this code example of CocoaAction in action.

If you'd like to use Action to do a complex operation such as file download with download progress report (to update progress bar in the UI for example) you'd use Action<Void, Int> instead of CocoaAction. Out of the box CocoaAction can't emit progress values, your own Action<Void, Int> will do that. For details refer to this article.

If your scenario involves many buttons that needs to trigger the same Action providing different input, you can use bindTo on each UIButton with a closure that returns correct input.

let button1 = UIButton()
let button2 = UIButton()

let action = Action<String, String> { input in
    print(input)
    return .just(input)
}
button1.rx.bindTo(action) { _ in return "Hello"}
button2.rx.bindTo(action) { _ in return "Goodbye"}

button1 and button2 are sharing the same Action, but they are feeding it with different input (Hello and Goodbye that will be printed for corresponding tap).

A more complex use case can be a single action related to a UIViewController that manages your navigation, error handling and loading state. With this approach, you can have as many UIButtons (or UIBarButtonItems) as you want and subscribe to executing, errors, elements and completions once and in a single common place.

There's also a really cool extension on UIAlertAction, used by UIAlertController. One catch: because of the limitations of that class, you can't instantiate it with the normal initializer. Instead, call this class method:

let action = UIAlertAction.Action("Hi", style: .default)

Installing

CocoaPods

Just add the line below to your Podfile:

pod 'Action'

Then run pod install and that'll be ๐Ÿ‘Œ

Carthage

Add this to Cartfile

github "RxSwiftCommunity/Action" ~> 5.0.0

If you are using RxSwift 3.2.0 or below, Use Action ~2.2.0 instead!

then run

> carthage update

Thanks

This library is (pretty obviously) inspired by ReactiveCocoa's Action class. Those developers deserve a lot of thanks!

License

MIT obvs.

Permissive licenses are the only licenses permitted in the Q continuum.

action's People

Contributors

ashfurrow avatar bobgodwinx avatar carlosypunto avatar chasercn avatar chipp avatar cruisediary avatar dangthaison91 avatar econa77 avatar floskel avatar fpillet avatar freak4pc avatar funzin avatar gin0606 avatar ishkawa avatar justinevans-ux avatar justinswart avatar lucianopalmeida avatar mau888 avatar mosamer avatar nanoxd avatar nflahavan avatar nnsnodnb avatar sharplet avatar stefanomondino avatar sunshinejr avatar toshi0383 avatar toshinarin avatar wberger avatar wenbingzuo avatar yuzushioh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

action's Issues

Versioning

Currently

The current version of Action reads s.version = "3.3.0-alpha.1

Required

A clear strategy on how to better do the versioning of Action if I may suggest we could follow the RxSwift versioning since we are depending on it as our main dependency framework

Actions defaults to enabled=false

I have updated to 2.1.0 recently and im experiencing that some actions not enabled by default.
This means i immediately get an error notEnabled, but the work factory seems to execute. Theres never a call back to my subscription on elements.

I looked around in the recent changes and this seems peculiar:

    public init(
        enabledIf: Observable<Bool> = Observable.just(true),
        workFactory: @escaping WorkFactory) {
        
        self._enabledIf = enabledIf
        self.workFactory = workFactory

        let enabledSubject = BehaviorSubject<Bool>(value: false)
        enabled = enabledSubject.asObservable()

I'm not 100% sure whats going on, but it seems to me _enabledIf defaults true and enabled defaults to false?

Podspec not updated for 2.3.0

Can we please get the podspec pushed to the main specs repo? Looks like this got lost in the update shuffle again.

Move to compositional approach

@kzaher has a great idea for building this by composing existing functionality, which sounds ๐Ÿ’ฏ

I'm not sure if I have time to do it right now, since I just want to get my project compiling again ๐Ÿ˜ฌ But I think the external API we have now is well-defined and we should definitely implement his suggested approach as soon as possible.

Use releases as changelogs

Thanks for putting the effort into this ๐Ÿ˜€.

I see that currently Changelog.md is used to track changes. Since tags are also being used, could the same data be put into the releases tab? That way, it would make it easy for users to know where to go to without looking for the changelog file. Similar to RxSwift

requires RxBlocking @ runtime!

I cannpt add Action to my project using Carthage

I'm getting

dyld: Library not loaded: @rpath/RxBlocking.framework/RxBlocking

Referenced from: ...app/Frameworks/Action.framework/Action
Reason: image not found

at runtime and obviously RxBlocking is Test library

NOTE: adding RxBlocking fixed runtime issue but I cannot push the binary to itunesconnect

Download Progress

Hi @ashfurrow, thanks for doing all this great work! Trying to use Action in my current project and have gotten into a bit of a jam - I have a download button that will pull several files from our backend and I am creating a CocoaAction for it. But I don't know how I can pull progress from the underlying Observable that actually does the work (I have a Observable<Int> that emits progress events, each event is one percent of overall progress upto 100% when it sends onComplete). Seems like CocoaAction's signature is Action<Void, Void> which means it takes no argument (makes sense because a button calls it) and it emits no values in its elements Observable (I've used your trick from here to map to Void).

I'm sure I'm missing something trivial but how can I observe my download progress and get a notification when the whole process/action is done (onComplete)?

Thanks in advance!

Some tests failing with RxSwift 3.1 (execute() with Observable.just() ?)

Hi guys,
thanks for this great library, lack of actions was preventing me to move from RAC to RX :)

I've bootstrapped a project with RxSwift and Action, cocoapods chose RxSwift 3.1 which should be compatible with the latest version of Action.

It seems that the "executing" state of the Action doesn't get properly updated when the Observable returned is created with .just() and execute()d with parameters.
Seems that this block of code

 let executionStart = executionObservables
        let executionEnd = executionObservables
            .flatMap { observable -> Observable<Void> in
                return observable
                    .flatMap { _ in Observable<Void>.empty() }
                    .concat(Observable.just())
                    .catchErrorJustReturn()
            }

        executing = Observable
            .of(executionStart.map { _ in true }, executionEnd.map { _ in false })
            .merge()
            .startWith(false)

is not respecting the expected "order" of executionStart and executionEnd, and the true of the executingStart observable is being sent AFTER the executingEnd's false

This is currently preventing me from using the same action more than once in my project (the secondo time I execute the action, it's still disabled because of wrong value sent by the executing observable).

I've also checked the tests:

context("trigger via execute() method")

is failing twice in your test suite, (line 138 and 297 of ActionTest.swift) with something like this

XCTAssertEqual failed: ("[next(false) @ 0, next(false) @ 10, next(true) @ 10, next(false) @ 20, next(true) @ 20]") is not equal to ("[next(false) @ 0, next(true) @ 10, next(false) @ 10, next(true) @ 20, next(false) @ 20]")

As you can see, we have false(10) BEFORE true(10). I would expect (and so do the tests) to see true(10) (executing) and then false(10) (finished executing).

I have a good experience with ReactiveCocoa/ReactiveSwift but I'm quite unexperienced with RxSwift (although they're seem almost identical to me). I don't know what clever trick could allow us to sort this out, I've tried with a delay of 0.0 seconds on the executionEnd observable, it seems to works for my purposes (== in my project) but is breaking almost ALL the tests XD

Thanks

Carthage Support

It'd be great if this repo included an Xcode project file, both to facilitate use with carthage and simply to build the micro framework without Cocoapods. I'll see if I can take a stab at it sometime soon.

Cleanup public API

Currently Action might be exposing more properties than needed. Optimally, it should look something like

                                    Action<Input, Element>
                      +----------------------------------------------+
                      |         enabledIf: Observable<Bool>,         |
       inputs ------->| workFactory: (Input) -> Observable<Elemenet> |------> elements 
(AnyObserver<Input>)  |                                              | (Observable<Element>)
                      +------------------------------+---------------+
                                                     |
                                                     |
                                                     |
                                                     +------> errors: Observable<Error>
                                                     |
                                                     +------> isExecuting: Observable<Bool>
                                                     |
                                                     +------> isEnabled: Observable<Bool>

Thus, following changes to be applied;

  • enabled, should be renamed to isEnabled in conformance with Swift API design guidelines.
  • executing, should be renamed to isExecuting in conformance with Swift API design guidelines
  • _enabledIf to be declared as private
  • workFactory to be declared as private
  • inputs type to be changed to an ObserverType<Input>.

Some questions open for discussion;

  • Should executionObservables remain public?
  • Should errors be Observable<ActionError> or Observable<Swift.Error>? (may be related to #119 )
  • Should inputs be AnyObserver<Input> or Binder<Input>?
  • Do we still need InputSubject?

Leaks

Hi.

I have accidentally googled this issue in RxSwift: ReactiveX/RxSwift#573
and decided to check CocoaActions.

   class ReleaseMe {
        var name: String

        init(name: String) {
            self.name = name
        }

        deinit {
            print("deinit for \(name)")
        }
    }

    func request() -> Observable<Void> {
        let captured = ReleaseMe(name: "captured")

        return Observable.just(ReleaseMe(name: "just"))
            .map {_ in
                captured.name
            }
            .map(void)
    }

    private func bindModel() {
        loginButton.rx_action = CocoaAction() {[unowned self] in
            return self.request()
        }
    }

ReleaseMe objects are not freed when i tap the button.
I managed to make it work only after i got rid of ReplaySubject and addDisposableTo in Action class, but i guess it is not an option :)

Drop testing dependencies

The move to Swift 4 works because I applied just the minimal fixes needed for Quick to run in the case of Action. But playing with Quick revealed that there are many more tasks to complete to bring it up to part with Swift 4.

I think it would be a good idea to drop the Quick/Nimble dependencies for testing, and only rely on RxSwift and RxCocoa which are the true one dependencies this frameworks depends on.

Update podspec

I created a new tag for Carthage. Please update the podspec as well.

Creating a CocoaAction correctly

Hey,

Thanks for the library! I think I'm starting to understand it. I was using rx_tap on a button but have since switched to trying CocoaAction for the enabling/disabling functionality.

Can you just quickly sense check a few of my understandings? I have the following block of code that is just an Action. When it's invoked, it completes after a 4.5 sec delay.

let newAction = CocoaAction {

    let requestObservable: Observable<Bool> = Observable.create { (observer) -> Disposable in

        //Pretend we're doing a network request

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(4.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
            observer.onNext(true)
            observer.on(.Completed)
        }

        return AnonymousDisposable{}
    }

    return requestObservable.flatMap{_ in
        // Pretend I do something useful with my result from the first Observable.
        // Now CocoaAction is expecting a Observable<Void,Void> return value so I...

        return Observable.empty()
    }
}
  1. I can't just return requestObservable . I have to return an Observable<Void, Void>
  2. My inner calls should not end in a .subscribe as this would not return an Observable. .rx_action is expecting an Observable so it can use.bindTo(self.x_enabled) etc.

Does that sound about right?

Flatten out underlyingErrors

Currently

The current implementation of Action doesn't allow you to receive the Swift.Error when .execution is called. But we get an ActionError type which is not really useful because you always have to switch within it to the underlyingError.

Proposal

I think it would be nice for the framework to have something like var underlyingErrors: Observable<Swift.Error> which will only emit when .execution actually has an error

tvOS support

I'm excluding UIButton from tvos but I shouldn't need to โ€“ just a difference between rx_tap and rx_primaryAction.

Readme

It should actually, like, explain how to use the library.

  • How to use a workFactory.
  • How to use enabledIf.
  • What a CocoaAction is.
  • How the UIButton extension works.

Swift 3.0

How are we doing on Swift 3.0? Is somebody already working on a branch, or?

Can't install RxSwift and RxCocoa alphas since Action requires 2.x.

How to do incremental search

Action can do only one action at the same time. This works very nice.
However, it can not be used in scenes like incremental search.

Like this.

let searchText = Variable<String>("")

let action = Action<Input, Result> { input in 
    return networkRequest()
}
searchText.asObservable()
    .throttle(0.5, scheduler: MainScheduler.instance)
    .distinctUntilChanged()
    .bind(to: action.inputs)
    .disposed(by: disposeBag)

Even if it is input during the request, a notEnabled error will flow.

To do this I wrote an LatestAction using flatMapLatest
https://gist.github.com/Econa77/a1bb84d386a40017ba52d0602113b439

Can this LatestAction be included in the Action.framework? What do you think?

Update to RxSwift RC

  • just -> Observable.just
  • Variable is no longer a direct ObservableType
  • empty() -> Observable.empty
  • MainScheduler.sharedInstance -> MainScheduler.instance
  • create -> Observable.create
  • combineLatest -> Observable.combineLatest

Bind an action to a button with observable input

I'm new to Rx, and I've just started looking at Actions too. This question may sound silly, so please bear with me.

I have a screen with a text field and a button to submit the form.
What I would like to do is bind the button to an Action while passing the text field text observable as input to the action. How can I do this?

What I would like to do is something like this:
button.rx.bind(to: viewModel.action, input: textField.rx.text)
Or, if I have two text fields:
button.rx.bind(to: viewModel.action, input: Observable.combineLatest(textField1.rx.text, textField2.rx.text))
Is this possible? Does this even make sense to you guys?

I know that I can pass input using another way (see below), but I would like to avoid capturing self if possible. And also, the code above seems more reactive to me.
button.rx.bind(to: viewModel.action) { _ in return self.textField.text }

Thoughts?

Swift 4 support

Hi,

Is this project last repo already extensively tested and passing tests with swift4 ?
I am getting EXC_BAD_ACCESS called at Action:100 :
Observable .combineLatest(executing, enabledIf) { !$0 && $1 } .bind(to: enabledSubject) .disposed(by: disposeBag)
in .bind(to...)
at: override func subscribe<O : ObserverType>(_ observer: O) -> Disposable where O.E == Element { if !CurrentThreadScheduler.isScheduleRequired { // The returned disposable needs to release all references once it was disposed. let disposer = SinkDisposer() let sinkAndSubscription = run(observer, cancel: disposer) disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)
in disposer.setSink...

Thats my only problem using RxSwift and not sure where is the problem.

CocoaAction Type Change

It's <Void, Void> right now, but it would be awesome to somehow feed input into it. The problem is we can't define a property using generics on a non-generic type. I haven't given this a tonne of thought, so there might be an obvious solution.

2.1.1 Availability

Did 2.1.1's podspec get published? I'm still seeing 2.1.0 as the latest in cocoapods.

How to do incremental search

Action can do only one action at the same time. This works very nice.
However, it can not be used in scenes like incremental search.

Like this.

let searchText = Variable<String>("")

let action = Action<Input, Result> { input in 
    return networkRequest()
}
searchText.asObservable()
    .throttle(0.5, scheduler: MainScheduler.instance)
    .distinctUntilChanged()
    .bind(to: action.inputs)
    .disposed(by: disposeBag)

Even if it is input during the request, a notEnabled error will flow.

To do this I wrote an LatestAction using flatMapLatest
https://gist.github.com/Econa77/a1bb84d386a40017ba52d0602113b439

Can this LatestAction be included in the Action.framework? What do you think?

How to Convert Action with input to CocoaAction?

Hey ,guys ,Thanks for your working, There is a problem when I used this library, there is a Controller that can edit some info, also have a button to commit the change, I want button bind an action with it. But CocoaAction is an <Void, Void> signature, I tried to bindInput with Action, but if I want to bindTo button , there will be an input when binding. That`s not good, So can you help me out?

Move to Org

See: RxSwiftCommunity/contributors#4

Copy steps from: RxSwiftCommunity/NSObject-Rx#3 :

  • Update podspecs with new remote URL
  • Update CI badge
  • Update CI settings
  • Tidy up readme and other things that reference "Ash Furrow", since it'll be a community project.
  • Fork the repo back to my personal account (I really don't feel like sending a PR to fix CocoaPods trunk, forking is so much easier)

Provide behavioural documentation and unit testing for public API

While the library API is pretty stable, some fixes and refactoring introduced some breaking changes to its behavior (e.g. removing replay from elements). Also, while the overall usage is well documented with examples, this might not be the case for how exposed properties are behaving.

It is required to provide a documentation for how public API properties should behave along with corresponding unit tests to reflect this behavior to avoid any regressions during future refactoring. Candidate members include;

  • elements
  • inputs
  • errors
  • executing
  • func execute(_:)

tvOS update (RxCocoa)

lookupControlEvent = self.rx_primaryAction
should be changed to
lookupControlEvent = self.rx.primaryAction

1.0.0 Tag

It looks like the 1.0.0 tag was not correctly set to the podspec bump. I'm not sure what the policy is here with force pushes or whether this warrants one but I thought I should bring it up ๐Ÿ˜„

Action.execute().subscribe() receiving ActionError.notEnabled even when enabled

I could be misunderstanding this, but my thinking is that subscription closures passed into Action.execute().subscribe() should receive values, errors, etc from that particular invocation of execute(). I noticed I was never getting called back in the onCompleted closure, and found that I always receive a ActionError.notEnabled. This happens even when I create my Action with an explicit enabledIf: Observable.just(true).

`CocoaAction` thread safety

While there is no guarantees for thread-safety on Action. CocoaAction exposed public API should guarantee delivering events on main thread to ensure safe binding to UI.

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

Action not executed anymore

Hi,

I went back on a project on which I didn't work recently. Then I realised that my Actions were not executed anymore. I updated to Action 2.2.1 after seeing that some fix were added after other issues but it's still not working.

Here is the function I am trying to execute :

func presentSetNewPasswordViewController(_ presentingViewController: UIViewController) -> CocoaAction {
        return CocoaAction { _ in
            return Observable.create { observer -> Disposable in

                let navVC = self.instantiateEmbedSetNewPasswordViewController()
                navVC.modalPresentationStyle = UIModalPresentationStyle.formSheet
                presentingViewController.present(navVC, animated: true) {
                    observer.onCompleted()
                }
                return Disposables.create()
            }
        }
    }

And I execute it like this:

authenticationWireframe.presentSetNewPasswordViewController(window.rootViewController!).execute()

Am I doing something wrong here? Because this is definitely working on the prod app.

Thanks.

3.0.0 Release

I should have some time this weekend to finalize a release of the changes that were merged yesterday; is there anything else we want to get in before that goes out? If so, I can try to tackle it, otherwise I'm going to touch up the Readme and give the docs a once-over and open a PR with that to get started.

Allow init `Action` with `PrimitiveSequence`

init method should be generalised to allow work factories returning PrimitiveSequence or other ObservableConvertibleType

Example:

func save(_ message: String) -> Completable {
   // something that either completes successfully or fail with an error
}

let saveAction: Action<Void, Never> = Action { save($0) } 

How to dispose an observable returned by workFactory?

I have a hard time to dispose an observable produced by the action's workFactory. It seems that Observable returned by execute is not the same as Observable returned by work factory. Disposing it does not dispose an internal observer and does not reset enabled. What is the recommended way to programmatically stop execution of an observable that was created by workFactory and currently being executed by Action?

Here is my ugly test code:

import RxSwift
import Action
import UIKit

class ViewController: UIViewController {
    let action = Action<Void, Int> { _ in Observable<Int>.interval(1, scheduler: MainScheduler.instance) }
    var actionDisposable = Disposable?.none
    
    @IBAction func initiateAction() {
        actionDisposable = action.execute().bind(onNext: { print("\($0)") })
    }
    
    @IBAction func stopAction() {
        actionDisposable?.dispose()
    }
}

It does stop printing, but it does not re-enable action, as well as does not stop timer.

RxSwift 3.5 support?

RxCocoa (~> 3.4.0) required by Action (3.1.0)

when trying to update to RxSwift 3.5
Can we replace this requirement with ~> 3.4?

Switch to Circle CI

Travis builds are taking hours just to queue, we need to switch to Circle to get faster feedback. I'll get to this eventually, if someone else wants to take it on, by all means ๐Ÿ˜„

"dyld: Symbol not found" with RxSwift 4

Hello. Thanks for this great library.

I am having problem building master branch with RxSwift 4.0.0-rc.0. Here is a very simple project reproducing my problem
https://github.com/orakaro/Test-Swift4

Build and run with iPhone 8 simulator gave me following error:

dyld: lazy symbol binding failed: Symbol not found: __T07RxSwift14ObservableTypePAAE5shareAA0C0Cy1EQzGyF
  Referenced from: /Users/orakaro/Library/Developer/CoreSimulator/Devices/A7E83BA1-576E-4E5F-B1AF-19F9EB0FAE0F/data/Containers/Bundle/Application/DCB0E2FE-6D99-4CE1-974A-1F2D5985D419/Test-Swift4.app/Frameworks/Action.framework/Action
  Expected in: /Users/orakaro/Library/Developer/CoreSimulator/Devices/A7E83BA1-576E-4E5F-B1AF-19F9EB0FAE0F/data/Containers/Bundle/Application/DCB0E2FE-6D99-4CE1-974A-1F2D5985D419/Test-Swift4.app/Frameworks/RxSwift.framework/RxSwift

dyld: Symbol not found: __T07RxSwift14ObservableTypePAAE5shareAA0C0Cy1EQzGyF
  Referenced from: /Users/orakaro/Library/Developer/CoreSimulator/Devices/A7E83BA1-576E-4E5F-B1AF-19F9EB0FAE0F/data/Containers/Bundle/Application/DCB0E2FE-6D99-4CE1-974A-1F2D5985D419/Test-Swift4.app/Frameworks/Action.framework/Action
  Expected in: /Users/orakaro/Library/Developer/CoreSimulator/Devices/A7E83BA1-576E-4E5F-B1AF-19F9EB0FAE0F/data/Containers/Bundle/Application/DCB0E2FE-6D99-4CE1-974A-1F2D5985D419/Test-Swift4.app/Frameworks/RxSwift.framework/RxSwift

Failable actions

How do you make an action failable?

I would like to do something like this:

class SomeClass {

    var cancelAction: CocoaAction

    init() {
        cancelAction = CocoaAction {
            if someBooleanExpression {
                return failWith(CancelError.UnsavedChanges)
            }
            return just()
        }
    }
}

but the compiler throws up and says:

Variable 'self.cancelAction' used before being initialized

Which apparently has something to do with the if statement in an initializer.

I can't find any examples on doing this, so how would you go around and implement this correctly?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.