ios - 如何知道 HTTPRequest 之后所有任务何时完成(Swift)

标签 ios swift uitableview asynchronous httprequest

我目前面临一个困扰我好几天的问题。我尝试了几种解决方案,但似乎无法解决问题。让我来说明发生了什么。

我在 UITableView 中有一个包含帖子的提要。一旦用户选择其中一个单元格,就会在新的 UIViewController 中向他显示​​这篇文章的详细 View 。在那里,我设置了所有 View 并在 viewDidLoad() 方法中调用函数 loadPostDetails()。 View 一出现,就会显示一个自定义加载指示器,该指示器设置为在加载详细信息时消失(隐藏),然后是此 UIViewControllerUITableView(让我们调用它 PostController) 显示。

在我的 loadPostDetails() 函数中,我创建了一个 HTTPRequest 来获取我需要的 JSON 数据。这将返回三种信息:帖子详细信息本身、点赞和评论。在重新加载 UITableView 并显示它之前,我需要处理这三个元素中的每一个。目前,我是这样做的:

HTTP.retrievePostDetails(postID: postID, authRequired: true) { (error, postDetails) in

    if(error != nil) {

        self.navigationController?.popViewController(animated: true)

    } else {

        if let postDetails = postDetails, let postInfo = postDetails["postInfoRows"] as? [[String: Any]], let postLikesCount = postDetails["postLikesCount"] as? Int, let postLikesRows = postDetails["postLikesRows"] as? [[String: Any]], let postCommentsRows = postDetails["postCommentsRows"] as? [[String: Any]] {

            DispatchQueue.main.async {

                let tableFooterView = self.postTableView.tableFooterView as! tableFooterView

                if let postTitle = postInfo[0]["postTitle"] as? String, let postText = postInfo[0]["postText"] as? String {

                    self.postTitleLabel.text = postTitle
                    self.postTextLabel.text = postText

                }

                for (index, postCommentRow) in postCommentsRows.enumerated() {

                    tableFooterView.postComments.append(Comment(userID: postCommentRow["userID"] as! Int, userProfilePicURL: postCommentRow["userProfilePicURL"] as! String, userDisplayName: postCommentRow["userDisplayName"] as! String, commentTimeStamp: postCommentRow["commentTimeStamp"] as! TimeInterval, commentText: postCommentRow["commentText"] as! String))

                }

                var likeDisplayNames = [String]()

                for postLikeRow in postLikesRows {

                    likeDisplayNames.insert(postLikeRow["userDisplayName"] as! String, at: 0)

                }

                if(postLikesCount > 2) {

                    tableFooterView.likesLabel.text = "\(likeDisplayNames[0]), \(likeDisplayNames[1]) and \(postLikesCount - 2) others"

                } else {

                    tableFooterView.likesLabel.text = "\(postLikesCount) likes"

                }

            }

            DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {

                self.screenDotsLoader.isHidden = true
                self.screenDotsLoader.stopAnimating()
                self.postTableView.isHidden = false
                self.postTableView.reloadData()

            })

        }

    }

 }

注意:我向 UILabels 添加了更多文本,例如用户的日期和个人资料图片,但我删除了几行以使其更易读,因为额外的代码与此问题无关。

现在,正如您可能已经看到的那样,我在 1 秒后调用重新加载,因此在 95% 的情况下它工作得很好(但仍然不完美,因为它是一个“hack”)。在另外 5% 中,布局无法找出正确的约束,导致布局非常糟糕。

我最近几天尝试使用 DispatchGroups(),但我不知道该怎么做。事实上,我想知道所有任务何时执行,所以当所有 UILabels 已更新,所有 UIImageViews 已更新等。只有到那时,我想重新加载UITableView

我希望有人能给我指出正确的方向,这样我就可以进一步提升我的用户体验。谢谢!

最佳答案

DispatchGroups 当你一起做一堆异步任务时使用,并且需要在所有完成时得到通知,但目前你不这样做,因为当你收到响应时,所有都是在同步(串行)的主线程中,这意味着重新加载表之前的所有内容都将在重新加载之前发生,因此如果这对您的 UX 有意义,您可以自由使用 dispatch

关于ios - 如何知道 HTTPRequest 之后所有任务何时完成(Swift),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55329290/

相关文章:

objective-c - 如何从nsarray删除空格,方括号和“

ios - 滚动时图像无法正确显示 iOS Swift

swift - Swift 中的问题

arrays - 如何制作包含当前月份和接下来月份的数组。?

ios - 将 iOS 6 设备作为 BLE 外围设备运行

ios - NSZombie是否可能没有使用ARC指出EXC_BAD_ACCESS?

ios - 复制粘贴 NSAttributedString 到外部应用程序 iOS

ios - 从 CoreData 制作 TableView

ios - Swift 代码中的 SVPullToRefresh + SVInfiniteScrolling

ios - 使 TableView 根据 PickerView 中的当前选择显示值?