2016-01-24 2 views
2

У меня есть приложение, которое извлекает информацию из базы данных Parse и отображает ее в UITableView. Я извлекаю информацию из parse в функции viewWillAppear, и я показываю ее в функции tableView (cellForRowAtIndexPath). Иногда я получаю сообщение об ошибке, потому что массив, в котором хранится информация о парсе, имеет длину 0 и я пытаюсь получить доступ к информации по индексу за пределами границ массива. Я считаю, что это потому, что cellForRowAtIndexPath вызывается до того, как viewWillAppear закончит работу. Возможно ли это, или моя ошибка определенно происходит откуда-то еще?CellForRowAtIndexPath вызывается перед запуском ViewWillAppear

EDIT: ошибка не происходит каждый раз, и я не могу найти способ, чтобы воспроизвести его

override func viewWillAppear(animated: Bool) { 

    //begin ignoring events until the information is finished being pulled 
    UIApplication.sharedApplication().beginIgnoringInteractionEvents() 

    resultsArray.removeAll(keepCapacity: false) 

    //run query 
    let query = PFQuery(className: "Answers") 
    query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in 

     if let objects = objects { 

        //append information to the resultsArray 
       } 
      } 
      self.tableView.reloadData() 
     } 
    } 
    //information is now pulled, so allow interaction 
    UIApplication.sharedApplication().endIgnoringInteractionEvents() 

} 


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

    // THIS IS WHERE THE ERROR OCCURS 
    resultsArray[indexPath.row].imageFile.getDataInBackgroundWithBlock { (data, error) -> Void in 

     //set image within cell 
    } 
    return cell 
} 
+0

поместить код с вашей стороны –

+0

см код @Graham – rohaldb

+0

пожалуйста, поставить точку останова в 'cellForRowAtIndexPath' затем запустить и посмотреть, шаг за шагом, что происходит. то в то же время вы можете видеть, что ваш arry имеет значение null или нет. –

ответ

0

Я бы предположил, что вы загружаете свои данные из Parse во временный массив, а затем назначаете это в свой массив свойств непосредственно перед вызовом reloadData - это позволит избежать любых возможных условий гонки и устранить необходимость в removeAll, что потенциально большая часть вашей проблемы;

override func viewWillAppear(animated: Bool) { 

    //begin ignoring events until the information is finished being pulled 
    UIApplication.sharedApplication().beginIgnoringInteractionEvents() 



    //run query 
    let query = PFQuery(className: "Answers") 
    query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in 

     var localArray=[SomeType]() 

     if let objects = objects { 

        //append information to the localArray 
       } 
      } 
      self.resultsArray=localArray 
      self.tableView.reloadData() 
     } 
    } 
    //information is now pulled, so allow interaction 
    UIApplication.sharedApplication().endIgnoringInteractionEvents() 

} 
+0

Странно, что это устранило проблему. Интересно, почему это случилось ... Но спасибо вам! – rohaldb

+0

arrays не являются потокобезопасными, поэтому в любое время, когда вы обновляете один поток и читаете от другого, у вас могут быть проблемы – Paulw11

+0

@rohaldb, если вы посмотрите на мой ответ, вы найдете «что на самом деле произошло» (в дополнение к комментарию @ Paulw11). – OhadM

0

Похоже, в viewWillAppear у вас есть справочный блок findObjectsInBackgroundWithBlock, который имеет какую-то работу, чтобы сделать в другом потоке (AKA от основного потока), это означает, что viewWillAppear закончит, пока блок получит обратный вызов.

Это объясняет, почему cellForRowAtIndexPath вызывается после завершения viewWillAppear из-за блока обратного вызова.

Это означает, что все в порядке и viewWillAppear действительно закончить законный «запуск».

Вы можете на самом деле поставить точку прерывания внутри метода обратного вызова (в viewWillAppear) и точку прерывания внутри cellForRowAtIndexPath и посмотреть, когда происходит обратный вызов, когда вызывается cellForRowAtIndexPath.

Если вам нужен другой метод из Парса, возможно, вы должны посмотреть в их documentation.

0

Фактически, если ваш обратный вызов не имеет доступа к self.tableView, все будет продолжаться, как вы думаете, как обычно. Вы можете попробовать.

Это случилось со мной, когда я получил доступ к представлению на экране в методе viewDidLoad, вызванный до init.

В любом случае, вы должны знать этот факт. И вы получаете доступ к вашему tableView в обратном вызове (вызывается до завершения viewWillAppear), который нуждается в cellForRowAtIndexPath.

+0

Im не совсем уверен, что вы имеете в виду/как это исправить. Что означает «На самом деле, если ваш обратный вызов не имеет доступа к self.tableView» означает? – rohaldb

+0

вы можете комментировать 'self.tableView.reloadData()', а затем посмотреть, что произойдет. – SeanChense

+0

, но тогда информация не будет отображаться в таблице? – rohaldb

Смежные вопросы