0

I'm trying to retrieve data from Parse to append to my array of Groups:

var displayedGroups = [Groups]()

Groups is a struct:

struct Groups{
    let name: String?
    let date: Date
    let number: Int
    let id: String

    init(id: String, name: String, date: Date, number: Int) {
        self.id = id
        self.name = name
        self.date = date
        self.number = number
    }
}

this is the function that I try to retrieve data with:

func getDisplayedGroups() {
        let query = PFQuery(className: "MeetUps")
        print(PFUser.current()?.username)
        query.whereKey("peeps", contains: PFUser.current()?.username)
        query.findObjectsInBackground { (objects, error) in
            if error != nil {
                print(error)
            } else if let objects = objects {
                for meetUps in objects {
                    let peeps = (meetUps["peeps"] as! [String])
                    let id = meetUps.objectId!
                    //let name = meetUps["meetUpName"] as? String
                    let date = meetUps["when"] as! Date
                    let group = Groups(id: id, name: " ", date: date, number: peeps.count)
                    print(group)
                    self.displayedGroups.append(group)
                }
            }
        }
        for i in displayedGroups {
            print(i)
        }
        tableView.reloadData()
    }

I've commented out let name = meetUps["meetUpName"]... because there are nil values in my parse dashboard's "meetUpName"-key column.

print(group) works and it prints a different group for every loop.

however, this block:

for i in displayedGroups {
                print(i)
            }

doesn't print at all :/ and as such my table isn't loading data from displayedGroups. has it got to do with asynchronous? shouldn't be right? since they are in the same block. I have no idea, please advise. Thanks!

5
  • 1
    query.findObjectsInBackground is not on the main thread. thus your for loop will run while query.findObjectsInBackground is running in the background. Your displayedGroups will always be null Commented Oct 12, 2016 at 6:59
  • It's probably nicer to use map rather than for and append. Commented Oct 12, 2016 at 7:20
  • @AlexanderMomchliov you mind explaining further? Commented Oct 12, 2016 at 13:32
  • or any reading you can point me to? @AlexanderMomchliov Commented Oct 12, 2016 at 13:34
  • @KwokWenJian useyourloaf.com/blog/swift-guide-to-map-filter-reduce Commented Oct 12, 2016 at 18:57

2 Answers 2

1

findObjectsInBackground works asynchronously, put the loop and the line to reload the table view in the completion block.

You might need to reload the table view on the main thread.

...
    for meetUps in objects {
      let peeps = (meetUps["peeps"] as! [String])
      let id = meetUps.objectId!
      //let name = meetUps["meetUpName"] as? String
      let date = meetUps["when"] as! Date
      let group = Groups(id: id, name: " ", date: date, number: peeps.count)
      // print(group)
      self.displayedGroups.append(group)
    }
    for i in displayedGroups {
      print(i)
    }
    dispatch_async(dispatch_get_main_queue) {
       self.tableView.reloadData()
    }
...
Sign up to request clarification or add additional context in comments.

3 Comments

after slotting my code into the completion block, it seems like even without dispatch_async(dispatch_get_main_queue), it works. would you explain to me why?
I cannot imagine but findObjectsInBackground might work on the main thread, too. It's always good programming habit to dispatch code affecting the UI to the main thread in background operations.
I'm not very sure when to use the main queue, because I'm not sure if putting it there might mean the code runs before the code preceding it has not completed running. do you mind explaining to me how main thread works or point me to any readings that would help me?
0

From the code as the name suggests findObjectsInBackground runs in background ,that means it runs in different thread and not in main thread.So the below lines will be executed

for i in displayedGroups {
        print(i)
    }
    tableView.reloadData()

before finishing the background operation.

Kindly move the above code inside the completion block and don't forget to reloadData from main thread.

Edited function:

func getDisplayedGroups() {
let query = PFQuery(className: "MeetUps")
print(PFUser.current()?.username)
query.whereKey("peeps", contains: PFUser.current()?.username)

query.findObjectsInBackground { (objects, error) in
    if error != nil {
        print(error)
    } else if let objects = objects {
        for meetUps in objects {
            let peeps = (meetUps["peeps"] as! [String])
            let id = meetUps.objectId!
            //let name = meetUps["meetUpName"] as? String
            let date = meetUps["when"] as! Date
            let group = Groups(id: id, name: " ", date: date, number: peeps.count)
            print(group)
            self.displayedGroups.append(group)
        }
    }
    for i in self.displayedGroups {
        print(i)
    }
    dispatch_async(dispatch_get_main_queue()) {

    tableView.reloadData()
    }
}
}
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.