UITableView был обработан до того, как данные из API были возвращены с использованием SwiftyJSON и Alamofire.

когда я вызываю функцию callapi() в viewDidLoad(), println() в callapi печатает массив сообщений с объектами Post внутри него, однако println() внутри функции viewDidLoad() печатает пустой массив. Также, когда я создаю проект, я получаю эту ошибку «фатальная ошибка: индекс массива вне диапазона». оператор println() в функции tableView также печатает пустой массив. Кажется, таблица была обработана до того, как поступили данные из API, как я могу решить эту проблему?

var posts = [Post]()

override func viewDidLoad() {
    super.viewDidLoad()
    callapi()
    println(self.posts)
}

func callapi(){
    request(.GET, "url")
    .responseJSON { (request, response, data, error) in
        let json = JSON(data!)
        if let jsonArray = json.array {
            for post in jsonArray {
                var onepost = Post(id:post["id"].stringValue,                    

              title:post["title"].stringValue, 
              author:post["author"].stringValue, 
              post:post["post"].stringValue,   
              created_on:post["created_on"].stringValue, 
              updated_on:post["updated_on"].stringValue)
                self.posts.append(onepost)
                println(self.posts)
                self.tableView.reloadData()
            }
        }
    }
}

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

    println(self.posts)
    let post = self.posts[indexPath.row]
    // Configure the cell...
    cell.titleLabel!.text = self.posts[indexPath.row].title
    cell.postLabel.text = post.post
    println(self.posts)
    return cell
}

person Ahmed Onawale    schedule 19.04.2015    source источник
comment
Можете ли вы показать нам свой tableView:numberOfRowsInSection: метод?   -  person Rob    schedule 19.04.2015
comment
Тот факт, что posts пуст в viewDidLoad, имеет смысл (поскольку это заполняется асинхронно, т.е. позже). Что не совсем понятно, так это то, что cellForRowAtIndexPath не следует вызывать до тех пор, пока numberOfRowsInSection не сообщит, что есть несколько строк для отображения.   -  person Rob    schedule 19.04.2015
comment
Однако я бы переместил вызов reloadData за пределы цикла for. Я не думаю, что это ваша проблема, но это неэффективно.   -  person Rob    schedule 19.04.2015
comment
@Rob, спасибо за ваш ответ, внутри метода tableView:numberOfRowsInSection: я явно установил, что он возвращает 2, он должен был возвращать self.posts.count, почему? потому что я установил, что длина массива уже равна 2   -  person Ahmed Onawale    schedule 19.04.2015
comment
теперь я просто изменил его, чтобы он возвращал self.posts.count, и это сработало!   -  person Ahmed Onawale    schedule 19.04.2015
comment
чего я не понимаю, так это: self.posts.count = 2, что является длиной массива. почему это отличается от возврата 2?   -  person Ahmed Onawale    schedule 19.04.2015
comment
Это не работает, потому что JSON возвращает асинхронно (т.е. позже). Таким образом, когда вы загружаете представление, таблица загружается до того, как posts сможет вам что-то показать. Когда вызов JSON завершен, таблица перезагружается (поскольку вы вызвали reloadData).   -  person Rob    schedule 19.04.2015


Ответы (3)


Когда вызывается viewDidLoad, он запускает асинхронный callapi, но к моменту завершения viewDidLoad posts все еще пуст. Но табличное представление по-прежнему будет продолжать свой первоначальный процесс загрузки, даже если posts не было заполнено, поэтому вы должны убедиться, что tableView:numberOfRowsInSection: возвращает ноль на этом этапе.

Позже callapi завершает запрос Alamofire GET и вызывает reloadData. Только в этот момент tableView:numberOfRowsInSection: должно возвращать ненулевое значение.

В итоге убедитесь, что tableView:numberOfRowsInSection: возвращает фактическое количество записей в posts, и проблема должна быть решена.

person Rob    schedule 19.04.2015
comment
Спасибо за ответ, теперь я понимаю, как работает tableView:numberOfRowsInSection. - person Ahmed Onawale; 19.04.2015

Просто вставьте перезагрузку в viewDidAppear, и все готово:

override func viewDidAppear(animated: Bool) {
        self.tableView.reloadData()
    }
person Gabriel J. S. Oliveira    schedule 26.09.2016

убедитесь, что вы установили tableView:numberOfRowsInSection: для возврата self.posts.count

person Johnson    schedule 19.04.2015