2015-08-02 2 views
1

Существует UITableView, его ячейки будут заполнены данными, полученными с запросом HTTP-сообщения. Но функции UITableView выполняются до ввода данных. Когда приложение запускается, выполняются все три метода tableView, а затем приложение выдает ошибку времени выполнения. Я думаю, это потому, что в cellForRowAtIndexPathmessageList по-прежнему пуст.Блок dispatch_async() не завершился до того, как методы UITableViewDataSource

Вот код:

class messageViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{ 

    var authData : NSDictionary = [:] 
    var funcLib = functionLibrary() 
    var messagesList : NSArray = [] 
    var messageCount: Int = 0 

    @IBOutlet weak var messageTableView: UITableView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // Do any additional setup after loading the view. 

     var authCode = self.authData["auth"] as! String 
     var userID = self.authData["user_id"] as! String 
     var messageRequsetBodyData: AnyObject = ["op":"users","op2":"getThisWeekMessages","id":"\(userID)","id2":"","id3":"","authCode":"\(authCode)"] as AnyObject 

     funcLib.HTTPPostRequest("http://asdasd.asdasdasd.com/services/index.php", bodyData: messageRequsetBodyData){data in 

      dispatch_async(dispatch_get_main_queue()){ 

       if let data = data{ 

        var messaggesListDic = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSDictionary 
        println("------MESSAGGES---------") 

        self.messageCount = messaggesListDic["count"] as! Int 
        //self.messages = messaggesListDic["messages"] as! NSDictionary 
        self.messagesList = messaggesListDic["messages"] as! NSArray 
        println("\(self.messagesList)") 
        self.messageTableView.reloadData() 
       } 

      } 

     } 

     self.messageTableView.delegate = self 
     self.messageTableView.dataSource = self 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    @IBAction func dismissMessageVC(sender: AnyObject) { 

     self.dismissViewControllerAnimated(true, completion: nil) 
    } 


    func numberOfSectionsInTableView(tableView: UITableView) -> Int { 

     println("asdasd") 
     return 1 
    } 

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

     println("asdasd") 
     println("\(self.messageCount)") 
     return 1 
    } 

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

     println("bdbsdbsdb") 
     var cell = self.messageTableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as? UITableViewCell 
     let row = indexPath.row 
     cell!.textLabel!.text = self.messagesList[0]["content"] as? String 
     return cell! 
    } 

Продолжительность Описание ошибки:

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 0 beyond bounds for empty array' 

Я попытался присвоить метку клеток с помощью cell.textLabel?.text = "asdasd" команды, и она работает. Поэтому я думаю, что нет проблем с выходами или методами.

Как назначить данные messageList до cellForRowAtIndexPath, выполненных с использованием другого способа?

+0

Вы можете сделать, если пусть строка из массива, и если она существует, тогда назначьте ей метку. –

+0

Но это вообще не будет. – Faruk

+0

Это будет, когда вы перезагрузите данные таблицы из закрытия –

ответ

1

Вы возвращаете постоянное значение для количества строк, даже если ваше количество сообщений равно нулю. Лучше вернуть количество сообщений.

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    println("asdasd") 
    println("\(self.messageCount)") 
    return self.messageCount; 
} 
+0

Он работал с 'return self.messageList.count. Но есть отставание. Это из-за 'dispacth_async'? Наконец, ячейки сначала пустые, затем они заполняются данными. Можете ли вы предложить какой-то способ исправить это? – Faruk

+0

Сотовые ячейки сначала пустые, потому что у вас нет данных. Что касается отставания, я не могу сказать вам, где проблема. Лучше использовать инструменты для анализа производительности. Возможно, ваш JSON слишком велик, и, поскольку вы делаете десериализацию в основной теме, у вас есть отставание, возможно, что-то еще. –

+0

Да, это должно быть отставание. данные невелики. но мое интернет-соединение слишком медленное прямо сейчас. Спасибо в любом случае :) – Faruk

0

Замените возвращаемое значение функции с помощью messagesList.count.

+0

Спасибо, это сработало, но есть некоторые проблемы. Пожалуйста, посмотрите комментарий первого ответа. – Faruk

3

Да, если у вас есть вид таблицы, которую необходимо сделать асинхронный вызов для извлечения данных, следует ожидать, что методы источника данных таблицы следует назвать, прежде чем асинхронный запрос делается. Но, когда асинхронный запрос выполняется, когда вы просто вызываете tableView.reloadData(), методы источников данных в виде таблицы будут вызываться во второй раз. Это очень распространенная картина.

Проблема здесь заключается в том, что этот код не грациозно обрабатывает ситуацию, когда нет данных для отображения при первом вызове методов источников данных табличного представления. Если numberOfRowsForSection вернул 0, пока данные не были восстановлены (как описано другими, в частности, возвращая messagesList.count(), как это было предложено Джоном и Йедидью, вместо того, чтобы возвращать фиксированное число), все было бы хорошо.

+0

спасибо за информацию, я сохраню это в своем уме. – Faruk

+1

О, ты поймал меня, когда я это делал :) – Faruk

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