PMVPCoreData 0.5.1

PMVPCoreData 0.5.1

Maintained by Aubrey Goodman.



  • By
  • Aubrey Goodman

PMVP is...

  • a framework for data management within your mobile app.
  • a tool for developers.
  • reactive, following the Reactive Extensions (Rx) design patterns.
  • lightweight and extensible!

PMVP is not...

  • a replacement for Core Data.
  • a replacement for Realm.
  • heavyweight.

Overview

A detailed description with examples is available on the Motiv Engineering Blog here:

https://medium.com/motiv-engineering-blog/introducing-pmvp-a-reactive-mobile-application-design-pattern-b2216b34ec0c

Provider

The generic Provider class defines the interface and boilerplate implementation for coordinating access to local and remote data stores. You are responsible for implementing the various domain-specific components, such as converters and storage adapters. The framework handles all the heavy lifting, using your custom components.

Model

The generic ViewModel<T, N> class defines standard behavior common to all view models, including state representation and intent processing. View controllers define observers to respond to user actions by mapping them to intents, which are routed to the view model. All actions taken to change view model state must be encoded as intents.

View

View components are simple UIKit objects, responsible for representing view state to the user. They also act as a mechanism for users to take action to change view model state by interacting with on-screen components. View delegates, if any, are defined in the controller and must be transformed to view model intents.

Presenter

The generic Presenter<T, N> class defines the interface and boilerplate implementation for configuring observers and bindings for conveying view model state to the user. Presenter observers subscribe to view model observables to update text, images, view bounds, layout constraints, etc.

Getting Started

Podfile

pod 'PMVP', '~> 0.4'

Implement required components

Let's say you're creating a class to manage Items.

class ItemProvider: Provider<...> {

Before you define the provider, you need to satisfy its dependencies. You need to create classes for the following:

  • ItemProxy: Proxy (the lightweight object you use everywhere in your app to describe an Item)
  • ItemLocal: LocalObject (must inherit from LocalObject; typically a Core Data or Realm managed object)
  • ItemRemote: RemoteObject (must inherit from RemoteObject; defines the remote object schema)
  • ItemLocalConverter: Converter (converts between proxy and local objects)
  • ItemRemoteConverter: Converter (converts between proxy and remote objects)
  • ItemLocalStorage: LocalStorage (your custom implementation of local data accessors)
  • ItemRemoteStorage: RemoteStorage (your custom implementation of lremote data accessors)

Once these are defined, you can create the provider class, as follows:

import PMVP

class ItemProvider: Provider<Int, ItemProxy, ItemLocal, ItemRemote, ItemLocalStorage, ItemRemoteStorage> {
}

Usage

Observing the collection

itemProvider.objects()
   .subscribe(onNext: { items in NSLog("\(items.count) objects") })
   .disposed(by: disposeBag)

Observing one item

itemProvider.object(for: 127)
   .subscribe(onNext: { item in NSLog(item) })
   .disposed(by: disposeBag)

Creating/Updating items

itemProvider.update(item, queue: .main) { result in 
  switch result {
  case .success(let localItem):
    NSLog("item updated \(localItem)")
  case .failure(let error):
    NSLog("failed to update item: \(error)")
  }
}

Destroying an item

itemProvider.destroy(item, queue: .main) { result in 
  switch result {
  case .success(let localItem):
    NSLog("item deleted \(localItem)")
  case .failure(let error):
    NSLog("failed to delete item: \(error)")
  }
}