title: What are the best practices - Realm Ordered List?
body: <p>I have been using Realm for a while now and I am very happy with it!
  However, I have stumbled upon some questions during my implementation.</p>
  
  <p>I have made a test scenario to try to point out where I need some input.</p>
  
  <p>I have a realm with a database of Person objects. These are all presented in a UITableView. I want to keep a specific order of the objects, and the user should be able to reorder the objects. From what I've read I have to use Realms 'List' to achieve this. This again means I have one class called Person and one class that's called PersonList. The PersonList only has one property: - list.</p>
  
  <p>The app should only have one object of the PersonList in its Realm, but may have several objects of Person.</p>
  
  <p>My questions:</p>
  
  <ol>
  <li><p>What is the best practice to only have one instance of PersonList in my Realm? As you can see in my example below I first check if one exists, if not I create it.</p></li>
  <li><p>What is the best practice when it comes to the use of Realm Notifications. Is it correct to add it to the list property of the one PersonList object in my Realm?</p></li>
  <li><p>Let's say I want to have a seperate class that handles the write transactions in my Realm. As you can see in my example all the read/write transactions are kept in the UITableViewController class - is this considered messy?</p></li>
  </ol>
  
  <p>My example below should be able to run fine using Xcode 8, Swift 3 and Realm 1.1.0.</p>
  
  <p>I appreciate any feedback and thoughts!</p>
  
  <p>Regards,
  Erik</p>
  
  <pre><code>import UIKit
  import RealmSwift
  
  class PersonList : Object {
      var list = List&lt;Person&gt;()
  }
  
  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&lt;Person&gt;?
      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!) -&gt; Void in
              textField.placeholder = "First Name"
          }
          alert.addTextField { (textField : UITextField!) -&gt; 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) -&gt; Int {
          return 1
      }
  
      override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
          return results?.count ?? 0
      }
  
  
      override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; 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) -&gt; 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) -&gt; 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) -&gt; 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()
      }
  }
  </code></pre>