正确的方法将数据加载到TableView

时间:2016-06-22 09:42:40

标签: ios swift uitableview

我有一个应用程序从JSON数据加载问题列表并在TableView上显示它们。

大部分时间一切正常,但似乎我做错了,这就是为什么 - 应用程序崩溃。

它很少发生,因此难以检测,但我确信逻辑必定存在问题。

所以我有问题项的问题和数组的模型类:

class questionItem {
 var id = 0
 var title : String = ""
 var question : String = ""
}

var questions = [questionItem]()

在我的ViewController中我有TableView的IBOutlet,我将数据加载到viewDidLoad中

class QuestionsListVC: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet weak var questionsTableView: UITableView!

 override func viewDidLoad() {
    super.viewDidLoad()
    get_questions()
}

func get_questions()
{
    let request = NSMutableURLRequest(URL:myURL!)
    request.HTTPMethod = "POST"        
    let postString = ""

    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
        {
            data, response, error in

            if error != nil {
                print("error=\(error)")
                return
            }

            //clearing array for new items
            questions.removeAll(keepCapacity: false)

            dispatch_async(dispatch_get_main_queue(),{

                var json = JSON(data: data!)

                if let items =  json["questions"].array {
                    for item in items {
                        let question = questionItem()
                        question.id = item["id"].int!
                        question.title = item["title"].string!;
                        question.question = item["question"].string!
                        questions.append(question)
                    }
                }

                self.questionsTableView.reloadData()
            });         
    }
    task.resume()
}
}

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

错误显示在cellForRowAtIndexPath

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell : QuestionsListCell = self.questionsTableView.dequeueReusableCellWithIdentifier("QuestionsListCell") as! QuestionsListCell

    //error happens here - Index out of range
        print(questions[indexPath.row].title)

在6个案例中发生了一次,并且在6个测试中的其他5个中没有错误 - 但我不明白为什么。

4 个答案:

答案 0 :(得分:1)

这指出了

的问题
numberOfSectionsInTableView

和/或

numberOfRowsInSection

你能发布这些当前的实现吗?

如果只显示一个连续列表,则numberOfSectionsInTableView应始终返回1,并且您需要检查numberOfRowsInSection是否准确返回数据源中的项目数。

修改

您是否可以在使用新项目更新之前立即清除主线程上的现有数据源,如下面的代码所示:

        dispatch_async(dispatch_get_main_queue(),{

        questions.removeAll(keepCapacity: false)

            var json = JSON(data: data!)

            if let items =  json["questions"].array {
                for item in items {
                    let question = questionItem()
                    question.id = item["id"].int!
                    question.title = item["title"].string!;
                    question.question = item["question"].string!
                    questions.append(question)
                }
            }

            self.questionsTableView.reloadData()
        });         

答案 1 :(得分:1)

您的代码中对questions.removeAll的调用会使以下事件序列成为可能:

    numberOfRowsInSection之前调用
  • questions.removeAll,返回旧的非零容量
  • questions.removeAll清除questions
  • 在重新填充cellForRowAtIndexPath之前调用
  • questions,导致索引超出范围异常

一种解决方法是相对简单的:制作一个newQuestions数组,在get_questions中填充它,并在调用numberOfRowsInSection时将其交换:

// Add this to your class
var newQuestions : [questionItem]

// Change get_questions:
dispatch_async(dispatch_get_main_queue(), {
    var json = JSON(data: data!)
    if let items =  json["questions"].array {
        var tmpQuestions = [questionItem]()
        for item in items {
            let question = questionItem()
            question.id = item["id"].int!
            question.title = item["title"].string!;
            question.question = item["question"].string!
            tmpQuestions.append(question)
        }
        newQuestions = tmpQuestions
        self.questionsTableView.reloadData()
    }
});

// Change numberOfRowsInSection
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
    if newQuestions != nil {
        questions = newQuestions
        newQuestions = nil
    }
    return questions.count
}

请注意get_questions如何不直接填充newQuestions。相反,它会构建tmpQuestions,并仅在完全构建时将其设置为newQuestions

答案 2 :(得分:0)

尝试使用以下代码,

find . -name \*.txt -maxdepth 1 -print0 | xargs -0 -n 1000 rename ....

使用此方法更改cellForRow。希望这会对你有所帮助。

答案 3 :(得分:0)

为了避免崩溃,我会添加以下三项安全检查。

<强> 1。清除前检查阵列计数。

if questions.count > 0
{
      questions.removeAll()
}

<强> 2。在表重新加载

之前检查数组计数
if questions.count > 0
{
      self.questionsTableView.reloadData()
}

第3。在cellForRowAtIndex方法中,在放入Cell之前检​​查对象数组中的值

if let objModel : questionItem = questions[indexPath.row] as? questionItem
{
          print(" title is \(objModel.title)")
}