mirror of
https://github.com/modo-studio/SugarRecord.git
synced 2024-08-16 18:00:26 +03:00
[examples/api] Add an example fetching items from the API and saving them into Realm
This commit is contained in:
parent
f059a68b10
commit
a1b664776e
@ -23,15 +23,15 @@ PODS:
|
||||
- Realm (= 1.1.0)
|
||||
- Result (3.0.0)
|
||||
- SnapKit (3.0.1)
|
||||
- SugarRecord (3.0.0-alpha.1):
|
||||
- SugarRecord/CoreData (= 3.0.0-alpha.1)
|
||||
- SugarRecord/CoreData+iCloud (= 3.0.0-alpha.1)
|
||||
- SugarRecord/Realm (= 3.0.0-alpha.1)
|
||||
- SugarRecord/CoreData (3.0.0-alpha.1):
|
||||
- SugarRecord (3.0.0-alpha.2):
|
||||
- SugarRecord/CoreData (= 3.0.0-alpha.2)
|
||||
- SugarRecord/CoreData+iCloud (= 3.0.0-alpha.2)
|
||||
- SugarRecord/Realm (= 3.0.0-alpha.2)
|
||||
- SugarRecord/CoreData (3.0.0-alpha.2):
|
||||
- Result (~> 3.0)
|
||||
- SugarRecord/CoreData+iCloud (3.0.0-alpha.1):
|
||||
- SugarRecord/CoreData+iCloud (3.0.0-alpha.2):
|
||||
- Result (~> 3.0)
|
||||
- SugarRecord/Realm (3.0.0-alpha.1):
|
||||
- SugarRecord/Realm (3.0.0-alpha.2):
|
||||
- RealmSwift (~> 1.1)
|
||||
- Result (~> 3.0)
|
||||
|
||||
@ -58,7 +58,7 @@ SPEC CHECKSUMS:
|
||||
RealmSwift: 838058b2db95b12cb86bd0cf209df642c33fb60a
|
||||
Result: 1b3e431f37cbcd3ad89c6aa9ab0ae55515fae3b6
|
||||
SnapKit: f818b8326d45b4e1c777d0ab27b5c0a3624bfdeb
|
||||
SugarRecord: 13f9d029c077dea63c7f7240dd401ac4af15a84c
|
||||
SugarRecord: 5d12c70dadef8e036edc795c76e533584b7da453
|
||||
|
||||
PODFILE CHECKSUM: 93e4a0d6049261cca889912a17deebad59571a81
|
||||
|
||||
|
@ -7,6 +7,9 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
23226F871D9C1ECF006A6769 /* NewsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23226F861D9C1ECF006A6769 /* NewsService.swift */; };
|
||||
23226F891D9C1F1A006A6769 /* RealmNew.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23226F881D9C1F1A006A6769 /* RealmNew.swift */; };
|
||||
23226F8B1D9C22B1006A6769 /* NewsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23226F8A1D9C22B1006A6769 /* NewsView.swift */; };
|
||||
23E13E5B1D96896300204C82 /* CoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E341D96896300204C82 /* CoreData.swift */; };
|
||||
23E13E5C1D96896300204C82 /* Realm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E351D96896300204C82 /* Realm.swift */; };
|
||||
23E13E5D1D96896300204C82 /* Track+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E381D96896300204C82 /* Track+CoreDataProperties.swift */; };
|
||||
@ -57,6 +60,9 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
199B6E9AFF9F22F151FCACD5 /* Pods-SugarRecord_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SugarRecord_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SugarRecord_Example/Pods-SugarRecord_Example.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
23226F861D9C1ECF006A6769 /* NewsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NewsService.swift; sourceTree = "<group>"; };
|
||||
23226F881D9C1F1A006A6769 /* RealmNew.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmNew.swift; sourceTree = "<group>"; };
|
||||
23226F8A1D9C22B1006A6769 /* NewsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NewsView.swift; sourceTree = "<group>"; };
|
||||
23E13E341D96896300204C82 /* CoreData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreData.swift; sourceTree = "<group>"; };
|
||||
23E13E351D96896300204C82 /* Realm.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Realm.swift; sourceTree = "<group>"; };
|
||||
23E13E381D96896300204C82 /* Track+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Track+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
@ -125,6 +131,40 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
23226F811D9C1E9D006A6769 /* News */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
23226F821D9C1EC6006A6769 /* Models */,
|
||||
23226F841D9C1EC6006A6769 /* Services */,
|
||||
23226F851D9C1EC6006A6769 /* Views */,
|
||||
);
|
||||
path = News;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
23226F821D9C1EC6006A6769 /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
23226F881D9C1F1A006A6769 /* RealmNew.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
23226F841D9C1EC6006A6769 /* Services */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
23226F861D9C1ECF006A6769 /* NewsService.swift */,
|
||||
);
|
||||
path = Services;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
23226F851D9C1EC6006A6769 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
23226F8A1D9C22B1006A6769 /* NewsView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
23E13E331D96896300204C82 /* Helpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -346,6 +386,7 @@
|
||||
23E13E7B1D96899000204C82 /* Examples */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
23226F811D9C1E9D006A6769 /* News */,
|
||||
23E13E7C1D96899000204C82 /* CoreData */,
|
||||
23E13E831D96899000204C82 /* Realm */,
|
||||
);
|
||||
@ -730,10 +771,13 @@
|
||||
23E13E931D96899000204C82 /* CoreDataBasicView.swift in Sources */,
|
||||
23E13E941D96899000204C82 /* BasicObject.swift in Sources */,
|
||||
23E13E9A1D96899000204C82 /* Random.swift in Sources */,
|
||||
23226F8B1D9C22B1006A6769 /* NewsView.swift in Sources */,
|
||||
23E13E921D96899000204C82 /* AppDelegate.swift in Sources */,
|
||||
23E13E9B1D96899000204C82 /* ViewController.swift in Sources */,
|
||||
23E13E981D96899000204C82 /* RealmBasicObject.swift in Sources */,
|
||||
23226F871D9C1ECF006A6769 /* NewsService.swift in Sources */,
|
||||
23E13E901D96899000204C82 /* Basic.xcdatamodeld in Sources */,
|
||||
23226F891D9C1F1A006A6769 /* RealmNew.swift in Sources */,
|
||||
23E13E951D96899000204C82 /* CoreDataBasicEntity.swift in Sources */,
|
||||
23E13E971D96899000204C82 /* RealmBasicEntity.swift in Sources */,
|
||||
23E13E961D96899000204C82 /* RealmBasicView.swift in Sources */,
|
||||
|
@ -0,0 +1,10 @@
|
||||
import Foundation
|
||||
import RealmSwift
|
||||
|
||||
class RealmNew: Object {
|
||||
|
||||
// MARK: - Attributes
|
||||
|
||||
dynamic var title: String = ""
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
import Foundation
|
||||
import SugarRecord
|
||||
import RealmSwift
|
||||
|
||||
class NewsService {
|
||||
|
||||
// MARK: - Attributes
|
||||
|
||||
private let session: URLSession
|
||||
private let apiKey: String
|
||||
private let storage: Storage
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
init(session: URLSession, storage: Storage, apiKey: String) {
|
||||
self.session = session
|
||||
self.storage = storage
|
||||
self.apiKey = apiKey
|
||||
}
|
||||
|
||||
convenience init(storage: Storage) {
|
||||
self.init(session: URLSession.shared, storage: storage, apiKey: "c7a6b4e8e221414b88a5883a98bbfbf9")
|
||||
}
|
||||
|
||||
// MARK: - Sync
|
||||
|
||||
internal func sync(completion: ((Swift.Error?) -> Void)? = nil) {
|
||||
let url = URL(string: "https://newsapi.org/v1/articles?source=the-next-web&sortBy=latest&apiKey=\(self.apiKey)")!
|
||||
self.session.dataTask(with: url) { [weak self] (data, _, error) in
|
||||
self?.save(data: data!)
|
||||
completion?(error)
|
||||
}.resume()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func save(data: Data) {
|
||||
guard let dict = try! JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { return }
|
||||
guard let articles = dict["articles"] as? [[String: Any]] else { return }
|
||||
DispatchQueue.main.async {
|
||||
_ = try? self.storage.operation { (context, save) -> Void in
|
||||
let existing = try context.fetch(FetchRequest<RealmNew>())
|
||||
try context.remove(existing)
|
||||
for article in articles {
|
||||
guard let title = article["title"] as? String else { return }
|
||||
let new: RealmNew = try context.create()
|
||||
new.title = title
|
||||
}
|
||||
save()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
100
Example/SugarRecord/Source/Examples/News/Views/NewsView.swift
Normal file
100
Example/SugarRecord/Source/Examples/News/Views/NewsView.swift
Normal file
@ -0,0 +1,100 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import SugarRecord
|
||||
import RealmSwift
|
||||
|
||||
class NewsView: UIViewController, UITableViewDelegate, UITableViewDataSource {
|
||||
|
||||
// MARK: - Attributes
|
||||
lazy var db: RealmDefaultStorage = {
|
||||
var configuration = Realm.Configuration()
|
||||
configuration.fileURL = URL(fileURLWithPath: databasePath("realm-news"))
|
||||
let _storage = RealmDefaultStorage(configuration: configuration)
|
||||
return _storage
|
||||
}()
|
||||
lazy var service: NewsService = {
|
||||
return NewsService(storage: self.db)
|
||||
}()
|
||||
lazy var tableView: UITableView = {
|
||||
let _tableView = UITableView(frame: CGRect.zero, style: UITableViewStyle.plain)
|
||||
_tableView.translatesAutoresizingMaskIntoConstraints = false
|
||||
_tableView.delegate = self
|
||||
_tableView.dataSource = self
|
||||
_tableView.register(UITableViewCell.classForCoder(), forCellReuseIdentifier: "default-cell")
|
||||
return _tableView
|
||||
}()
|
||||
var entities: [String] = [] {
|
||||
didSet {
|
||||
self.tableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
init() {
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
self.title = "News"
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Lifecycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setup()
|
||||
self.service.sync()
|
||||
let request = FetchRequest<RealmNew>()
|
||||
self.db.observable(request).observe { [weak self] (change) in
|
||||
switch change {
|
||||
case .initial(let values):
|
||||
self?.entities = values.map({$0.title})
|
||||
case .update(_, _, _):
|
||||
do {
|
||||
self?.entities = try self?.db.fetch(request).map({$0.title}) ?? []
|
||||
} catch {}
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
fileprivate func setup() {
|
||||
setupView()
|
||||
setupTableView()
|
||||
}
|
||||
|
||||
fileprivate func setupView() {
|
||||
self.view.backgroundColor = UIColor.white
|
||||
}
|
||||
|
||||
fileprivate func setupTableView() {
|
||||
self.view.addSubview(tableView)
|
||||
self.tableView.snp.makeConstraints { (make) -> Void in
|
||||
make.edges.equalTo(self.view)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - UITableViewDataSource / UITableViewDelegate
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return self.entities.count
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "default-cell")!
|
||||
cell.textLabel?.text = "\(entities[(indexPath as NSIndexPath).row])"
|
||||
return cell
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
|
||||
}
|
@ -56,7 +56,7 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega
|
||||
// MARK: - UITableViewDataSource / UITableViewDelegate
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return 2
|
||||
return 3
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
@ -66,6 +66,8 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega
|
||||
cell.textLabel?.text = "CoreData Basic"
|
||||
case 1:
|
||||
cell.textLabel?.text = "Realm Basic"
|
||||
case 2:
|
||||
cell.textLabel?.text = "News from API"
|
||||
default:
|
||||
cell.textLabel?.text = ""
|
||||
}
|
||||
@ -80,6 +82,8 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega
|
||||
self.navigationController?.pushViewController(CoreDataBasicView(), animated: true)
|
||||
case 1:
|
||||
self.navigationController?.pushViewController(RealmBasicView(), animated: true)
|
||||
case 2:
|
||||
self.navigationController?.pushViewController(NewsView(), animated: true)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user