mirror of
https://github.com/modo-studio/SugarRecord.git
synced 2024-09-11 14:36:41 +03:00
Merge pull request #257 from pepibumur/observerOnNext
Observer.OnNext / Operation generic functions
This commit is contained in:
commit
5bb35b2ab6
14
README.md
14
README.md
@ -64,7 +64,7 @@ pod "SugarRecord/Realm+RAC"
|
||||
6. Link your target with **CoreData** library *(from Build Phases)*
|
||||
|
||||
#### Notes
|
||||
- Carthage integration includes both, CoreData and Carthage. We're planning to separate it in multiple frameworks. [Task](https://trello.com/c/hyhN1Tp2/11-create-separated-frameworks-for-foundation-coredata-and-realm)
|
||||
- Carthage integration includes both, CoreData and Realm. We're planning to separate it in multiple frameworks. [Task](https://trello.com/c/hyhN1Tp2/11-create-separated-frameworks-for-foundation-coredata-and-realm)
|
||||
- SugarRecord 2.0 is not compatible with the 1.x interface. If you were using that version you'll have to update your project to support this version.
|
||||
|
||||
## Reference
|
||||
@ -197,13 +197,13 @@ catch {
|
||||
`Storage`s offer a reactive API that you can use if your app follows the Reactive paradigm. SugarRecord supports the two main Reactive libraries for Swift, [ReactiveCocoa](https://github.com/reactivecocoa/reactivecocoa) and [RxSwift](https://github.com/ReactiveX/RxSwift). Methods prefixes are `rac_` and `rx_` respectively:
|
||||
|
||||
```swift
|
||||
// Executes the operation and notifies the completion/error to the producer.
|
||||
func rac_operation(operation: (context: Context, save: Saver) -> Void) -> SignalProducer<Void, NoError>
|
||||
func rx_operation(operation: (context: Context, save: Saver) -> Void) -> Observable<Void>
|
||||
// Executes the operation and notifies the completion/error to the producer. Optionally returns an object from the operation (such as the id of a newly created object)
|
||||
func rac_operation<T>(operation: (context: Context, save: Saver) -> T) -> SignalProducer<T, NoError>
|
||||
func rx_operation<T>(operation: (context: Context, save: Saver) -> T) -> Observable<T>
|
||||
|
||||
// Executes the operation in background and notifies the completion/error to the producer.
|
||||
func rac_backgroundOperation(operation: (context: Context, save: Saver) -> Void) -> SignalProducer<Void, NoError>
|
||||
func rx_backgroundOperation(operation: (context: Context, save: Saver) -> Void) -> Observable<Void>
|
||||
// Executes the operation in background and notifies the completion/error to the producer. Optionally returns an object from the operation (such as the id of a newly created object)
|
||||
func rac_backgroundOperation<T>(operation: (context: Context, save: Saver) -> T) -> SignalProducer<T, NoError>
|
||||
func rx_backgroundOperation<T>(operation: (context: Context, save: Saver) -> T) -> Observable<T>
|
||||
|
||||
// Executes a fetch in a background thread mapping them into thread safe plain entities forwarding the results to the producer.
|
||||
func rac_backgroundFetch<T, U>(request: Request<T>, mapper: T -> U) -> SignalProducer<[U], Error>
|
||||
|
@ -39,12 +39,14 @@ public class CoreDataDefaultStorage: Storage {
|
||||
return _context
|
||||
}
|
||||
|
||||
public func operation(operation: (context: Context, save: () -> Void) throws -> Void) throws {
|
||||
public func operation<T>(operation: (context: Context, save: () -> Void) throws -> T) throws -> T {
|
||||
let context: NSManagedObjectContext = self.saveContext as! NSManagedObjectContext
|
||||
var _error: ErrorType!
|
||||
|
||||
var returnedObject: T!
|
||||
context.performBlockAndWait {
|
||||
do {
|
||||
try operation(context: context, save: { () -> Void in
|
||||
returnedObject = try operation(context: context, save: { () -> Void in
|
||||
do {
|
||||
try context.save()
|
||||
}
|
||||
@ -69,6 +71,8 @@ public class CoreDataDefaultStorage: Storage {
|
||||
if let error = _error {
|
||||
throw error
|
||||
}
|
||||
|
||||
return returnedObject
|
||||
}
|
||||
|
||||
public func removeStore() throws {
|
||||
|
@ -40,12 +40,15 @@ public class CoreDataiCloudStorage: Storage {
|
||||
}
|
||||
}
|
||||
|
||||
public func operation(operation: (context: Context, save: () -> Void) throws -> Void) throws {
|
||||
public func operation<T>(operation: (context: Context, save: () -> Void) throws -> T) throws -> T {
|
||||
let context: NSManagedObjectContext = (self.saveContext as? NSManagedObjectContext)!
|
||||
var _error: ErrorType!
|
||||
|
||||
var returnedObject: T!
|
||||
|
||||
context.performBlockAndWait {
|
||||
do {
|
||||
try operation(context: context, save: { () -> Void in
|
||||
returnedObject = try operation(context: context, save: { () -> Void in
|
||||
do {
|
||||
try context.save()
|
||||
}
|
||||
@ -71,6 +74,8 @@ public class CoreDataiCloudStorage: Storage {
|
||||
if let error = _error {
|
||||
throw error
|
||||
}
|
||||
|
||||
return returnedObject
|
||||
}
|
||||
|
||||
public func removeStore() throws {
|
||||
|
@ -14,7 +14,7 @@ public protocol Storage: CustomStringConvertible, Requestable {
|
||||
var saveContext: Context! { get }
|
||||
var memoryContext: Context! { get }
|
||||
func removeStore() throws
|
||||
func operation(operation: (context: Context, save: () -> Void) throws -> Void) throws
|
||||
func operation<T>(operation: (context: Context, save: () -> Void) throws -> T) throws -> T
|
||||
func fetch<T: Entity>(request: Request<T>) throws -> [T]
|
||||
|
||||
}
|
||||
|
@ -6,15 +6,17 @@ public extension Storage {
|
||||
|
||||
// MARK: - Operation
|
||||
|
||||
func rac_operation(op: (context: Context, save: () -> Void) throws -> Void) -> SignalProducer<Void, Error> {
|
||||
func rac_operation<T>(op: (context: Context, save: () -> Void) throws -> T) -> SignalProducer<T, Error> {
|
||||
return SignalProducer { (observer, disposable) in
|
||||
do {
|
||||
try self.operation { (context, saver) throws in
|
||||
let returnedObject = try self.operation { (context, saver) throws in
|
||||
try op(context: context, save: {
|
||||
saver()
|
||||
})
|
||||
observer.sendCompleted()
|
||||
}
|
||||
|
||||
observer.sendNext(returnedObject)
|
||||
observer.sendCompleted()
|
||||
}
|
||||
catch {
|
||||
observer.sendFailed(Error.Store(error))
|
||||
@ -22,24 +24,26 @@ public extension Storage {
|
||||
}
|
||||
}
|
||||
|
||||
func rac_operation(op: (context: Context) throws -> Void) -> SignalProducer<Void, Error> {
|
||||
func rac_operation<T>(op: (context: Context) throws -> T) -> SignalProducer<T, Error> {
|
||||
return self.rac_operation { (context, saver) throws in
|
||||
try op(context: context)
|
||||
let returnedObject = try op(context: context)
|
||||
saver()
|
||||
return returnedObject
|
||||
}
|
||||
}
|
||||
|
||||
func rac_backgroundOperation(op: (context: Context, save: () -> Void) throws -> Void) -> SignalProducer<Void, Error> {
|
||||
func rac_backgroundOperation<T>(op: (context: Context, save: () -> Void) throws -> T) -> SignalProducer<T, Error> {
|
||||
return SignalProducer { (observer, disposable) in
|
||||
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
|
||||
dispatch_async(dispatch_get_global_queue(priority, 0)) {
|
||||
do {
|
||||
try self.operation { (context, saver) throws in
|
||||
let returnedObject = try self.operation { (context, saver) throws in
|
||||
try op(context: context, save: {
|
||||
saver()
|
||||
})
|
||||
observer.sendCompleted()
|
||||
}
|
||||
observer.sendNext(returnedObject)
|
||||
observer.sendCompleted()
|
||||
}
|
||||
catch {
|
||||
observer.sendFailed(Error.Store(error))
|
||||
@ -48,10 +52,12 @@ public extension Storage {
|
||||
}
|
||||
}
|
||||
|
||||
func rac_backgroundOperation(op: (context: Context) throws -> Void) -> SignalProducer<Void, Error> {
|
||||
func rac_backgroundOperation<T>(op: (context: Context) throws -> T) -> SignalProducer<T, Error> {
|
||||
return rac_backgroundOperation { (context, save) throws in
|
||||
try op(context: context)
|
||||
let returnedObject = try op(context: context)
|
||||
save()
|
||||
|
||||
return returnedObject
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,15 +3,17 @@ import RxSwift
|
||||
|
||||
public extension Storage {
|
||||
|
||||
func rx_operation(op: (context: Context, save: () -> Void) throws -> Void) -> Observable<Void> {
|
||||
func rx_operation<T>(op: (context: Context, save: () -> Void) throws -> T) -> Observable<T> {
|
||||
return Observable.create { (observer) -> Disposable in
|
||||
do {
|
||||
try self.operation { (context, saver) throws -> Void in
|
||||
let returnedObject = try self.operation { (context, saver) throws -> T in
|
||||
try op(context: context, save: { () -> Void in
|
||||
saver()
|
||||
})
|
||||
observer.onCompleted()
|
||||
}
|
||||
|
||||
observer.onNext(returnedObject)
|
||||
observer.onCompleted()
|
||||
}
|
||||
catch {
|
||||
observer.onError(error)
|
||||
@ -20,22 +22,28 @@ public extension Storage {
|
||||
}
|
||||
}
|
||||
|
||||
func rx_operation(op: (context: Context) -> Void) -> Observable<Void> {
|
||||
func rx_operation<T>(op: (context: Context) throws -> T) -> Observable<T> {
|
||||
return rx_operation { (context, save) in
|
||||
op(context: context)
|
||||
|
||||
let returnedObject = try op(context: context)
|
||||
save()
|
||||
|
||||
return returnedObject
|
||||
}
|
||||
}
|
||||
|
||||
func rx_backgroundOperation(op: (context: Context, save: () -> Void) throws -> Void) -> Observable<Void> {
|
||||
func rx_backgroundOperation<T>(op: (context: Context, save: () -> Void) throws -> T) -> Observable<T> {
|
||||
return Observable.create { (observer) -> Disposable in
|
||||
do {
|
||||
try self.operation { (context, saver) throws in
|
||||
let returnedObject = try self.operation { (context, saver) throws -> T in
|
||||
try op(context: context, save: { () -> Void in
|
||||
saver()
|
||||
})
|
||||
observer.onCompleted()
|
||||
}
|
||||
|
||||
observer.onNext(returnedObject)
|
||||
observer.onCompleted()
|
||||
|
||||
}
|
||||
catch {
|
||||
observer.onError(error)
|
||||
@ -44,10 +52,13 @@ public extension Storage {
|
||||
}
|
||||
}
|
||||
|
||||
func rx_backgroundOperation(op: (context: Context) throws -> Void) -> Observable<Void> {
|
||||
func rx_backgroundOperation<T>(op: (context: Context) throws -> T) -> Observable<T> {
|
||||
return rx_backgroundOperation { (context, save) throws in
|
||||
try op(context: context)
|
||||
|
||||
let returnedObject = try op(context: context)
|
||||
save()
|
||||
|
||||
return returnedObject
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,13 +49,15 @@ public class RealmDefaultStorage: Storage {
|
||||
}
|
||||
}
|
||||
|
||||
public func operation(operation: (context: Context, save: () -> Void) throws -> Void) throws {
|
||||
public func operation<T>(operation: (context: Context, save: () -> Void) throws -> T) throws -> T {
|
||||
let context: Realm = self.saveContext as! Realm
|
||||
context.beginWrite()
|
||||
var save: Bool = false
|
||||
var _error: ErrorType!
|
||||
|
||||
var returnedObject: T!
|
||||
do {
|
||||
try operation(context: context, save: { () -> Void in
|
||||
returnedObject = try operation(context: context, save: { () -> Void in
|
||||
defer {
|
||||
save = true
|
||||
}
|
||||
@ -77,6 +79,9 @@ public class RealmDefaultStorage: Storage {
|
||||
if let error = _error {
|
||||
throw error
|
||||
}
|
||||
|
||||
return returnedObject
|
||||
|
||||
}
|
||||
|
||||
public func observable<T: Object>(request: Request<T>) -> RequestObservable<T> {
|
||||
|
@ -116,6 +116,24 @@ class CoreDataDefaultStorageTests: QuickSpec {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
describe("-operation:") {
|
||||
|
||||
it("should return the inner value from the operation") {
|
||||
waitUntil(action: { (done) -> Void in
|
||||
let result: String = try! subject.operation({ (context, save) -> String in
|
||||
let issue: Track = try! context.create()
|
||||
issue.name = "trackName"
|
||||
save()
|
||||
return issue.name!
|
||||
})
|
||||
expect(result) == "trackName"
|
||||
done()
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
describe("-observable:") {
|
||||
|
||||
|
@ -75,6 +75,24 @@ class ReactiveStorageTests: QuickSpec {
|
||||
}
|
||||
}
|
||||
|
||||
describe("rx_backgroundOperation") {
|
||||
it("should produce the object from the inner block", closure: {
|
||||
waitUntil(action: { (done) -> Void in
|
||||
_ = storage?.rx_backgroundOperation({ (context, save) -> String in
|
||||
let issue: Issue = try! context.create()
|
||||
issue.name = "testName"
|
||||
save()
|
||||
return issue.name
|
||||
}).subscribeNext({ (stringProduced) in
|
||||
expect(stringProduced) == "testName"
|
||||
done()
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
describe("rac_fetch") {
|
||||
it("should execute the fetch and return the results") {
|
||||
_ = try? storage?.operation({ (context, save) -> Void in
|
||||
|
Loading…
Reference in New Issue
Block a user