简体   繁体   English

Mac 上 collectionview 单元格中的 UITextView 尖峰 cpu

[英]UITextView in collectionview cell on mac spikes cpu

I have a simple UIKit application that has a UITextView in a UICollectionViewCell .我有一个简单的 UIKit 应用程序,它在UICollectionViewCell中有一个UITextView The app is designed for iOS/iPadOS and works just fine on those platforms.该应用程序专为 iOS/iPadOS 设计,在这些平台上运行良好。 However, when run on Mac (Designed for iPad) as soon as I start scrolling the collectionview, the cpu usage spikes to ~85% and stays there indefinitely.但是,当我开始滚动集合视图时在 Mac(专为 iPad 设计)上运行时,CPU 使用率飙升至 ~85% 并无限期地保持在那里。 The only way to lower the cpu is to click outside of the application window, but once it comes to the foreground again, the cpu usage jumps right back up.降低 cpu 的唯一方法是在应用程序 window 之外单击,但一旦它再次出现在前台,cpu 使用率就会立即跳回。 I've tried running on Mac in Catalyst mode too, but the same problem occurs with slightly less cpu usage (~45%).我也试过在 Mac 上以 Catalyst 模式运行,但同样的问题发生在 cpu 使用率略低 (~45%) 的情况下。

Additionally the debugger constantly spits out [API] cannot add handler to 3 from 3 - dropping while scrolling.此外,调试器不断吐出[API] cannot add handler to 3 from 3 - dropping

Does anyone have an explanation or solutions for this?有人对此有解释或解决方案吗?

I'm using Xcode Version 14.1 (14B47b) on macOS Ventura 13.0 (22A380).我在 macOS Ventura 13.0 (22A380) 上使用 Xcode 版本 14.1 (14B47b)。

class ViewController: UIViewController {
    var dataSource: UICollectionViewDiffableDataSource<Section, String>! = nil
    var collectionView: UICollectionView! = nil
    var items = Array(0...100).map{"Item \($0)"}
    
    enum Section: String {
        case main
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.title = "List"
        configureCollectionView()
        configureDataSource()
        applyInitialSnapshot()
    }
    
    private func createLayout() -> UICollectionViewLayout {
        return UICollectionViewCompositionalLayout { sectionIndex, layoutEnvironment in
            let size = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(100))
            let item = NSCollectionLayoutItem(layoutSize: size)
            let group = NSCollectionLayoutGroup.horizontal(layoutSize: size, subitems: [item])
            
            return NSCollectionLayoutSection(group: group)
        }
    }
    
    private func configureCollectionView() {
        collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createLayout())
        collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        collectionView.backgroundColor = .systemBackground
        view.addSubview(collectionView)
    }
    
    private func configureDataSource() {
        let cellRegistration = UICollectionView.CellRegistration<TestCell, String> { (cell, indexPath, item) in
            cell.configure(title: item, row: indexPath.item)
        }
        
        dataSource = UICollectionViewDiffableDataSource<Section, String>(collectionView: collectionView) {
            (collectionView, indexPath, identifier) -> UICollectionViewCell? in
            
            return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: identifier)
        }
    }
    
    private func applyInitialSnapshot() {
        var snapshot = NSDiffableDataSourceSnapshot<Section, String>()
        snapshot.appendSections([.main])
        snapshot.appendItems(items)
        
        dataSource.apply(snapshot, animatingDifferences: false)
    }
}
class TestCell: UICollectionViewCell {
    private let annotationsTextView = UITextView()

    override init(frame: CGRect) {
        super.init(frame: frame)
        addViews()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func configure(title: String, row: Int) {
        annotationsTextView.attributedText = .init(string: "Row: \(row) Item: \(title)", attributes: [.font: UIFont.preferredFont(forTextStyle: .title1)])
    }
    
    private func addViews() {
        annotationsTextView.isScrollEnabled = false
        annotationsTextView.isEditable = false
        annotationsTextView.translatesAutoresizingMaskIntoConstraints = false
        
        contentView.addSubview(annotationsTextView)
        
        NSLayoutConstraint.activate([
            annotationsTextView.topAnchor.constraint(equalTo: contentView.topAnchor),
            annotationsTextView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
            annotationsTextView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            annotationsTextView.trailingAnchor.constraint(equalTo:  contentView.trailingAnchor),
        ])
    }
}

I'm experiencing this exact behavior in Ventura whenever there is a UITextView anywhere in the view hierarchy with either isSelectable or isEditable set to true, but only while the UITextView is NOT first responder.每当视图层次结构中的任何位置有一个 UITextView 且 isSelectable 或 isEditable 设置为 true 时,我都会在 Ventura 中遇到这种确切的行为,但前提是 UITextView 不是第一响应者。 This occurs whether the UITextView is visible or hidden.无论 UITextView 是可见还是隐藏,都会发生这种情况。

The excess CPU usage can be prevented by any of the following:可以通过以下任一方式防止 CPU 使用率过高:

  • Remove the UITextView from the view hierarchy.从视图层次结构中删除 UITextView。
  • Set isSelectable AND isEditable to false.将 isSelectable AND isEditable 设置为 false。
  • Make the UITextView first responder.使 UITextView 成为第一响应者。

I'm still investigating and will update here if I find more.我仍在调查中,如果发现更多,我会在这里更新。 We should all probably report the issue to Apple as I imagine they will need to fix this at the system level.我们可能都应该向 Apple 报告这个问题,因为我想他们需要在系统级别解决这个问题。

2022-12-01: Update 2022-12-01:更新

This issue appears to have been resolved as of macOS 13.1 beta 4 (22C5059b).从 macOS 13.1 beta 4 (22C5059b) 开始,此问题似乎已得到解决。 Hallelujah!哈利路亚!

I am still on 13.0.1 and had the same problem (tons of [API] cannot add handler to 3 from 3 - dropping).我仍在使用 13.0.1 并遇到了同样的问题(大量 [API] 无法将处理程序从 3 添加到 3 - 丢弃)。 Was able to narrow it down to a call to UITableView.scrollToNearestSelectedRow with animated = true.能够将其缩小到调用 UITableView.scrollToNearestSelectedRow 并使用 animated = true。

Setting animated to false stops the logging.将 animated 设置为 false 会停止记录。 I guess I'll have to check out 13.1我想我得去看看 13.1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM