7 Replies
      Latest reply on May 19, 2018 11:08 PM by Claude31
      Pludan Level 1 Level 1 (0 points)

        Hello

         

        In the app you can add a text and a photo to each line.

        Now I want to delete the text and the photo in the line, which is clicked in the line.

         

         

         @IBAction func remove(_ sender: Any) {
                
                let query = PFQuery(className: "Post")
                query.whereKey("username", equalTo: PFUser.current()?.username)
                query.findObjectsInBackground(block: { (object, error) in
                    
                    if let posts = object {
                        for post in posts{
                            print(posts)
        
                            self.comments.remove(at: self.comments.index(of: post["message"] as! String)!)
                            self.imageFile.remove(at: self.imageFile.index(of: post["imageFile"] as! PFFile)!)
                           
                            self.tableView.reloadData()
        
            }
                        
                        DispatchQueue.main.async {
                            self.tableView.reloadData()
                        }
                    }
                })
            }

        Message in the line 13. Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

         

        I'm still a beginner and I'm not going any further.

         

        Can someone help me and show me how I need to do this delete function ?

        thank you very much

        best greetings

        • Re: Parse Delete a text and a photo in a line
          Claude31 Level 7 Level 7 (4,255 points)

          Could you show the output of

          print(posts)

           

          Error is line 13 (in fact probably 11 or 12) ?

           

          You have a lot of unwrap  !  that are not very safe.

           

          Cause is that you unwrap a nil ! It may be:

          - post has no field "message" or "imageFile" : hence post["message"] or post["imageFile"] is nil (take care to the exact spelling of message, including lower/uppercase

           

          - the type of post["message"] is not a String, hence a crash with as! String

           

          - the type of post["imageFile"] is not PFFile, hence a crash with as! PFFile

          Note: how did you define PFFile ? Is it a String ?

           

          - the index(of ) returns nil because not found

           

          a good way to avoid crash is to check:

           

          if let message = post["message"] as? String, let image = post["imageFile"] as? PFFile {
                if let messageIndex = self.comments.index(of: message), imageIndex = self.imageFile.index(of:image) {
                       self.comments.remove(at: messageIndex))
                       self.imageFile.remove(at: imageIndex)
                 }
          }
            • Re: Parse Delete a text and a photo in a line
              Pludan Level 1 Level 1 (0 points)

              Hello Claudio31

               

              Thank you for your answer.

               

              I've added your part. If I click on the Delete button, nothing happens.

               

              Have I added this incorrectly?

               

               @IBAction func remove(_ sender: Any) {
                      
                      let query = PFQuery(className: "Post")
                      query.whereKey("username", equalTo: PFUser.current()?.username)
                      query.findObjectsInBackground(block: { (object, error) in
                          
                          if let posts = object {
                              for post in posts{
                                  print(posts)
                                  
                                  if let message = post["message"] as? String, let image = post["imageFile"] as? PFFile {
                                      if let messageIndex = self.comments.index(of: message), let imageIndex = self.imageFile.index(of:image) {
                                          self.comments.remove(at: messageIndex)
                                          self.imageFile.remove(at: imageIndex)
                                      }
                                  }  
                                  self.tableView.reloadData()
              
                  }
                              
                              DispatchQueue.main.async {
                                  self.tableView.reloadData()
                              }
                          }
                      })
                  }
              
              

              With this code, I post the image and the text. This works.

              @IBAction func postImage(_ sender: Any) {
                      
                      if let image = imageTopost.image {
                          
                          let post = PFObject(className: "Post")
                          post["message"] = comment.text
                          post.saveEventually()
                          post["userId"] = PFUser.current()?.objectId
                          post.saveEventually()
                          post["username"] = PFUser.current()?.username
                          post.saveEventually()
                          if let imageData = UIImagePNGRepresentation(image){
                              
                              //Spinner
                              let activityIndicator = UIActivityIndicatorView(frame: CGRect(x:0, y: 0, width: 50, height: 50))
                              activityIndicator.center = self.view.center
                              activityIndicator.hidesWhenStopped = true
                              activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
                              view.addSubview(activityIndicator)
                              activityIndicator.startAnimating()
                              UIApplication.shared.beginIgnoringInteractionEvents()
                              
                              
                              let imageFile = PFFile(name: "image.png", data: imageData)
                              post["imageFile"] = imageFile
                              post.saveEventually()
                              post.saveInBackground(block: { (success, error) in
                              
                                  //Stop Spiner
                                  activityIndicator.stopAnimating()
                                  UIApplication.shared.endIgnoringInteractionEvents()
                                  
                                  
                                  if success {
                                      self.displayAlert(title: "Hat super geklappt", message: "Dein Ziel wurde erfolgreich hinzugefügt")
                                      self.comment.text = ""
                                      self.imageTopost.image = nil
                                  }else {
                                      self.displayAlert(title: "Etwas ist schiefgelaufen" , message: "Dein Bild konnte leider nicht gespeichert werden. Versuche es nochmal. Dein Internet muss eingeschalten sein." )
                                  }
                              })
                          }
                      }
                  }
              
              

               

               

              Greetings Daniel

                • Re: Parse Delete a text and a photo in a line
                  Claude31 Level 7 Level 7 (4,255 points)

                  You should answer all the questions from previous post.

                   

                  • Could you show the output of
                  print(posts) 
                  • how did you define PFFile ?

                   

                  When you click delete button, do you enter into remove ?

                   

                  Add some print statements to check and tell what you get exactly on console (it will be verbose, but that should help debug):

                   

                  @IBAction func remove(_ sender: Any) {
                      
                          print("Entered remove")     // ADD THIS
                          let query = PFQuery(className: "Post")
                          query.whereKey("username", equalTo: PFUser.current()?.username)
                          query.findObjectsInBackground(block: { (object, error) in
                          
                              if let posts = object {
                                      print(posts)               // ADD THIS
                  
                                 for post in posts{
                                      print(post)               // CHANGE THIS TO SEE INDIVIDUAL POST
                                  
                                      if let message = post["message"] as? String, let image = post["imageFile"] as? PFFile {
                                           print("message and image read", message, image)          // ADD THIS
                                          if let messageIndex = self.comments.index(of: message), let imageIndex = self.imageFile.index(of:image) {
                                              print("messageIndex", messageIndex)
                                              self.comments.remove(at: messageIndex)
                                              self.imageFile.remove(at: imageIndex)
                                          }
                                      }
                                      self.tableView.reloadData()
                                }
                              
                                  DispatchQueue.main.async {
                                      self.tableView.reloadData()
                                  }
                              }
                          })
                      }
                    • Re: Parse Delete a text and a photo in a line
                      Pludan Level 1 Level 1 (0 points)

                      This is the output:

                       

                      message and image read fjhsdjkfhdskj <PFFile: 0x600000451b80>

                      [<Post: 0x6000002a3ae0, objectId: OtH7UHh9nm, localId: (null)> {

                          imageFile = "<PFFile: 0x600000450860>";

                          message = text;

                          userId = VBTOwnVeED;

                          username = "test@test.ch";

                      }, <Post: 0x6000002a3f00, objectId: AoN9iybL7b, localId: (null)> {

                          imageFile = "<PFFile: 0x600000451430>";

                          message = "Text Diana";

                          userId = VBTOwnVeED;

                          username = "test@test.ch";

                      }, <Post: 0x6000002a3840, objectId: jL1wOLhzAj, localId: (null)> {

                          imageFile = "<PFFile: 0x60000044b700>";

                          message = "Einwenig text";

                          userId = VBTOwnVeED;

                          username = "test@test.ch";

                      }, <Post: 0x6000002a1ce0, objectId: uTL8P8qVF3, localId: (null)> {

                          imageFile = "<PFFile: 0x600000450170>";

                          message = text;

                          userId = VBTOwnVeED;

                          username = "test@test.ch";

                      }, <Post: 0x6000002a0060, objectId: JVLmJr1kYs, localId: (null)> {

                          imageFile = "<PFFile: 0x600000451be0>";

                          message = jdfnsdkfj;

                          userId = VBTOwnVeED;

                          username = "test@test.ch";

                      }, <Post: 0x6000002a36c0, objectId: iAAfck44OR, localId: (null)> {

                          imageFile = "<PFFile: 0x6000004512e0>";

                          message = text;

                          userId = VBTOwnVeED;

                          username = "test@test.ch";

                      }, <Post: 0x6000002a37e0, objectId: rPpAAPGGmq, localId: (null)> {

                          imageFile = "<PFFile: 0x600000451bb0>";

                          message = "Test text zum 123";

                          userId = VBTOwnVeED;

                          username = "test@test.ch";

                      }, <Post: 0x6000002a35a0, objectId: s3OO4gLEsi, localId: (null)> {

                          imageFile = "<PFFile: 0x600000451b80>";

                          message = fjhsdjkfhdskj;

                          userId = VBTOwnVeED;

                          username = "test@test.ch";

                      }, <Post: 0x6000002a00c0, objectId: BCImU0GeqU, localId: (null)> {

                          imageFile = "<PFFile: 0x600000451c40>";

                          message = Text;

                          userId = VBTOwnVeED;

                          username = "test@test.ch";

                      }]

                       

                      When you click Delete, this output appears

                      message and image read Text <PFFile: 0x600000451c40>

                       

                      A short message still appears:

                      entered remove

                • Re: Parse Delete a text and a photo in a line
                  junkpile Level 6 Level 6 (2,335 points)

                  Claude is on the case of the unwrapping optional issue, so I won't comment on that.

                   

                  But I will point out that calling self.tableView.reloadData() from a background thread (the first call, within the for loop) is a big no-no. You must dispatch all UIKit calls to the main thread, as you are doing with that DispatchQueue block after the loop.

                   

                  On the same topic of multithreading... consider the case where the main thread is busy happily updating your table view (calling your numberOfRows, cellForRow etc. methods) at the same time as this background thread is updating your "comments" and "imageFile" data structures. If those data structures are used by the main thread, then you may need to do some additional work adding synchronization and/or moving some of this processing over to the main thread too.