Парсинг данных в tableview swift 3

Я пытаюсь проанализировать данные с веб-сайта и затем отобразить их в виде таблицы при нажатии кнопки. Я использую swift 3, Xcode 8.2 beta и не могу получить данные для хранения в массиве или отображения в tableView. Вот мой класс tableViewCell:

class TableViewCell: UITableViewCell {
@IBOutlet weak var userIdLabel: UILabel!
@IBOutlet weak var titleLabel: UILabel!
override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

Вот мой код viewController:

import UIKit
class SecondViewController: UIViewController, UITableViewDelegate,UITableViewDataSource {
let urlString = "https://jsonplaceholder.typicode.com/albums"
@IBOutlet weak var tableView: UITableView!
  var titleArray = [String]()
  var userIdArray = [String]()
@IBAction func getDataButton(_ sender: Any) {
    self.downloadJSONTask()
     self.tableView.reloadData()
}
override func viewDidLoad() {
    super.viewDidLoad()
     tableView.dataSource = self
     tableView.delegate = self
}
override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

func downloadJSONTask() {
    let url = NSURL(string: urlString)
    var downloadTask = URLRequest(url: (url as? URL)!, cachePolicy:  URLRequest.CachePolicy.reloadIgnoringCacheData, timeoutInterval: 20)
    downloadTask.httpMethod = "GET"


    URLSession.shared.dataTask(with: (url! as URL),  completionHandler: {(Data, URLResponse, Error) -> Void in
        let jsonData = try? JSONSerialization.jsonObject(with: Data!,  options: .allowFragments)
           print(jsonData as Any)
        if let albumArray = (jsonData! as AnyObject).value(forKey: "") as? NSArray {
            for title in albumArray{
                if let titleDict = title as? NSDictionary {
                    if let title = titleDict.value(forKey: "title") {
                        self.titleArray.append(title as! String)
                        print("title")
                        print(title)
                    }
                    if let title = titleDict.value(forKey: "userId")    {
                        self.userIdArray.append(title as! String)
                    }
                    OperationQueue.main.addOperation ({
                        self.tableView.reloadData()
                    })
                }
            }                
        }        
    }).resume()       
    }
 func tableView(_ tableView: UITableView, numberOfRowsInSection  section: Int) -> Int{
    return titleArray.count
  }
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell
    cell.titleLabel.text = titleArray[indexPath.row]
    cell.userIdLabel.text = userIdArray[indexPath.row]
    return cell
    }
    }

1 ответ

Решение

Есть много проблем в вашем коде, худшее - это использовать NSArray/NSDictionary в Свифте.

JSON - это массив словарей, значение для ключа title является String значение для userID является Intтак что вы должны объявить свои массивы

var titleArray = [String]()
var userIdArray = [Int]()

Никогда не приводите данные JSON к большинству неуказанных Any это еще один запрет. Приведите это всегда к фактическому типу. Еще одна большая проблема заключается в Data параметр в замыкании, который конфликтует с нативной структурой в Swift3, Используйте всегда строчные метки параметров. Запрос вообще не используется в вашем коде. А в Swift 3 всегда используются родные структуры URL, Data, URLRequest и т. д. Наконец .allowFragments это нонсенс, поскольку JSON четко начинается с типа коллекции.

let url = URL(string: urlString)!
let request = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 20)
URLSession.shared.dataTask(with: request) { (data, response, error) in
    if error != nil {
        print(error!)
        return
    }

    do {
        if let jsonData = try JSONSerialization.jsonObject(with:data!, options: []) as? [[String:Any]] {
            print(jsonData)
            for item in jsonData {

                if let title = item["title"] as? String {
                    titleArray.append(title)
                }
                if let userID = item["userId"] as? Int {
                    userIdArray.append(userID)
                }
                DispatchQueue.main.async {
                    self.tableView.reloadData()
                }
            }
        }
    } catch let error as NSError {
        print(error)
    }
}.resume()

PS: использование двух отдельных массивов в качестве источника данных тоже ужасно. Представьте, что одна из необязательных привязок может потерпеть неудачу, и количество элементов в массивах будет другим. Это красивое приглашение для крушения во время выполнения.

Другие вопросы по тегам