Home Completion handler issues
Reply: 0

Completion handler issues

user8526
1#
user8526 Published in June 21, 2018, 4:40 am

So I have a tableview controller which has headers and cells which are supposed to be present under those headers. I have already done the job of correctly creating the headers. I currently have prepared the datasource for the cells which takes its content from the a list of currentEvents that a user is currently attending. The issue isn't the pulling of the data it seems to be the completion block. It takes so long to come back that the currentEvents array never gets appended when it is supposed to. It also keeps appending events onto the original array even after it should reset upon entering the new section. I have tried many things and moved code around many places but nothing seems to be having any effect

The key function in all this is

self.fetchEventsFromServer()

specifically the part where the EventService.show takes place

import UIKit
import Firebase

class FriendsEventsView: UITableViewController{
    var cellID = "cellID"
    var friends = [Friend]()
    var attendingEvents = [Event]()
    //label that will be displayed if there are no events
    var currentUserName: String?
    var currentUserPic: String?
    var currentEventKey: String?

    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "Friends Events"
        view.backgroundColor = .white
        // Auto resizing the height of the cell
        tableView.estimatedRowHeight = 44.0
        tableView.rowHeight = UITableViewAutomaticDimension
        self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "close_black").withRenderingMode(.alwaysOriginal), style: .done, target: self, action: #selector(self.goBack))
        tableView.register(EventDetailsCell.self, forCellReuseIdentifier: cellID)
        self.tableView.tableFooterView = UIView(frame: CGRect.zero)



    }
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        DispatchQueue.global(qos: .background).async {
            print("This is run on the background queue")
            self.fetchEventsFromServer { (error) in
                if error != nil {
                    print(error)
                    return
                } else {
                    DispatchQueue.main.async {
                        self.tableView.reloadData()
                        print("This is run on the main queue, after the previous code in outer block")
                    }

                }
            }


        }

    }

    @objc func goBack(){
        dismiss(animated: true)
    }
    override func numberOfSections(in tableView: UITableView) -> Int {
       // print(friends.count)
        return friends.count
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
       // print(friends[section].events.count)
        return friends[section].collapsed ? 0 : friends[section].events.count
    }
    func tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as! EventDetailsCell? ?? EventDetailsCell(style: .default, reuseIdentifier: cellID)
       // print(indexPath.row)
        cell.details = friends[indexPath.section].events[indexPath.row]
        return cell
    }

    override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "header") as? CollapsibleTableViewHeader ?? CollapsibleTableViewHeader(reuseIdentifier: "header")
       // print(section)
        header.arrowLabel.text = ">"
        header.setCollapsed(friends[section].collapsed)
        print(friends[section].collapsed)
        header.section = section
       // header.delegate = self
        header.friendDetails = friends[section]
        return header
    }
    override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 50
    }

   func fetchEventsFromServer(_ completion: @escaping (_ error: Error?) -> Void ){
        //will grab the uid of the current user

        guard let myUserId = Auth.auth().currentUser?.uid else {
            return
        }
        let ref = Database.database().reference()
        //checking database for users that the current user is following
        ref.child("following").child(myUserId).observeSingleEvent(of: .value, with: { (followingSnapshot) in
           //handling potentail nil or error cases
            guard let following = followingSnapshot.children.allObjects as? [DataSnapshot]
                else {return}

            //validating if proper data was pulled
            let group = DispatchGroup()
            for followingId in following {
                group.enter()
                print(followingId.key)
                ref.child("users").child(followingId.key).observeSingleEvent(of: .value, with: { (userInfoSnapShot) in
                    guard let followingUserInfo = userInfoSnapShot.children.allObjects as? [DataSnapshot] else {
                        return
                    }
                    //validating if proper data was pulled for each follower
                    for currentUserInfo in followingUserInfo {
                        //will add this back when I want to event implementation
                        if currentUserInfo.key == "Attending" {
                            guard let eventKeys = currentUserInfo.children.allObjects as? [DataSnapshot] else{return}
                            for event in eventKeys {
                                print(event.key)
                                EventService.show(forEventKey: event.key, completion: { (event) in
                                    guard let currentEvent = event else{
                                        return
                                    }
                                    self.attendingEvents.append(currentEvent)
                                    print(self.attendingEvents.count)
                                })

                            }
                        }
                        if currentUserInfo.key == "profilePic"{
                            self.currentUserPic = currentUserInfo.value as! String
                            //print(self.currentUserPic)
                        }
                        if currentUserInfo.key == "username"{
                            self.currentUserName = currentUserInfo.value as! String
                            //print(self.currentUserName)
                            var friend = Friend(friendName: self.currentUserName!, events: self.attendingEvents, imageUrl: self.currentUserPic!)
                            print(friend.events.count)
                            self.friends.append(friend)
                            //print(self.friends.count)
                        }


                    }
                    group.leave()
                    let result = group.wait(timeout: .now() + 0.01)
                    completion(nil)
                }, withCancel: { (err) in
                    completion(err)
                    print("Couldn't grab info for the current list of users: \(err)")
                })
            }
            completion(nil)

        }) { (err) in
            completion(err)
            print("Couldn't grab people that you are currently following: \(err)")
        }

    }
}

If anyone sees something I don't please dont hesitate to say something How would I alter my dispatch group implementation to accomplish this goal

EventService Function

struct EventService {

    static func show(forEventKey eventKey: String, completion: @escaping (Event?) -> Void) {
        // print(eventKey)
        let ref = Database.database().reference().child("events").child(eventKey)
       //  print(eventKey)
        //pull everything
        ref.observeSingleEvent(of: .value, andPreviousSiblingKeyWith: { (snapshot,eventKey) in
        //    print(snapshot.value ?? "")
            guard let event = Event(snapshot: snapshot) else {
                return completion(nil)
            }

           completion(event)
        })
    }
}
You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.313429 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO