使用 JSON 数据填充 UITableView

Posted

技术标签:

【中文标题】使用 JSON 数据填充 UITableView【英文标题】:Populate UITableView with JSON data 【发布时间】:2017-12-12 22:55:28 【问题描述】:

我正在为 iPhone 构建一个非常基本的 reddit 客户端,只是为了练习为 ios 开发。我已经得到它来解析我选择的 subreddit 的 JSON,但是我无法从解析的 JSON 中获取标题并将它们显示在我的 UITableView 中。我目前遇到的问题是,在加载 UITableView 之前,我无法让我的“postList”数组填充 JSON 数据。因此,当表格视图单元格被填充时,postList 数组的元素中没有任何内容可供填充。知道如何解决这个问题吗?

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate 

@IBOutlet weak var tableView: UITableView!

let URL = "https://www.reddit.com/r/swift/.json"

var postList : [PostList] = Array(repeating: PostList(), count: 26)
//var postList : [PostList] = []
override func viewDidLoad() 
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    tableView.dataSource = self
    tableView.delegate = self


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


//Setting up tableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return 5


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    var cell = tableView.dequeueReusableCell(withIdentifier: "aroundMeCell", for: indexPath)

    getPosts(url: URL, row: indexPath.row, cell: cell)
    let title = postList[indexPath.row].title
    cell.textLabel?.text = title
    return cell



//Receiving posts using Alamofire
func getPosts(url: String, row: Int, cell: UITableViewCell) 
    Alamofire.request(url, method: .get)
        .responseJSON  response in
            if response.result.isSuccess 
                let postJSON : JSON = JSON(response.result.value!)
                //print(postJSON)
                self.createPostListArray(json: postJSON, row: row, cell: cell)

             else 
                print("Error: \(String(describing: response.result.error)) aaaaaa")
            
    


func createPostListArray(json: JSON, row: Int, cell: UITableViewCell) 

    let titlePath : [JSONSubscriptType] = ["data", "children", row, "data", "title"]
    let postPath : [JSONSubscriptType] = ["data", "children", row, "data", "selftext"]

    //Making sure I can unwrap both
    if(json[titlePath].string != nil && json[postPath].string != nil)
        let inTitle = json[titlePath].string!
        let inPost = json[postPath].string!
        postList[row].title = inTitle
        postList[row].post = inPost
    
    else
        print("error")
    

【问题讨论】:

我看到很多问题,从 cellForRowAt 你调用 Alamofire.request,通过调用链传递单元格,然后单元格(可以出队,等等......)到达它的“createPostListArray”中的终端位置并且未被使用。对我来说,这段代码闻起来很糟糕。 可能与问题无关,但从不使用 Array(repeating:count: 语法创建数组。将数组声明为空 var postList = [PostList]() 并附加或插入项目。并且不要在cellForRowAt 中填充数据源数组,在viewDidLoad 中填充。 您是否尝试过在 *** 浏览其他问题?搜索您的问题标题returns a lot of questions 看似相似的问题:o) 这是代码还是坏菜。真的很难闻。您正在 cellforrowatindexpath 中执行 almofire 请求。 【参考方案1】:

您的代码存在多个问题。

1-var postList : [PostList] = Array(repeating: PostList(), count: 26)。您可以创建空数组var postList = [PostList]() 并在响应中追加删除元素。

2- 在cellForRowAt 上调用 api 根本不是一个好主意。 原因:每当调用此方法时,您都会调用 api。考虑一个场景,您正在为每个调用此 api 的 dequeue 滚动 tableview。

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate 

@IBOutlet weak var tableView: UITableView!

let URL = "https://www.reddit.com/r/swift/.json"

var postList = [PostList]()
override func viewDidLoad() 
    super.viewDidLoad()
    getPosts(url: URL)
    tableView.dataSource = self
    tableView.delegate = self


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


//Setting up tableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return postList.count


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    var cell = tableView.dequeueReusableCell(withIdentifier: "aroundMeCell", for: indexPath)
    let title = postList[indexPath.row].title
    cell.textLabel?.text = title
    return cell



//Receiving posts using Alamofire
func getPosts(url: String) 
    Alamofire.request(url, method: .get)
    .responseJSON  [weak self] response in
        if response.result.isSuccess 
                    let postJSON : JSON = JSON(response.result.value!)
                //print(postJSON)
                self?.createPostListArray(json: postJSON)
                self?.tableView.reloadData()

             else 
                print("Error: \(String(describing: response.result.error)) aaaaaa")
            
    


func createPostListArray(json: JSON) 
     //parse your json here, or read about objectMapper a pod. This will help you in parsing and if you are using swift 4, read encode json.

【讨论】:

【参考方案2】:

首先在 viewDidLoad() 中调用 api。将数组声明为

      var postList = [PostList]

api调用成功阻塞后执行self.tableview.reloadData()。

【讨论】:

以上是关于使用 JSON 数据填充 UITableView的主要内容,如果未能解决你的问题,请参考以下文章

使用 JSON 数据填充 INPUT 和 SELECT

使用 JSON 数据填充表

通过名称和值使用 json 数据填充表单

无法使用 json 数据填充 UITableview

使用 json 填充 switch case 数据

需要帮助使用 SwiftyJSON 使用 JSON 数据填充数组