UITableView empty after a reloadData() from NSNotificationCenter

866 views Asked by At

I have a problem with my UITableView. It is always empty.

Abstract: I have got a model class. After the instantiation of the model in the method viewDidLoad in my UITableViewController it will grab asynchronously a JSON-struct from my server. This data will be parse to my object.

My UITableViewController also has a NSNotification Observer with a selector method. This selector method will be triggered if the model class post the notification (post notification if the model is done with requesting and parsing the data from server).

The selector method will execute a "self.tableView.reloadData()" in a dispatch main-queue block.

The debugger shows that the object is not nil but the tableView is empty. I do not have an idea why the tableview is empty.

Parts from my UITableViewController:

import UIKit

class BillingPlanTableViewController: UITableViewController {

@IBOutlet weak var menuButton: UIBarButtonItem!
var budgetBillingPlansModel: BudgetBillingPlanModel!

// MARK: - Lifecycle
override func viewDidLoad() {
    super.viewDidLoad()

    //Menu gesture recognizer
    if self.revealViewController() != nil {
        menuButton.target = self.revealViewController()
        menuButton.action = "revealToggle:"
        self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }

    //initialize BudgetBillingPlansModel
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "initBbPDone:",name:"initBbPDone", object: nil)
    budgetBillingPlansModel = BudgetBillingPlanModel()
    println(budgetBillingPlansModel)
}


// MARK: - Custom Methods
func initBbPDone(notification: NSNotification){
    //reload tableview: from in thread: Zu diesem Zeitpunkt ist mein Objekt gefüllt.
    dispatch_async(dispatch_get_main_queue(),{
        self.tableView.reloadData()
    });



}


// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {

    if(self.budgetBillingPlansModel.checkBbPisReady()){
        return self.budgetBillingPlansModel.getBudgetBillingPlanModel()!.getBbpArray().count
    }else{
        return 0
    }

}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    if(self.budgetBillingPlansModel.checkBbPisReady()){
        var numberOfRowsInSection: Int = 0

        for(var index = 0; index < self.budgetBillingPlansModel.getBudgetBillingPlanModel()!.getBbpArray().count; index++){
            if(index == section){
                numberOfRowsInSection = self.budgetBillingPlansModel.getBudgetBillingPlanModel()!.getBbpArray()[index].getSubPlan().count
            }
        }

        return numberOfRowsInSection
    }else{
        return 0
    }

}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("budgetBillingPlans", forIndexPath: indexPath) as! BudgetBillingPlanTableViewCell


    if(self.budgetBillingPlansModel.checkBbPisReady()){
        //section == bbP Array
        for(var i = 0; i < self.budgetBillingPlansModel.getBudgetBillingPlanModel()!.getBbpArray().count; i++){
            if(i == indexPath.section){
                //row == subPlans Array
                let subPlans: [SubPlan] = self.budgetBillingPlansModel.getBudgetBillingPlanModel()!.getBbpArray()[i].getSubPlan()
                for(var j = 0; j < subPlans.count; j++){
                    if(j == indexPath.row){
                        cell.ibo_header.text = "\(self.budgetBillingPlansModel.getBudgetBillingPlanModel()!.getBbpArray()[i].getSubPlan()[j].getSbbpDivisionName())"
                        cell.ibo_budgetAmount.text = "\(self.budgetBillingPlansModel.getBudgetBillingPlanModel()!.getBbpArray()[i].getSubPlan()[j].getSbbpActAmount())"
                        cell.ibo_contract.text = "\(self.budgetBillingPlansModel.getBudgetBillingPlanModel()!.getBbpArray()[i].getSubPlan()[j].getSbbpContractNumber())"
                        cell.ibo_date.text = (self.budgetBillingPlansModel.getBudgetBillingPlanModel()!.getBbpArray()[i].getFirstAdjustmentDate()) +  " " + (self.budgetBillingPlansModel.getBudgetBillingPlanModel()!.getBbpArray()[i].getbbpCycleName())
                    }
                }
            }
        }
    }else{

    }

    return cell
}

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return 150
}

}

Parts from my model class:

class BudgetBillingPlanModel: NSObject {
var budgetBillingPlan: BudgetBillingPlan!
var bbPisReady: Bool!
//getBudgetBillingPlans
private func getBudgetBillingPlans(){
    Alamofire.request(.GET, Constants.service_getBudgetBillingPlans)
        .responseString { (request, response, jsonString, error) in
            println(error)// error ist im debugger-Zeitpunkt == nil
            self.budgetBillingPlan = self.parseServerResponse(jsonString!)
            self.setbbPisReady()
    }
}
//Notifications
private func setbbPisReady(){
    self.bbPisReady = true
    //object controller has to implement the notification method with "initBbPDone"
    NSNotificationCenter.defaultCenter().postNotificationName("initBbPDone", object: nil)
}
//check status
func checkBbPisReady()->Bool{
    if(self.bbPisReady == true){
        return true
    }else{
        return false
    }
}
//getter
func getBudgetBillingPlanModel()->BudgetBillingPlan?{
    if(self.checkBbPisReady()){
        return self.budgetBillingPlan
    }else{
        return nil
    }
}

Debugger Screenshot:

enter image description here

Addition: If I try to init the tableView with static cells, it will shows the static cells. But after the instantiation in viewDidLoad, when the notification is fired the tableview is empty. If I interact with the empty tableView like a pan or tap gesture I will get the error: EXC_bad_Access in the appdelegate ( thread1 )

1

There are 1 answers

0
iach On

I didn't find out the problem with the Notification-pattern for the mvc communication, but I think it was an issue with the threads. The solution was that I switch to the kvc-pattern, now my tableView is not longer empty.