title: Child Updated crashing table (indexPath is out of range error that crashes my app Error)
body: <p>I am having a hard time updating an array in my app that controls a table. I want to be able to change a child node in Firebase Database and have it update on my users' end without me having to code and send an update. I need to be able to change their tag and have it update the table without the index being out of range.</p>
  <p>Here is my Class Struct for the information for the users:</p>
  <pre><code>import UIKit
  
  class User: NSObject {
      var Name: String?
      var Email: String?
      var UID: String?
      var Tag: String?
  </code></pre>
  <p>}</p>
  <p>In my controller I have the following code to initialize the table with the info from Firebase:</p>
  <pre><code>func CreateDataArray() {
      
      Database.database().reference().child(&quot;Users&quot;).observe(.childAdded, with: { (snapshot) in
          
          if let dictionary = snapshot.value as? [String: AnyObject] {
              
              let user = User()
              //self.setValuesForKeys(dictionary)
              user.Name = dictionary[&quot;Name&quot;] as? String
              user.Email = dictionary[&quot;Email&quot;] as? String
              user.UID = dictionary[&quot;UID&quot;] as? String
              user.Tag = dictionary[&quot;Tag&quot;] as? String
              
              if user.Tag == &quot;Macro&quot; {
                              self.macroUsersArray.append(user)
              } else if user.Tag == &quot;Micro&quot; {
                              self.microUsersArray.append(user)
                          }
              
              self.users.append(user)
              self.userName.append(user.Name!)
              self.filteredNames.append(user.Name!)
              
              print(dictionary)
              print(self.macroUsersArray)
              
              DispatchQueue.main.async {
              self.tableView.reloadData()
                  }
              }
          }, withCancel: nil)
      
      }
  </code></pre>
  <p>I then have a function that listens for any changes from my Firebase and updates the arrays:</p>
  <pre><code>func updateDataArray() {
      
      Database.database().reference().child(&quot;Users&quot;).observe(.childChanged, with: { (snapshot) in
          
          if let dictionary = snapshot.value as? [String: AnyObject] {
              
              let user = User()
              //self.setValuesForKeys(dictionary)
              user.Name = dictionary[&quot;Name&quot;] as? String
              user.Email = dictionary[&quot;Email&quot;] as? String
              user.UID = dictionary[&quot;UID&quot;] as? String
              user.Tag = dictionary[&quot;Tag&quot;] as? String
              
              if user.Tag == &quot;Macro&quot; {
                  self.microUsersArray.remove(at: 2)
              } else if user.Tag == &quot;Micro&quot; {
                  self.macroUsersArray.remove(at: 2)
                          }
              
              self.users.append(user)
              self.userName.append(user.Name!)
              self.filteredNames.append(user.Name!)
              
              print(dictionary)
              print(self.macroUsersArray)
              
              DispatchQueue.main.async {
              self.tableView.reloadData()
                  }
              }
          }, withCancel: nil)
      
      }
  </code></pre>
  <p>I want to get the user that originally had the tag &quot;macro&quot; that got switch to &quot;micro&quot; to be removed from the macro list and show up in the micro list. I am not able to get the arrays to append and keep getting the indexPath is out of range error that crashes my app. I really need help and have been struggling with this the last few weeks.</p>
  <p>Edit: I have decided to use observe.value so that when I make changes it reads it. Here is my code for creating the users' info:</p>
  <pre><code>func CreateDataArray() {
      
      Database.database().reference().child(&quot;Users&quot;).observe(.value, with: { (snapshot) in
          
          if let dictionary = snapshot.value as? [String: AnyObject] {
              
              let user = User()
              //self.setValuesForKeys(dictionary)
              user.Name = dictionary[&quot;Name&quot;] as? String
              user.Email = dictionary[&quot;Email&quot;] as? String
              user.Tag = dictionary[&quot;Tag&quot;] as? String
              
              if user.Tag == &quot;Macro&quot; {
                              self.macroUsersArray.append(user)
              } else if user.Tag == &quot;Micro&quot; {
                              self.microUsersArray.append(user)
                          }
              
              self.users.append(user)
              self.userName.append(user.Name!)
              self.filteredNames.append(user.Name!)
              
              print(dictionary)
              print(self.macroUsersArray)
              
              DispatchQueue.main.async {
              self.tableView.reloadData()
                  }
              }
          }, withCancel: nil)
      
      }
  </code></pre>
  <p>However, I am able to pull all the data into a snapshot but it is returning nil when I try to append. I am getting an error of nil on any line of code with &quot;append(User.Name!)</p>
  <p>I would love to figure out how to stop this nil and allow my observer to keep listening for changes in my database.</p>
  <p><strong>EDIT 2:</strong></p>
  <p>Here are my variables:</p>
  <pre><code>var allUsersArray = [User]()
  var macroUsersArray = [User]()
  var microUsersArray = [User]()
  </code></pre>
  <p>Here is my ViewDidLoad:</p>
  <pre><code> override func viewDidLoad() {
          super.viewDidLoad()
          
          updateDataArray()
          
      }
  </code></pre>
  <p>Here is my updateDataArray code:</p>
  <pre><code>func updateDataArray() {
      
      Database.database().reference().child(&quot;Users&quot;).observe(.childAdded, with: { (snapshot) in
          
          if let dictionary = snapshot.value as? [String: AnyObject] {
              
              let user = User()
              //self.setValuesForKeys(dictionary)
              user.Name = dictionary[&quot;Name&quot;] as? String
              user.Email = dictionary[&quot;Email&quot;] as? String
              user.UID = dictionary[&quot;UID&quot;] as? String
              user.Tag = dictionary[&quot;Tag&quot;] as? String
              
              self.allUsersArray.append(user)
              self.users.append(user)
              self.userName.append(user.Name!)
              self.filteredNames.append(user.Name!)
  
              self.macroUsersArray = self.allUsersArray.filter { $0.Tag == &quot;Macro&quot; }
              self.microUsersArray = self.allUsersArray.filter { $0.Tag == &quot;Micro&quot; }
              self.observeChangeInUserProperty()
              
              DispatchQueue.main.async {
              self.tableView.reloadData()
                  }
              }
          }, withCancel: nil)
      
      }
  </code></pre>
  <p>Here is the observeChangeInUserProperty() function:</p>
  <pre><code>func observeChangeInUserProperty() {
      let ref = Database.database().reference().child(&quot;Users&quot;).child(&quot;Talent&quot;)
      ref.observe(.childChanged, with: { snapshot in
          let key = snapshot.key
          
          let tag = snapshot.childSnapshot(forPath: &quot;Tag&quot;).value as! String // ! = never optional
          //get the user from the allUsersArray by its key
          if let user = self.allUsersArray.first(where: { $0.Tag == key }) {
              if user.Tag != tag { //if the tag changed, handle it
                  user.Tag = tag //update the allUsersArray
                  if tag == &quot;Macro&quot; { //if the new tag is Macro remove the user from the Micro array
                      if let userIndex = self.microUsersArray.firstIndex(where: { $0.Tag == key }) {
                          self.microUsersArray.remove(at: userIndex)
                          self.macroUsersArray.append(user) //add user to macro array
                      }
                  } else { //new type is micro so remove from macro array
                      if let userIndex = self.macroUsersArray.firstIndex(where: { $0.Tag == key }) {
                          self.macroUsersArray.remove(at: userIndex)
                          self.microUsersArray.append(user)
                      }
                  }
                  //reload the tableviews to reflect the changes
                  self.microTableView.reloadData()
                  self.tableView.reloadData()
                  
              }
          }
      })
  }
  </code></pre>
  <p>I am getting empty arrays for Macro and Micro. I don't know what I am doing wrong.</p>
  <p><strong>EDIT 3:</strong></p>
  <p>Here is my new user struct with initialization from Firebase:</p>
  <pre><code>import UIKit
  import Firebase
  
  class User: NSObject {
      var Name: String?
      var Email: String?
      var UID: String?
      var Tag: String?
  
      init?(from snapshot: DataSnapshot) {
  
          let dictionary = snapshot.value as? [String: Any]
      
              self.Name = dictionary![&quot;Name&quot;] as? String
              self.Email = dictionary![&quot;Email&quot;] as? String
              self.UID = dictionary![&quot;UID&quot;] as? String
              self.Tag = dictionary![&quot;Tag&quot;] as? String
  
          }
      }
  </code></pre>
  <p>I am now able to append the arrays but they are not populating my tables. I can also change the user's tag in Firebase without the app crashing but it doesn't observe the changed Tag and move the user to the other array. So I need help with those two things.</p>