【问题标题】:swift3 uitableView reload makes screen blinkswift3 uitableView重新加载使屏幕闪烁
【发布时间】:2017-05-08 08:45:20
【问题描述】:

我正在使用 UITableview,它看起来与 Instagram 的提要相似。我遇到的问题

  1. 我在每个tableviewCell 中都有一个like 函数
  2. 点赞按钮时,需要更新屏幕,屏幕闪烁
  3. 在 tableview cellForRowAt 函数中,我有一个网络调用来检查 like 及其编号。

如果有办法避免这种闪烁,请告诉我。我应该在这个函数中避免网络调用还是有其他方法?

你可以在下面看到我的部分代码:

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! StoryReviewTableViewCell

    let review = ReviewArray[indexPath.row]

    // 프로필 이미지랑 닉네임 설정
    if let user = review.creator {
        let nickname = user.getProperty("nickname") as! String
        cell.profileName.text = nickname

        if let profileURL = user.getProperty("profileURL") {
            if profileURL is NSNull {
                cell.profileImage.image = #imageLiteral(resourceName: "user_profile")
            } else {
                let url = URL(string: profileURL as! String)
                DispatchQueue.main.async {
                    cell.profileImage.kf.setImage(with: url, placeholder: #imageLiteral(resourceName: "imageLoadingHolder"), options: [.transition(.fade(0.2))], progressBlock: nil, completionHandler: nil)
                }
            }
        }
    } else {
        //  삭제된 유저의 경우
        cell.profileName.text = "탈퇴 유저"
        cell.profileImage.image = #imageLiteral(resourceName: "user_profile")
    }

    // 장소 이름
    if let store = ReviewArray[indexPath.row].store {
        cell.storeName.text = "장소: \(String(describing: store.name!))"
    } else {
        cell.storeName.text = "가게 이름"
    }


    // 라이크버튼 설정 - 라이크 모양은 여기서 컨트롤, delegate에서 user 라이크 컨트롤
    DispatchQueue.global(qos: .userInteractive).async {

        let likeStore = Backendless.sharedInstance().data.of(ReviewLikes.ofClass())
        let dataQuery = BackendlessDataQuery()

        let objectID = review.objectId!
        let userID = UserManager.currentUser()!.objectId!
        // print("objectID & userID: \(objectID) & \(userID)")

        // 여기서 by가 현재 유저의 objectId이어야 하고, to는 이 리뷰의 objectId이어야 한다
        dataQuery.whereClause = "by = '\(userID)' AND to = '\(objectID)'"

        DispatchQueue.main.async {
            likeStore?.find(dataQuery, response: { (collection) in
                let likes = collection?.data as! [ReviewLikes]

                // 하트를 안 눌렀을 때
                if likes.count == 0 {
                    DispatchQueue.main.async {
                        cell.likeButton.setImage(#imageLiteral(resourceName: "like_bw"), for: .normal)
                    }
                } else {
                    DispatchQueue.main.async {
                        cell.likeButton.setImage(#imageLiteral(resourceName: "like_red"), for: .normal)
                    }
                }

            }, error: { (Fault) in
                print("라이크 불러오기에서 에러: \(String(describing: Fault?.description))")
            })

        }

        // 좋아요 개수 세기
        let countQuery = BackendlessDataQuery()
        // to가 story의 objectID와 일치하면 땡
        countQuery.whereClause = "to = '\(objectID)'"

        let queryOptions = QueryOptions()
        queryOptions.pageSize = 1
        countQuery.queryOptions = queryOptions

        DispatchQueue.global(qos: .userInteractive).async {
            let matchingLikes = likeStore?.find(countQuery)
            let likeNumbers = matchingLikes?.totalObjects

            DispatchQueue.main.async {
                if likeNumbers == 0 {
                    cell.likeLabel.text = "라이크 없음 ㅠ"
                } else {
                    cell.likeLabel.text = "\(String(describing: likeNumbers!))개의 좋아요"
                }
            }
        }
    }

    // 리뷰 평점 배당
    cell.ratingView.value = review.rating as! CGFloat

    // 리뷰 바디
    cell.reviewBody.text = review.text

    // 코멘트 개수 받아오기
    DispatchQueue.global(qos: .userInteractive).async {
        // 댓글수 찾기
        let tempStore = Backendless.sharedInstance().data.of(ReviewComment.ofClass())

        let reviewId = review.objectId!
        let dataQuery = BackendlessDataQuery()
        // 이 리뷰에 달린 댓글 모두 몇 개인지 찾기
        dataQuery.whereClause = "to = '\(reviewId)'"

        DispatchQueue.main.async {
            tempStore?.find(dataQuery, response: { (collection) in
                let comments = collection?.data as! [ReviewComment]

                cell.replyLabel.text = "댓글 \(comments.count)개"

            }, error: { (Fault) in
                print("서버에서 댓글 얻어오기 실패: \(String(describing: Fault?.description))")
            })
        }
    }

    cell.timeLabel.text = dateFormatter.string(from: review.created! as Date)

    return cell
}

你可以在这里看到按钮动作

    @IBAction func likeButtonClicked(_ sender: UIButton) {

    likeButton.isUserInteractionEnabled = false

    // delegate action
    delegate?.actionTapped(tag: likeButton.tag)

    // image change
    if sender.image(for: .normal) == #imageLiteral(resourceName: "like_bw") {
        UIView.transition(with: sender, duration: 0.2, options: .transitionCrossDissolve, animations: {
            sender.setImage(#imageLiteral(resourceName: "like_red"), for: .normal)
        }, completion: nil)
        self.likeButton.isUserInteractionEnabled = true
    } else {
        UIView.transition(with: sender, duration: 0.2, options: .transitionCrossDissolve, animations: {
            sender.setImage(#imageLiteral(resourceName: "like_bw"), for: .normal)
        }, completion: nil)
        self.likeButton.isUserInteractionEnabled = true
    }
}

这是我的委托函数的一部分,它只为行重新加载

    func changeLike(_ row: Int, _ alreadyLike: Bool, completionHandler: @escaping (_ success:Bool) -> Void) {

    let selectedReview = ReviewArray[row]
    let reviewId = selectedReview.objectId

    // 그냥 유저 객체로 비교는 안되고 objectId로 체크를 해야 함
    let objectID = Backendless.sharedInstance().userService.currentUser.objectId

    let dataStore = Backendless.sharedInstance().data.of(ReviewLikes.ofClass())

    // 좋아요 - alreadyLike가 true이면
    if !alreadyLike {
        // 객체 생성

        let like = ReviewLikes()
        like.by = objectID! as String
        like.to = reviewId

        dataStore?.save(like, response: { (response) in

            DispatchQueue.main.async {

                let indexPath = IndexPath(row: row, section: 0)
                self.tableView.reloadRows(at: [indexPath], with: .none)

            }
    }

【问题讨论】:

  • 分享代码按钮操作。
  • @KKRocks 你可以看到按钮动作 - 但我认为与屏幕闪烁没有太大关系。请检查!
  • 您是否在 likeButtonClicked 时重新加载了 tableview?
  • 只需获取 tablewview 的单元格,并仅更新该单元格的类似状态。避免重新加载tableview,它会闪烁tableview。
  • @KKRocks 哦,我在 viewcontroller 和 tableviewcell 之间的委托调用期间重新加载了表格。

标签: ios swift uitableview


【解决方案1】:
let cell = self.tblView.cellForRow(at: IndexPath(row: index, section: 0)) as! UITableViewCell
cell.btnLike.setImage(UIImage(named: (isReviewed! ? IMG_LIKE : IMG_UNLIKE)), for: .normal)

只需更新单元格,而不是在 tableview 中重新加载整个数据。

【讨论】:

    【解决方案2】:

    尝试在单击按钮时调用数据而不是 cellForRowAtIndexpath,并使用单击的按钮而不是重新加载数据

    @IBAction func likeButtonClicked(_ sender: UIButton) {
       let buttonPosition:CGPoint = sender.convert(CGPointZero, to:self.tableView)
    
       let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
       let cell = tableView.cellForRow(at: indexPath)   as! StoryReviewTableViewCell
    
                DispatchQueue.main.async {
                            likeStore?.find(dataQuery, response: { (collection) in
                                let likes = collection?.data as! [ReviewLikes]
    
                                // 하트를 안 눌렀을 때
                                if likes.count == 0 {
                                    DispatchQueue.main.async {
                                        cell.likeButton.setImage(#imageLiteral(resourceName: "like_bw"), for: .normal)
                                    }
                                } else {
                                    DispatchQueue.main.async {
                                        cell.likeButton.setImage(#imageLiteral(resourceName: "like_red"), for: .normal)
                                    }
                                }
    
                            }, error: { (Fault) in
                                print("라이크 불러오기에서 에러: \(String(describing: Fault?.description))")
                            })
    
    
    
                }
    

    【讨论】:

    • 好的,我会尝试您的解决方案并回复您!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-18
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    • 2011-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多