Rioner Rioner - 3 months ago 9
Swift Question

UITableViewController disappears after asynchronous query

Hoping you can help me out...I've been trying to figure this issue out for a couple days now.

I'm using Parse (www.parse.com) as my backend, and have hosted it on my own AWS server.

Structure of the app:
In AppDelegate, if user is logged in, show a ViewController that sets up my SlideMenuControllerSwift (https://github.com/dekatotoro/SlideMenuControllerSwift) and my TabBarController.
[Storyboard][1]

In my tab bar controller, I have a navigation controller that leads to a UITableViewController that segues to another UITableViewController when I click on a row.

Problem:
http://imgur.com/izdCBgt

1) I click on a row and it performs an asynch query to my parse database

2) The data populates the table and then disappears

3) If I change the tab and go back to the main tab, the data reappears

Also

1) I click on a row and it performs an asynch query to my parse database

2) The data populates the table and then disappears

3) If I go back to the original UITableViewController, it does not transition back properly, and I need to change tabs back and forth until it reappears

Code:

I segue to the documents table view controller using the storyboard segue. Here is the relevant code in my DocumentsTableViewController:

class DocumentTableViewController: UITableViewController, UIDocumentInteractionControllerDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate, MMCropDelegate {

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
print("initDocs")
}

var specificDocs=[Document](){
didSet{
dispatch_async(dispatch_get_main_queue(), {
//we might be called from the parse block which executes in seperate thread
self.loadView()
})
}
}


override func viewDidLoad() {
tableView.dataSource = self
tableView.delegate = self

print("we loadeD")
super.viewDidLoad()

navigationItem.title = "Job Documents"

let cameraButton = UIBarButtonItem(image: UIImage(named: "Camera"), style: .Plain, target: self, action: #selector(self.didPressCamera(_:)))
navigationItem.rightBarButtonItem = cameraButton

self.queryForTable()

}

override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.tableView.reloadData()
}


// Define the query that will provide the data for the table view
func queryForTable() {
// Run a spinner to show a task in progress
let progressHUD = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
progressHUD.label.text = "Loading..."

//2 using those jobActions to find which documents are mine
let query = PFQuery(className: Document.parseClassName())
query.whereKey(Document.jobActionCol(), containedIn: jobActions)
query.includeKey(Document.documentCategoryCol())
// do {
// let test = try query.findObjects()
// self.specificDocs = test as! [Document]
// progressHUD.hideAnimated(true)
// } catch {
// print("error!")
// }
// FIND WHY THIS DOESNT WORK....WHAT THE F
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
self.specificDocs = objects as! [Document]
print("done")
progressHUD.hideAnimated(true)

} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
}
}


// MARK: - Table view data source

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return specificDocs.count

}

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

var cell:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("cellIdentifier")
if ((cell) == nil){
cell = UITableViewCell.init(style: .Default, reuseIdentifier: "cellIdentifier")
}

cell!.textLabel?.text = specificDocs[indexPath.row].documentCategory!.type!
print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
// print(UIApplication.sharedApplication().keyWindow?.performSelector("recursiveDescription"))
return cell!
}


deinit {
print("docs deinit")
}
}

Answer

Oh, now I see intention of your codes. But, Do you have some reason that doing? It isn't right way that directly call loadView().

tableView.dataSource = self
tableView.delegate = self

move to first in viewWillAppear and, It will be work except too fast done to receive from parse.

Normal way will be like below:

var specificDocs=[Document](){
didSet{
    dispatch_async(dispatch_get_main_queue(), {
        //we might be called from the parse block which executes in seperate thread
        self.loadView()
    })
}

self.loadView() to self.tableView.reloadData().

tableView.dataSource = self
tableView.delegate = self

That doesn't needs.

override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.tableView.reloadData()}

That doesn't needs too.

Anyway, your codes will work just modify calling self.loadView() to self.tableView.reloadData()

Comments