进行第二次 Json 调用 Swift 3 后如何在 UITableview 中重新加载数据

Posted

技术标签:

【中文标题】进行第二次 Json 调用 Swift 3 后如何在 UITableview 中重新加载数据【英文标题】:How to reload data in UITableview after making second Json call Swift 3 【发布时间】:2017-05-31 05:08:15 【问题描述】:

我正在发出 JSON 请求,如果它已完成,那么我将带有 JSON 数据的页面导航到我的表格视图控制器,一切正常,但是当我第二次调用加载更多单元格时,我无法重新加载数据,这里是我正在第二次调用我的表视图控制器的代码。

    var listData:[String] = []
    var videoIDData:[String] = []
    var valueKeyData:[String] = []
    var nextPageToken:String?
    var titleNamee:[String] = []
    var videoIDD :[String] = []
    var valueKeyy :[String] = []
    var PrevPageToken:String?



    @IBOutlet weak var tableView: UITableView!


    override func viewDidLoad() 
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self
    

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

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
               return listData.count
    


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
      let cell = tableView.dequeueReusableCell(withIdentifier: "VideoCell", for: indexPath) as! VideoTableViewCell
        cell.videoTitle.text = listData[indexPath.row]
        let url = NSURL(string: valueKeyData[indexPath.row])
        let dataaa = NSData(contentsOf: url! as URL)
        let image = UIImage(data: dataaa! as Data)
        cell.videoThumnailImageView.image = image


        if (indexPath.row == listData.count - 1)
        
            makeGetCall()

        




     return cell
     

    func makeGetCall() 
        // Set up the URL request
        var pageToken:String = (pageToken)
        let todoEndpoint: String = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50\(pageToken)&playlistId=\(id)_ItOZ8WBF5_SI_SrSN3_F&\(key)"

        guard let url = URL(string: todoEndpoint) else 
            print("Error: cannot create URL")
            return
        
        let urlRequest = URLRequest(url: url)

        // set up the session
        let config = URLSessionConfiguration.default
        let session = URLSession(configuration: config)

        // make the request
        let task = session.dataTask(with: urlRequest) 
            (data, response, error) in
            // check for any errors
            guard error == nil else 
                print("error calling GET on /todos/1")
                print(error)
                return
            

            guard let responseData = data else 
                print("Error: did not receive data")
                return
            
            // parse the result as JSON, since that's what the API provides
            do 
                guard let jsonObject = try JSONSerialization.jsonObject(with: responseData, options: []) as? [String : AnyObject]  else 
                    print("error trying to convert data to JSON")

                    return
                
                self.PrevPageToken = jsonObject["prevPageToken"] as? String
                self.nextPageToken = jsonObject["nextPageToken"] as? String
                    if let itemsArray = jsonObject["items"] as? [[String:AnyObject]]
                        for snippetArray in itemsArray
                            if var snippet = snippetArray["snippet"] as? [String : AnyObject]
                                if let titleItems = snippet["title"] as? String
                                    self.titleNamee += [titleItems]
                                
                                if let thumbnail = snippet["thumbnails"] as? [String : AnyObject]
                                    if let highValue = thumbnail["high"] as? [String : AnyObject]
                                        if let urlValueKey = highValue ["url"] as? String
                                            self.valueKeyy += [urlValueKey]
                                        
                                    
                                
                                if let resource = snippet["resourceId"] as? [String : AnyObject]
                                    if let videoId = resource["videoId"] as? String
                                        // self.videoIDD.append(videoId)
                                        self.videoIDD += [videoId]
                                    
                                
                            
                        
                

             catch  
                print("error trying to convert data to JSON")
                return
            
        

        task.resume()

        DispatchQueue.main.async
            self.tableView.reloadData()
        

    

 

【问题讨论】:

您必须尝试使用​​Model Class 代替Multiple Array 所有要在表格视图中传递的内容,在获得second JSON 之后,您必须调用表格重新加载代码在main dispatch 内,因为该块是异步的,这就是为什么无法执行Table reload 我已经创建了 NSObject 自定义类,但我不知道如何在这个方法中使用这个类..任何帮助请...??? 【参考方案1】:

您在错误的位置重新加载tableView,您需要在for loop 之后的完成块内重新加载它,因为完成块将调用异步,因此请删除您当前的tableView 重新加载代码并将其放在for 循环之后。

for snippetArray in itemsArray
    if var snippet = snippetArray["snippet"] as? [String : AnyObject]
        if let titleItems = snippet["title"] as? String
            self.titleNamee += [titleItems]
        
        if let thumbnail = snippet["thumbnails"] as? [String : AnyObject]
            if let highValue = thumbnail["high"] as? [String : AnyObject]
                if let urlValueKey = highValue ["url"] as? String
                    self.valueKeyy += [urlValueKey]
                
            
        
        if let resource = snippet["resourceId"] as? [String : AnyObject]
            if let videoId = resource["videoId"] as? String
                // self.videoIDD.append(videoId)
                self.videoIDD += [videoId]
            
        
    

//Reload your table here
DispatchQueue.main.async
    self.tableView.reloadData()

注意:您需要做的是创建一个具有所有这些属性的自定义类或结构,并创建该自定义类或结构对象的数组,而不是创建当前正在执行的多个数组。

编辑:我没有看到你在cellForRowAt 中调用这个方法,不要这样做,因为单元格将被重用,这就是你 UI 卡住的原因,所以删除从cellForRowAt 调用代码,如果你想做类似分页的东西,你可以像这样使用scrollViewDelegate 方法。

func scrollViewDidScroll(_ scrollView: UIScrollView) 
    if((scrollView.contentOffset.y + scrollView.frame.size.height) == scrollView.contentSize.height)
    
        self.makeGetCall()
    

另外,在发出 API 请求时显示一些进程指示器会更好。

【讨论】:

感谢您的回复...我尝试过这种方式,但仍然没有重新加载数据..它总是卡在最后一个单元格上....但是当我打印每个数组时显示数据... @User786 卡住是什么意思,是应用程序崩溃了吗?如果它在cellForRowAt 崩溃,其中一个用于您使用 indexPath.row 为数组下标的行,那么您的所有数组都没有相等的对象 不,它没有崩溃......当我向上滚动时它卡住了,它的调用函数 makeGetCall() 再次 n ......当我调试函数在所有数组中平均解析数据时。 .. 但不重新加载单元格。 是的...感谢您的帮助n回复...它正在工作n在表格视图上重新加载数据但唯一的问题是卡住n然后重新加载数据...但至少它的工作... @User786 欢迎朋友 :)

以上是关于进行第二次 Json 调用 Swift 3 后如何在 UITableview 中重新加载数据的主要内容,如果未能解决你的问题,请参考以下文章

Swift UIViewController tableView.reloadData nil 在第二次调用时包装

Swift 5 - 用户第二次单击标签栏按钮后,需要帮助在视图控制器 1 上重新加载 Web 视图

Swift - 第二次加载后 Tableview 无法正确重新加载

Swift 2:电子邮件取消按钮在第二次尝试表视图后停止工作

第二次冲刺

Swift JSON 无法获取第二个变量