ios - UICollectionView 延迟/掉帧

标签 ios swift xcode

下午好,我的所有应用程序目前都在丢帧,我不知道如何修复它......我有点迷失。

希望你们能为我指明正确的方向。

我目前正在使用 Kingfisher 从后端下载图像,一切正常,除了滚动时,向下滚动时有点不稳定。

Controller 代码如下,可能有问题。

我正在使用 Storyboard ,并删除并添加了约束...但我没有运气。


import UIKit
import Kingfisher

class WallpaperCVC: UICollectionViewController , UIViewControllerTransitioningDelegate {

    var categoryId: String!
    var categoryName: String!
    var wallpaperBackend: Backend!
    var result:CGSize!
    // Header peralax
    fileprivate let headerId = "headerId"
    fileprivate let padding: CGFloat = 16



    @IBOutlet var wpMain: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = self.categoryName // Name to the controller or section selected
        // go go gadget data...
        getData()
        buttonGray()
        setupCollectionViewLayout()
        setupCollectionView()
    }

    func getData(){
        GLOBAL_BACKEND_DATA.removeAll()
        self.wallpaperBackend = Backend()
        self.wallpaperBackend.getWallByIdData(id: self.categoryId) { (god) in
            for post in god {
                let postData = post as! NSDictionary
                let wallpaperCVCId = postData.value(forKey: "id") as! String
                let wallpaperCVCFile = postData.value(forKey: "file") as! String
                let wallpaperCVCCategory = postData.value(forKey: "category") as! String
                let wallpaperCVCDownload = Int(postData.value(forKey: "download") as! String)

                GLOBAL_BACKEND_DATA.append(WallpaperModel(wallpaperModelId: wallpaperCVCId, wallpaperModelFile: wallpaperCVCFile, wallpaperModelCategoryId: wallpaperCVCCategory, wallpaperModelDownload: wallpaperCVCDownload!))
            }
         self.collectionView?.reloadData()
        }
    }

    @IBAction func pressedAction(_ sender: UIButton) {
        // do your stuff here
        self.dismiss(animated: true, completion: nil)
        print("you clicked on button \(sender.tag)")
    }
    func buttonGray(){
        let myButton = UIButton() // if you want to set the type use like UIButton(type: .RoundedRect) or UIButton(type: .Custom)
        let img = UIImage(named: "buttonA")
        myButton.setImage(img, for: .normal)
       // myButton.setTitleColor(UIColor.blue, for: .normal)
        myButton.frame = CGRect(x: 15, y: 50, width: 100, height: 100)
        // shadow
        myButton.layer.shadowOpacity = 0.5
        myButton.layer.shadowRadius = 4
        myButton.layer.shadowOffset = CGSize(width: 0, height: 5)
        myButton.addTarget(self, action: #selector(pressedAction(_:)), for: .touchUpInside)
        // haptic feedback
        myButton.isHaptic = true
        myButton.hapticType = .impact(.medium)
        //floatbutton like this
        view.addSubview(myButton)
        myButton.translatesAutoresizingMaskIntoConstraints = false
        myButton.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 10).isActive = true
        myButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
    }
    // MARK: UICollectionViewDataSource

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        // You only need one section for now
        return 1
    }
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // Here call the wallpapers
        return GLOBAL_BACKEND_DATA.count
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        // pulling & going to the controller
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "wallpapers", for: indexPath) as! WallpaperCVCell
        let godData = GLOBAL_BACKEND_DATA[indexPath.row]
        let imageURL = String(format:"%@uploads/image/%@", BASE_BACKEND_URL,godData.wallpaperModelFile) // calling wallpaperModel controller
        let escapedURL = imageURL.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
        let urls = URL(string:escapedURL!)
        // if nothing load this...
        let loadImage = UIImage(named: "skullLoading")
        cell.collWallpaperImage.kf.setImage(with: urls, placeholder: loadImage)
        cell.collWallpaperImage.kf.indicatorType = .activity  // Showing a loading indicator while downloading
        // lets count the downloads
        let count = godData.wallpaperModelDownload as Int // calling wallpaperModel controller
        cell.collectionCount.text = String(count) //collection view cell count label
        cell.configure() // calling a function from the cell

        return cell
    }

    // Lets move over to the next controller
    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("Tapped....Tapped go to the next controller..")
        collectionView.deselectItem(at: indexPath, animated: true)

        let vc = self.storyboard!.instantiateViewController(withIdentifier: "page") as! PageViewController
        vc.position = indexPath.row
        vc.categoryName = self.categoryName
        vc.transitioningDelegate = self
        vc.modalPresentationStyle = .custom
        self.present(vc, animated: true, completion: nil)
    }
}

// MARK: - CollectionView Delegate
extension WallpaperCVC {
    // size images
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {

        result =  CGSize(width: 187, height: 314)
        if DeviceType.IS_IPHONE_5 {
            result = CGSize(width: 160, height: 280)
        }
        if DeviceType.IS_IPHONE_6 {
            result =  CGSize(width: 187, height: 314)
        }
        if DeviceType.IS_IPHONE_6P {
            result = CGSize(width: 207, height: 320)
        }
        if DeviceType.IS_IPHONE_4_OR_LESS {
            result = CGSize(width: 151, height: 200)
        }
        return result;
    }

        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {


            return UIEdgeInsets(top: 15, left: 8, bottom: 5, right: 8)
        }

        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
            return 10
        }

     //size to all model screens to one.....NOW!!!!!!!!
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
            let width = UIScreen.main.bounds.width
            return CGSize(width: (width - 28)/2, height: 350) // width & height are the same to make a square cell
            }

}
// MARK: - CollectionView Layout Delegate
extension WallpaperCVC : UICollectionViewDelegateFlowLayout  {
    // Header peralax
    fileprivate func setupCollectionViewLayout() {
        let padding: CGFloat = 16
        if let layout = wpMain.collectionViewLayout as? UICollectionViewFlowLayout {
            layout.sectionInset = .init(top: padding, left: 0, bottom: padding, right: 0)
        }
    }
   // Header peralax
    fileprivate func setupCollectionView(){
        wpMain.contentInsetAdjustmentBehavior = .never
        wpMain.register(headerView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: headerId)

    }
   // Header peralax
    override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath)

        return headerView
    }
    // Header peralax
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        return .init(width: view.frame.width, height: 400)
      }
    }

单元格看起来像这样

import UIKit
import Spring
import UICountingLabel



class WallpaperCVCell: UICollectionViewCell {


    override func layoutSubviews() {
        super.layoutSubviews()
      // self.textLabel?.frame = self.bounds
    }

    func configure() {

            layer.shouldRasterize = true
            layer.rasterizationScale = UIScreen.main.scale
            contentView.layer.cornerRadius = 7
            contentView.layer.masksToBounds = true
           // contentView.layer.borderWidth = 1.0
          //  contentView.layer.borderColor = UIColor.black.cgColor
    }
    @IBOutlet weak var collectionCount: UICountingLabel!

    @IBOutlet weak var collWallpaperImage: UIImageView!


    override func awakeFromNib() {
        super.awakeFromNib()
    }
}

&& 这是视频...初始滚动滞后然后消失,但每次都会这样做

iPhone app lag video

编辑:好吧,最后我重新改造了 Kingfisher 并安装了 SDWebImage,这解决了这个问题。

最佳答案

根据给定的代码,没有什么会导致延迟。如果您可以分享一段有关延迟的短视频,可能有助于更好地理解问题。

如果您可以分享 cell.configure() 方法中的代码也会有所帮助。

我确实有一些建议可能对您有帮助,您可以尝试一下。

首先你可以移动你的设备检查

    if DeviceType.IS_IPHONE_5 {
        result = CGSize(width: 160, height: 280)
    }
    if DeviceType.IS_IPHONE_6 {
        result =  CGSize(width: 187, height: 314)
    }
    if DeviceType.IS_IPHONE_6P {
        result = CGSize(width: 207, height: 320)
    }
    if DeviceType.IS_IPHONE_4_OR_LESS {
        result = CGSize(width: 151, height: 200)
    }

在 viewDidLoad 中,这将帮助您的 Collection View 布局更快地调整单元格大小,而不必在用户每次滚动时都进行检查

类似这样的事情

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
    return result;
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.title = self.categoryName // Name to the controller or section selected
    setupDeviceSize()
    // go go gadget data...
    getData()
    buttonGray()
    setupCollectionViewLayout()
    setupCollectionView()
}

func setupDeviceSize(){

  if DeviceType.IS_IPHONE_5 {
    result = CGSize(width: 160, height: 280)
  }
  if DeviceType.IS_IPHONE_6 {
    result =  CGSize(width: 187, height: 314)
  }
  if DeviceType.IS_IPHONE_6P {
    result = CGSize(width: 207, height: 320)
  }
  if DeviceType.IS_IPHONE_4_OR_LESS {
    result = CGSize(width: 151, height: 200)
  }
}

其次,您可以为占位符图像创建一个全局变量

let loadImage = UIImage(named: "skullLoading")

并在 cellForItemAtIndexpath 中使用它,这将在每次调用 cellForItemAtIndexpath 时再次保存占位符图像的加载。

您应该始终保持 cellForItemAtIndexpath 尽可能轻,以获得流畅的滚动体验。

希望这有帮助。

关于ios - UICollectionView 延迟/掉帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55705490/

相关文章:

ios - 停止/中止 NSURLConnection

ios - 细节 View 顶部的额外空间不会消失(SwiftUI)

ios - UICollectionView 出列错误的单元格并显示错误的图像

ios - 为什么我必须将 Bundle 资源复制到主项目才能在框架中使用图像?

ios - ios 5.1.1 上的 Xcode 4.5.1 ios 二进制文件导致错误

ios - 我们可以使用一个具有两种不同编程语言的两个不同项目的单个应用程序吗?

ios - vImageBoxConvolve : errors when kernel size > 255

ios - tableview segue 到另一个 View Controller

swift - 如何在 Swift Package Manager 中添加本地库作为依赖项

ios - 忽略 #pragma 发出的警告