首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Swift 3-从主线程更新UI

Swift 3-从主线程更新UI
EN

Stack Overflow用户
提问于 2017-01-09 05:43:57
回答 1查看 3.4K关注 0票数 3

我想在后台线程中加载数据,并在主线程上更新tableview/UI。根据前面提到的关于线程的here,我想知道下面的代码是不是可以解决这个问题。我正在尝试加载更多的数据,因为用户滚动到特定的索引,并希望确保UI不会因为线程而冻结。谢谢!

代码语言:javascript
复制
 func loadMore () {
    guard !self.reachedEndOfItems else {
        return
    }

    self.offset = self.offset! + 10
    print("load more offset: \(self.offset)")

    var start = 0
    var end = 0


    isPullToRefresh = false

    let userCreds = UserDefaults.standard

    var getReqString = ""


    if userCreds.bool(forKey: "client_journal") == true || userCreds.bool(forKey: "user_journal") == true {

        var pageNum = ""
        if let pgNum = currentPgNum {
            print(pgNum)
            pageNum = String(pgNum)
        }
        var filterEntryType = ""
        if let entryTypeStr = filtEntryType {
            filterEntryType = entryTypeStr
        }

        var filterUserId = ""
        if let userId = filtUserId {
            filterUserId = userId

        }

        getReqString = "https://gethealthie.com/selected_entries.json?page=\(pageNum)&user_id=\(filterUserId)&entry_type=\(filterEntryType)&entry_filter="


    } else {

        if let pgNum = currentPgNum {
            print(pgNum)

            getReqString = "https://gethealthie.com/entries.json?page=\(pgNum)"
        }

    }


        BXProgressHUD.showHUDAddedTo(self.view)
        let request = Alamofire.request(getReqString, method: .get, headers: [
            "access-token": userCreds.object(forKey: "access-token")! as! String,
            "client": userCreds.object(forKey: "client")! as! String,
            "token-type": userCreds.object(forKey: "token-type")! as! String,
            "uid": userCreds.object(forKey: "uid")! as! String,
            "expiry": userCreds.object(forKey: "expiry")! as! String
            ]).responseJSON { (response:DataResponse<Any>) in
                print(response.response)

                let json = JSON(data: response.data!)
                print(json)

                print("yes")
                print(json.count)


                if userCreds.bool(forKey: "client_journal") == true || userCreds.bool(forKey: "user_journal") == true {
                    self.totalEntries = json["entries"].count

                    let totalEntryCount = json["entries"].count
                    start = 0
                    end = totalEntryCount
                } else {
                    self.totalEntries = json["entries"].count

                    let totalEntryCount = json["entries"].count
                    start = 0
                    end = totalEntryCount
                }

                if  self.totalEntries == 0 {
                    BXProgressHUD.hideHUDForView(self.view);

                } else if end <= self.totalEntries {
                    var jourIdx = 0

                    let newPatient = Patient()
                    let newDietitian = Dietitian()


                    for i in start ..< end {


                        let allEntries = json["entries"]
                        print(allEntries)
                        print("Entry count in loadMore is \(allEntries.count)")

                        let entry = allEntries[i]
                        print(entry)

                        let category = entry["category"]
                        print(category)


                        let name = entry["entry_comments"]
                        let k = name["id"]


                        var indexStr = String(i)

                        //entry attributes
                        self.jsonIdx.add(indexStr)

                        self.type.add(entry["type"].stringValue)
                        self.desc.add(entry["description"].stringValue)
                        self.category.add(entry["category"].stringValue)
                        //food cell- metric stat == healthy int
                        self.metric_stat.add(entry["metric_stat"].stringValue)
                        self.dateCreate.add(entry["created_at"].stringValue)
                        self.viewed.add(entry["viewed"].stringValue)
                        self.seenStatusArr.add(entry["viewed"].stringValue)
                        self.comments.add(entry["entry_comments"].rawValue)
                        self.entryType.add(entry["category"].stringValue)
                        //   "category" : entryType as AnyObject]

                        let posterInfo = entry["poster"]
                        let first = posterInfo["first_name"].stringValue
                        let last = posterInfo["last_name"].stringValue
                        let full = first + " " + last
                        self.captionName.add(full)


                        //food cell subcat
                        self.hungerInt.add(entry["percieved_hungriness"].stringValue)
                        self.prehunger.add(entry["ed_prehunger_string"].stringValue)
                        self.posthunger.add(entry["ed_posthunger_string"].stringValue)
                        self.emotions.add(entry["emotions_string"].stringValue)
                        self.reflection.add(entry["reflection"].stringValue)


                        print(self.comments)
                        self.id.add(entry["id"].stringValue)
                        self.entryImages.add(entry["image_url"].stringValue)


                        if i == end - 1 {
                            userCreds.set(json.count, forKey: "oldJsonCount")

                               BXProgressHUD.hideHUDForView(self.view)

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

                            }
                    }


                } else {
                    var reachedEndOfItems = true
                    BXProgressHUD.hideHUDForView(self.view);
                    print("reached the end")
                }

    }
EN

回答 1

Stack Overflow用户

发布于 2017-01-09 08:48:45

在这里的代码示例中,您将reloadData分派到主队列。但这是不必要的,因为responseJSON的闭包已经在主队列上运行,所以不需要调度任何东西。因此,您应该删除将reloadData分派到主队列。

现在,如果您正在使用URLSession,它默认在后台队列上运行闭包,或者如果您显式地提供了一个后台队列作为responseJSONqueue参数,那么,是的,您将把reloadData分派给主队列。但这并不是您需要确保分派到主队列的唯一事情,因为您的模型更新和HUD更新也应该在主队列上运行。但这是没有意义的,因为这个responseJSON已经在主队列上运行它的完成处理程序了。

然后,在评论中,您稍后会问是否所有这些都在主队列上运行,是否应该像在a previous question中那样将所有这些都分派到后台队列(大概是为了避免阻塞主队列)。

事实证明,这不是必需的(也不是理想的),因为当responseJSON完成处理程序中的响应在主队列上运行时,网络请求本身是异步执行的。如果在闭包中执行计算密集型操作,则只需将完成处理程序代码分派到后台队列(或将后台队列指定为responseJSON的参数)。但您不必担心网络请求会阻塞主队列。

总之,Alamofire让这一切变得简单,它异步运行请求,但在主队列上运行它的完成处理程序。它消除了很多手动GCD代码,这些代码是在使用URLSession时胡乱编写的。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41538232

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档