Giter Site home page Giter Site logo

reactivecocoa / reactiveswift-composable-architecture Goto Github PK

View Code? Open in Web Editor NEW
160.0 11.0 15.0 13.22 MB

A library for building applications in a consistent and understandable way, with composition, testing, and ergonomics in mind.

Home Page: https://www.pointfree.co/

License: MIT License

Makefile 0.23% Swift 98.61% C 1.16%

reactiveswift-composable-architecture's Issues

Object get deallocated on Signal.Observer

This error happen on device not simulator, it happens before pushing a new controller on IfLet.
Could anyone please help me get out of this ?
iOS version : 14.5
Xcode 12.5

Screenshot 2021-05-11 at 13 22 19

Nested properties keyPath support for Produced values

I'd like to add support for the nested properties in Produced values, current implementation use
@dynamicMemberLookup, which does not support nested properties yet, and I have 2.5 solutions:

Zero (not a real one, I mean ๐Ÿ˜…)
Use

viewStore.property.map(\.nestedProperty).skipRepeats()

which is okay, but not the most convenient stuff.

First
Add another method to the ViewStore type to support default KeyPath stuff:

viewStore.producer(for: \.KeyPath<State, Value>) -> Produced<Value>

That extremely easy and fits ReactiveSwift, but I'm not sure if it fits ComposableArchitecture.
Maybe it worth mentioning in readme or smth if approved.
I use it locally now btw.

Second
Use Produced type as a dynamicMemberLookup container and do not return a producer implicitly, but return mapped itself.

/// A producer of store state.
@dynamicMemberLookup
public struct Produced<Value> { // <- have to drop `SignalProducerConvertible` protocol
    private let _producer: Effect<Value, Never> // <- private stuff
    
    init(by upstream: Effect<Value, Never>) {
        self._producer = upstream
    }
    
    /// Returns the resulting producer of a given key path.
    public subscript<LocalValue>(
        dynamicMember keyPath: KeyPath<Value, LocalValue>
    ) -> Produced<LocalValue> {
        Produced<LocalValue>(by: _producer.map(keyPath)) // <- here is a change
    }
}

extension Produced {
    public var producer: Effect<Value, Never> { _producer } // <- Logic inconsistency {li}
}

extension Produced where Value: Equatable {
    public var producer: Effect<Value, Never> { _producer.skipRepeats() } // <- Logic inconsistency {li}
}

Usage:

viewStore.property.nestedProperty.producer

That will lead to more consistent API, but the implementation will be major so that users won't be able to subscribe to any property without explicitly calling the producer anymore. Also, there is a little logic inconsistency at {li} marks due to Equatable conformance, that should be tested and anyways it may suffer from type erasure stuff.

ViewStore version without Combine/SwiftUI

Hi,

First of all, thank you for doing an amazing job in creating this version of the library. It's been of a lot of help.

At my workplace we're still required to support iOS 12, which means that we can't use Combine/SwiftUI yet.
I wanted to integrate this version, as it's based on ReactiveSwift which can run on older version, but to my surprise, parts of it are still using Combine.

Is there any option to remove dependency from ViewStore to Combine.
It's conforming to ObservableObject(least of all) which makes it impossible to use in older version.

Multiple calls to store.ifLet

Thanks for the hard work in making this fork! I'm currently noticing an issue with calling ifLet on a Store. I have a test project that I've been messing around with to get a good feel for using this fork. I can share the test project if needed.

The issue is that I have two modals that are presented from the root view controller. Both have optional states on the root State. When presenting/dismissing the modals one after the other, I'm noticing that the ifiLet call on the store is called multiple times. This doesn't happen the first time, only after dismissing a modal once or twice, and then it happens every time after that.

Here's what my root state looks like:

struct State {
    var items: ItemsState?
    var favorites: FavoritesState?
    ...
}

I'm presenting the view controllers with the following:

let store = self.store.scope(state: \.favorites, action: Root.Action.favorites)
store.ifLet { [weak self] store in
    guard let self = self else { return }
    let vc = FavoritesViewController(store: store)
    let nc = UINavigationController(rootViewController: vc)
    nc.presentationController?.delegate = self
    self.present(nc, animated: true, completion: nil)
}

I was able to fix my issue by creating another variant of ifLet. The "fix" is to use skipRepeats() instead of .skipRepeats { ($0 != nil) == ($1 != nil) }.

@discardableResult
public func ifLet2<Wrapped: Equatable>(
    then unwrap: @escaping (Store<Wrapped, Action>) -> Void,
    else: @escaping () -> Void
) -> Disposable where State == Wrapped? {
    let elseDisposable =
        self
        .producerScope(
            state: { state -> Effect<Wrapped?, Never> in
                state
                    .skipRepeats()
            }
        )
        .startWithValues { store in
            if ViewStore(store).state == nil { `else`() }
        }

    let unwrapDisposable =
        self
        .producerScope(
            state: { state -> Effect<Wrapped, Never> in
                state
                    .skipRepeats()
                    .compactMap { $0 }
            }
        )
        .startWithValues(unwrap)

    return CompositeDisposable([elseDisposable, unwrapDisposable])
}

I don't want to break something else by doing this though, so I'm curious what I might be missing? I'll try digging in to this a bit more if I get the time.

Change TestStore so that it isn't only compiled when running in DEBUG

On one of the projects I work on, we are forced to pull in CA manually. This is because we have a build configuration for testing that isn't DEBUG. However, this means that we can not use TestStore since that is guarded by DEBUG. It would be nice to be able to use TestStore regardless of project configuration.

Would it be possible to remove the #if DEBUG here?

Include TCA Swift Concurrency changes from release 0.39.0

TCA just released version 0.39.0 which includes all the Swift Concurrency changes, and fundamentally changes many internals of the library. For example, Effect no longer conforms to Publisher but instead holds on to a Publisher internally.

The changes encourage moving away from Combine based effects to effects that use Swift Concurrency using Effect.task.

I've been able to maintain this fork in sync with TCA up to the last commit prior to the merge of the Swift Concurrency PR, however I feel that trying to update the fork to include the Swift Concurrency changes would be a huge task, and I don't have the necessary time to dedicate to it.

There's also the question of how useful this fork will continue to be. The objective for @mbrandonw and @stephencelis with TCA is clearly (and rightly) to be able to remove Combine completely from TCA sooner or later, at which point the need for a Reactive Swift fork really ceases to exist. Even now, this fork has a minimum deployment target of iOS 13 so the only use cases for it are:

  • existing projects using it which haven't yet migrated to Combine TCA
  • projects that don't want to use Combine as it's not open source
  • projects using non-Apple OSes like Linux and Android

If anyone is interested in trying to migrate this fork to the new changes, I'd be happy to help out where I can.

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.