我一直在使用Realm一段時間,我非常滿意!然而,我在實施過程中偶然發現了一些問題。什麼是最佳實踐 - 領域有序列表?
我做了一個測試場景,試圖指出我需要什麼輸入。
我有一個領域與個人對象的數據庫。這些都是在UITableView中呈現的。我想保持對象的特定順序,並且用戶應該能夠重新排序對象。從我讀過的,我必須使用Realms'List'來實現這一點。這也意味着我有一個名爲Person的類和一個名爲PersonList的類。 PersonList只有一個屬性: - 列表。
該應用程序應該只有一個PersonList對象的Realm,但可能有Person的幾個對象。
我的問題:
什麼是最好的做法是隻具有PersonList的一個實例在我的境界?正如你可以在下面的例子中看到的,我首先檢查是否存在,如果沒有,我創建它。
關於使用領域通知的最佳做法是什麼?將它添加到我的Realm中的一個PersonList對象的列表屬性中是否正確?
比方說,我想有一個單獨的類來處理我領域內的寫入事務。正如你在我的例子中看到的,所有的讀/寫事務都保存在UITableViewController類中 - 這被認爲是凌亂的嗎?
我的下面的例子應該能夠運行正常使用Xcode 8,Swift 3和Realm 1.1.0。
我很欣賞任何反饋和想法!
問候, 埃裏克
import UIKit
import RealmSwift
class PersonList : Object {
var list = List<Person>()
}
class Person : Object {
dynamic var favorite = false
dynamic var username : String?
dynamic var firstName : String?
dynamic var lastName : String?
var fullName : String? {
get {
guard let firstName = firstName, let lastName = lastName else {
return nil
}
return "\(firstName) \(lastName)"
}
}
}
class ViewController: UITableViewController {
var results : List<Person>?
var notificationToken: NotificationToken? = nil
func addPerson() {
let alert = UIAlertController(title: "Add Person", message: "Please fill in the information", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
alert.addAction(UIAlertAction(title: "Add", style: .default, handler: { alertAction in
if let firstNameTextField = alert.textFields?[0], let lastNameTextField = alert.textFields?[1] {
self.savePerson(firstName: firstNameTextField.text, lastName: lastNameTextField.text)
}
}))
alert.addTextField { (textField : UITextField!) -> Void in
textField.placeholder = "First Name"
}
alert.addTextField { (textField : UITextField!) -> Void in
textField.placeholder = "Last Name"
}
self.present(alert, animated: true, completion: nil)
}
func savePerson(firstName: String?, lastName: String?) {
guard let firstName = firstName, !firstName.isEmpty else {
let alert = UIAlertController(title: "Oops!", message: "First name missing!", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
return
}
guard let lastName = lastName, !lastName.isEmpty else {
let alert = UIAlertController(title: "Oops!", message: "Last name missing!", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
return
}
let realm = try! Realm()
let newPerson = Person()
newPerson.firstName = firstName
newPerson.lastName = lastName
newPerson.username = "\(Date())"
do {
try realm.write {
results?.append(newPerson)
}
}
catch let error {
print("Error: \(error)")
}
}
func editButtonAction(_ sender: UIBarButtonItem) {
if tableView.isEditing {
tableView.setEditing(false, animated: true)
sender.title = "Edit"
}
else {
tableView.setEditing(true, animated: true)
sender.title = "Done"
}
}
override func viewDidLoad() {
super.viewDidLoad()
let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(self.addPerson))
let editButton = UIBarButtonItem(title: "Edit", style: UIBarButtonItemStyle.plain, target: self, action: #selector(self.editButtonAction(_:)))
self.navigationItem.rightBarButtonItems = [addButton, editButton]
tableView.allowsSelectionDuringEditing = true
let realm = try! Realm()
//First, make sure a list exists in realm
if realm.objects(PersonList.self).first?.list == nil {
print("No existing list found in realm. Creating one.")
let defaultList = PersonList()
do {
try realm.write {
realm.add(defaultList)
}
}
catch let error { print("Error creating person list: \(error)") }
}
results = realm.objects(PersonList.self).first?.list
// Observe Results Notifications
notificationToken = results?.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in
guard let tableView = self?.tableView else { return }
switch changes {
case .initial:
// Results are now populated and can be accessed without blocking the UI
tableView.reloadData()
break
case .update(_, let deletions, let insertions, let modifications):
// Query results have changed, so apply them to the UITableView
tableView.beginUpdates()
tableView.insertRows(at: insertions.map { IndexPath(row: $0, section: 0) }, with: .automatic)
tableView.deleteRows(at: deletions.map { IndexPath(row: $0, section: 0) }, with: .automatic)
tableView.reloadRows(at: modifications.map { IndexPath(row: $0, section: 0) }, with: .automatic)
tableView.endUpdates()
break
case .error(let error):
// An error occurred while opening the Realm file on the background worker thread
print("Error: \(error)")
break
}
}
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return results?.count ?? 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let reuseIdentifier = "PersonTestCell"
var cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier)
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: reuseIdentifier)
}
if let results = self.results {
let person = results[indexPath.row]
cell!.textLabel?.text = person.fullName ?? "Name not found."
cell!.detailTextLabel?.text = person.username ?? "Username not found."
}
return cell!
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
if let results = self.results {
//Delete Person
let realm = try! Realm()
do {
try realm.write {
results.remove(objectAtIndex: indexPath.row)
}
}
catch let error {
print("Error: \(error)")
}
}
}
}
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.delete
}
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to toIndexPath: IndexPath) {
let realm = try! Realm()
do {
try realm.write {
results?.move(from: toIndexPath.row, to: fromIndexPath.row)
results?.move(from: fromIndexPath.row, to: toIndexPath.row)
}
}
catch let error {
print("Error: \(error)")
}
}
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
deinit {
notificationToken?.stop()
}
}
感謝您的詳細解釋!它讓我對事情更清楚。 – fisher