RocketData: DataProviders don't call delegate for update after first miss?

Hey, thanks for a great library. I was trying to integrate it into my project. I use a wrapper ReactiveProvider<T> around DataProvider<T> for RAC Support. I have my ReactiveProviders in each viewModel, but networking is done elsewhere so I initiate another DataProvider and call setData(_:updateCache:context:) on that data provider, and the ReactiveProvider doesn’t get the delegate call for update.

Is this expected behaviour? I saw another issue, is this related to that? https://github.com/linkedin/RocketData/issues/8

Here is the code for ReactiveProvider

class ReactiveProvider<M: SimpleModel> {
    private let provider = DataProvider<M>()

    let signal: Signal<M?, NoError>
    fileprivate let pipe: Observer<M?, NoError>

    init() {
        let (signal, pipe) = Signal<M?, NoError>.pipe()
        self.signal = signal
        self.pipe = pipe
        provider.delegate = self
    }

    func start(with cacheKey: CacheKey) {
        if provider.isPaused {
            provider.isPaused = false
        }
        provider.fetchDataFromCache(withCacheKey: cacheKey.key, context: cacheKey) {
            [weak self] model, error in
            self?.pipe.send(value: model)
        }
    }

    func pause() {
        provider.isPaused = true
    }
}

extension ReactiveProvider: DataProviderDelegate {
    func dataProviderHasUpdatedData<T>(_ dataProvider: DataProvider<T>,
                                    context: Any?) {
        guard let data = dataProvider.data as? M else {
            pipe.send(value: nil)
            return
        }

        pipe.send(value: data)
    }
}

and here is the code that sets the data (in networking part of the app, not in viewModel)

class CacheProvider {
    private var providers: [String: Any] = [:]

    func cache<T: SimpleModel>(object: T?, for key: CacheKey) {
        let provider: DataProvider<T>
        if let p = providers[key.key] as? DataProvider<T> {
            provider = p
        } else {
            provider = DataProvider<T>()
            providers[key.key] = provider
        }
        provider.setData(object, updateCache: true, context: key)
    }
}

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 42 (22 by maintainers)

Most upvoted comments

@plivesey Will you add a sample for this?

Yeah this seems to have fixed the issue, working as intended. Thanks a lot!

That’s great. Hoping to get the full solution in soon. On Wed, Dec 7, 2016 at 3:03 PM Ahmet Karalar notifications@github.com wrote:

I wasn’t able to print the identifiers because it was happening on a background thread and the code is in a block, which causes lldb errors on my machine when I try po model (might be related to me)… but you are right, the assertion problem was indeed same cache key for both the model and the collection.

I tried to change them and got the fatal error two comments above, but I guess I messed up last night working late, as it seems to be working now! Not the best solution but a solution nonetheless! thanks so much, and thanks again for the great library 😃

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/linkedin/RocketData/issues/50#issuecomment-265601946, or mute the thread https://github.com/notifications/unsubscribe-auth/ABMNTddfE1Pyfz7PK9igVAhoB3dty5Ybks5rFztRgaJpZM4LCt04 .

This would also allow people to add elements to collection data providers when they meet a certain predicate (like core data):

Something like:

collectionDataProvider.listenForModels { model in
    if let model = model as? SpecificModel, model.name = "something" {
        collectionDataProvider.append(model)
    }
}

This feature has been requested before, so being able to support both would be great.

Btw, all the APIs here need a bunch of work…just a rough idea.