Add Observable examples

This commit is contained in:
Pedro Piñera Buendía 2016-05-16 15:32:05 +02:00
parent bb8386ee46
commit 4c9ed87fb3
11 changed files with 235 additions and 30 deletions

View File

@ -39,6 +39,10 @@ class CoreDataBasicView: UIViewController, UITableViewDelegate, UITableViewDataS
fatalError("init(coder:) has not been implemented")
}
deinit {
print("🚀🚀🚀 Deallocating \(self) 🚀🚀🚀")
}
// MARK: - Lifecycle

View File

@ -34,13 +34,17 @@ class CoreDataObservableView: UIViewController, UITableViewDelegate, UITableView
init() {
super.init(nibName: nil, bundle: nil)
self.title = "CoreData Basic"
self.title = "CoreData Observable"
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
print("🚀🚀🚀 Deallocating \(self) 🚀🚀🚀")
}
// MARK: - Lifecycle
@ -75,21 +79,23 @@ class CoreDataObservableView: UIViewController, UITableViewDelegate, UITableView
}
private func setupObservable() {
db.observable(Request<BasicObject>())
db.observable(Request<BasicObject>().sortedWith("date", ascending: true))
.rx_observe()
.subscribeNext { (change) in
.subscribeNext { [weak self] (change) in
switch change {
case .Initial(let entities):
self?.entities = entities.map(CoreDataBasicEntity.init)
break
case .Update(let deletions, let insertions, let modifications):
modifications.forEach { [weak self] in self?.entities[$0.0] = CoreDataBasicEntity(object: $0.1) }
insertions.forEach { [weak self] in self?.entities.insert(CoreDataBasicEntity(object: $0.1), atIndex: $0.0) }
deletions.forEach({ [weak self] in self?.entities.removeAtIndex($0) })
break
default:
break
}
}
.addDisposableTo(self.disposeBag)
// self.entities = try! db.fetch(Request<BasicObject>()).map(CoreDataBasicEntity.init)
}

View File

@ -38,6 +38,10 @@ class RealmBasicView: UIViewController, UITableViewDelegate, UITableViewDataSour
fatalError("init(coder:) has not been implemented")
}
deinit {
print("🚀🚀🚀 Deallocating \(self) 🚀🚀🚀")
}
// MARK: - Lifecycle
@ -120,25 +124,4 @@ class RealmBasicView: UIViewController, UITableViewDelegate, UITableViewDataSour
private func updateData() {
self.entities = try! db.fetch(Request<RealmBasicObject>()).map(RealmBasicEntity.init)
}
}
class RealmBasicObject: Object {
dynamic var date: NSDate = NSDate()
dynamic var name: String = ""
internal override class func primaryKey() -> String? {
return "name"
}
}
class RealmBasicEntity {
let dateString: String
let name: String
init(object: RealmBasicObject) {
let dateFormater = NSDateFormatter()
dateFormater.timeStyle = NSDateFormatterStyle.ShortStyle
dateFormater.dateStyle = NSDateFormatterStyle.ShortStyle
self.dateString = dateFormater.stringFromDate(object.date)
self.name = object.name
}
}

View File

@ -0,0 +1,21 @@
import Foundation
class RealmBasicEntity {
// MARK: - Attributes
let dateString: String
let name: String
// MARK: - Init
init(object: RealmBasicObject) {
let dateFormater = NSDateFormatter()
dateFormater.timeStyle = NSDateFormatterStyle.ShortStyle
dateFormater.dateStyle = NSDateFormatterStyle.ShortStyle
self.dateString = dateFormater.stringFromDate(object.date)
self.name = object.name
}
}

View File

@ -0,0 +1,18 @@
import Foundation
import RealmSwift
class RealmBasicObject: Object {
// MARK: - Attributes
dynamic var date: NSDate = NSDate()
dynamic var name: String = ""
// MARK: - PrimaryKey
internal override class func primaryKey() -> String? {
return "name"
}
}

View File

@ -0,0 +1,141 @@
import Foundation
import UIKit
import SugarRecord
import RealmSwift
import RxSwift
class RealmObservableView: UIViewController, UITableViewDelegate, UITableViewDataSource {
// MARK: - Attributes
lazy var db: RealmDefaultStorage = {
var configuration = Realm.Configuration()
configuration.fileURL = NSURL(fileURLWithPath: databasePath("realm-basic"))
let _storage = RealmDefaultStorage(configuration: configuration)
return _storage
}()
lazy var tableView: UITableView = {
let _tableView = UITableView(frame: CGRectZero, style: UITableViewStyle.Plain)
_tableView.translatesAutoresizingMaskIntoConstraints = false
_tableView.delegate = self
_tableView.dataSource = self
_tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: "default-cell")
return _tableView
}()
var entities: [RealmBasicEntity] = [] {
didSet {
self.tableView.reloadData()
}
}
var disposeBag: DisposeBag = DisposeBag()
// MARK: - Init
init() {
super.init(nibName: nil, bundle: nil)
self.title = "Realm Observable View"
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
print("🚀🚀🚀 Deallocating \(self) 🚀🚀🚀")
}
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
// MARK: - Private
private func setup() {
setupView()
setupNavigationItem()
setupTableView()
setupObservable()
}
private func setupView() {
self.view.backgroundColor = UIColor.whiteColor()
}
private func setupNavigationItem() {
self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Add, target: self, action: #selector(RealmBasicView.userDidSelectAdd(_:)))
}
private func setupTableView() {
self.view.addSubview(tableView)
self.tableView.snp_makeConstraints { (make) -> Void in
make.edges.equalTo(self.view)
}
}
private func setupObservable() {
db.observable(Request<RealmBasicObject>().sortedWith("date", ascending: true))
.rx_observe()
.subscribeNext { [weak self] (change) in
switch change {
case .Initial(let entities):
self?.entities = entities.map(RealmBasicEntity.init)
break
case .Update(let deletions, let insertions, let modifications):
modifications.forEach { [weak self] in self?.entities[$0.0] = RealmBasicEntity(object: $0.1) }
insertions.forEach { [weak self] in self?.entities.insert(RealmBasicEntity(object: $0.1), atIndex: $0.0) }
deletions.forEach({ [weak self] in self?.entities.removeAtIndex($0) })
break
default:
break
}
}
.addDisposableTo(self.disposeBag)
}
// MARK: - UITableViewDataSource / UITableViewDelegate
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.entities.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("default-cell")!
cell.textLabel?.text = "\(entities[indexPath.row].name) - \(entities[indexPath.row].dateString)"
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
let name = entities[indexPath.row].name
try! db.operation({ (context, save) -> Void in
guard let obj = try! context.request(RealmBasicObject.self).filteredWith("name", equalTo: name).fetch().first else { return }
_ = try? context.remove(obj)
save()
})
}
}
// MARK: - Actions
func userDidSelectAdd(sender: AnyObject!) {
try! db.operation { (context, save) -> Void in
let _object: RealmBasicObject = try! context.new()
_object.date = NSDate()
_object.name = randomStringWithLength(10) as String
try! context.insert(_object)
save()
}
}
}

View File

@ -56,7 +56,7 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega
// MARK: - UITableViewDataSource / UITableViewDelegate
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
return 4
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
@ -68,6 +68,8 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega
cell.textLabel?.text = "Realm Basic"
case 2:
cell.textLabel?.text = "CoreData Observable"
case 3:
cell.textLabel?.text = "Realm Observable"
default:
cell.textLabel?.text = ""
}
@ -84,6 +86,8 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega
self.navigationController?.pushViewController(RealmBasicView(), animated: true)
case 2:
self.navigationController?.pushViewController(CoreDataObservableView(), animated: true)
case 3:
self.navigationController?.pushViewController(RealmObservableView(), animated: true)
default:
break
}

View File

@ -14,6 +14,9 @@
2346DAB51CE9F3220047CB5F /* RealmBasicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2346DAB21CE9F3220047CB5F /* RealmBasicView.swift */; };
2346DAB71CE9F3350047CB5F /* BasicObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2346DAB61CE9F3350047CB5F /* BasicObject.swift */; };
2346DAB91CE9F34E0047CB5F /* CoreDataBasicEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2346DAB81CE9F34E0047CB5F /* CoreDataBasicEntity.swift */; };
235ABB8F1CEA011200C2AEB9 /* RealmObservableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 235ABB8E1CEA011200C2AEB9 /* RealmObservableView.swift */; };
235ABB921CEA012C00C2AEB9 /* RealmBasicObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 235ABB911CEA012C00C2AEB9 /* RealmBasicObject.swift */; };
235ABB941CEA013C00C2AEB9 /* RealmBasicEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 235ABB931CEA013C00C2AEB9 /* RealmBasicEntity.swift */; };
236B5A171C3886CA00C9E469 /* Basic.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 236B5A151C3886CA00C9E469 /* Basic.xcdatamodeld */; };
23D5927E1C28494500441B41 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 23D592741C28494500441B41 /* Assets.xcassets */; };
23D5927F1C28494500441B41 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 23D592761C28494500441B41 /* LaunchScreen.storyboard */; };
@ -29,6 +32,9 @@
2346DAB21CE9F3220047CB5F /* RealmBasicView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmBasicView.swift; sourceTree = "<group>"; };
2346DAB61CE9F3350047CB5F /* BasicObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BasicObject.swift; sourceTree = "<group>"; };
2346DAB81CE9F34E0047CB5F /* CoreDataBasicEntity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataBasicEntity.swift; sourceTree = "<group>"; };
235ABB8E1CEA011200C2AEB9 /* RealmObservableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmObservableView.swift; sourceTree = "<group>"; };
235ABB911CEA012C00C2AEB9 /* RealmBasicObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmBasicObject.swift; sourceTree = "<group>"; };
235ABB931CEA013C00C2AEB9 /* RealmBasicEntity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmBasicEntity.swift; sourceTree = "<group>"; };
236B5A161C3886CA00C9E469 /* Basic.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Basic.xcdatamodel; sourceTree = "<group>"; };
23D5925D1C2834DC00441B41 /* SugarRecordExamples.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SugarRecordExamples.app; sourceTree = BUILT_PRODUCTS_DIR; };
23D592741C28494500441B41 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@ -101,6 +107,8 @@
2346DAB01CE9F3220047CB5F /* Realm */ = {
isa = PBXGroup;
children = (
235ABB901CEA011B00C2AEB9 /* Models */,
235ABB8D1CEA010B00C2AEB9 /* Observable */,
2346DAB11CE9F3220047CB5F /* Basic */,
);
path = Realm;
@ -114,6 +122,23 @@
path = Basic;
sourceTree = "<group>";
};
235ABB8D1CEA010B00C2AEB9 /* Observable */ = {
isa = PBXGroup;
children = (
235ABB8E1CEA011200C2AEB9 /* RealmObservableView.swift */,
);
path = Observable;
sourceTree = "<group>";
};
235ABB901CEA011B00C2AEB9 /* Models */ = {
isa = PBXGroup;
children = (
235ABB911CEA012C00C2AEB9 /* RealmBasicObject.swift */,
235ABB931CEA013C00C2AEB9 /* RealmBasicEntity.swift */,
);
path = Models;
sourceTree = "<group>";
};
236B5A141C3886BF00C9E469 /* DataModels */ = {
isa = PBXGroup;
children = (
@ -359,9 +384,12 @@
buildActionMask = 2147483647;
files = (
2346DAB31CE9F3220047CB5F /* CoreDataBasicView.swift in Sources */,
235ABB941CEA013C00C2AEB9 /* RealmBasicEntity.swift in Sources */,
2346DAB91CE9F34E0047CB5F /* CoreDataBasicEntity.swift in Sources */,
2346DAB71CE9F3350047CB5F /* BasicObject.swift in Sources */,
235ABB921CEA012C00C2AEB9 /* RealmBasicObject.swift in Sources */,
2346DAB41CE9F3220047CB5F /* CoreDataObservableView.swift in Sources */,
235ABB8F1CEA011200C2AEB9 /* RealmObservableView.swift in Sources */,
23D592811C28494500441B41 /* ViewController.swift in Sources */,
236B5A171C3886CA00C9E469 /* Basic.xcdatamodeld in Sources */,
232660A71C28563F00575110 /* Random.swift in Sources */,

View File

@ -61,7 +61,7 @@ public class CoreDataObservable<T: NSManagedObject where T:Equatable>: Observabl
}
public func controllerDidChangeContent(controller: NSFetchedResultsController) {
let deleted = self.batchChanges.filter { $0.isDeletion() }.map { (index: $0.index(), element: $0.object()) }
let deleted = self.batchChanges.filter { $0.isDeletion() }.map { $0.index() }
let inserted = self.batchChanges.filter { $0.isInsertion() }.map { (index: $0.index(), element: $0.object()) }
let updated = self.batchChanges.filter { $0.isUpdate() }.map { (index: $0.index(), element: $0.object()) }
self.observer?(ObservableChange.Update(deletions: deleted, insertions: inserted, modifications: updated))

View File

@ -2,7 +2,7 @@ import Foundation
public enum ObservableChange<T> {
case Initial([T])
case Update(deletions: [(index: Int, element: T)], insertions: [(index: Int, element: T)], modifications: [(index: Int, element: T)])
case Update(deletions: [Int], insertions: [(index: Int, element: T)], modifications: [(index: Int, element: T)])
case Error(NSError)
}

View File

@ -47,7 +47,7 @@ public class RealmObservable<T: Object>: Observable<T> {
case .Initial(let initial):
return ObservableChange.Initial(initial.toArray())
case .Update(let objects, let deletions, let insertions, let modifications):
let deletions = deletions.map { (index: $0, element: objects[$0]) }
let deletions = deletions.map { $0 }
let insertions = insertions.map { (index: $0, element: objects[$0]) }
let modifications = modifications.map { (index: $0, element: objects[$0]) }
return ObservableChange.Update(deletions: deletions, insertions: insertions, modifications: modifications)