iOS - 今天分机 'show more' & 'show less' 状态不正确。折叠显示 'show less' - 需要多次按下才能修复

iOS - Today Extension 'show more' & 'show less' state incorrect. Collapsed says 'show less' - requiring multipule presses to fix

我有一个扩展程序,我拆掉了基本结构,它使自己处于不正确的状态,当它折叠时会显示 "Show Less"。

这发生在两种情况下

  1. 我用 "Show More" 展开扩展,然后离开 屏幕。我打开另一个应用程序,然后 return 到扩展程序。 扩展的扩展在我面前明显崩溃了,但仍然 说 "Show Less"
  2. 我推送一个新版本来测试更改。它将比以前扩展, 当新构建推送时,它会折叠并显示 "show less"

我还尝试过在扩展时激活另一个扩展(天气),并且在扩展后始终保持扩展状态,而我的扩展正在折叠并显示错误状态。

无论是否存在天气小部件,都会发生这种情况。

当我在代码中放置断点时,在步骤 #1 中再次调用 ViewDidLoad。

这是代码,我一点一点地删除了所有内容,直到剩下所有内容,但仍然导致问题。

class TodayController: UICollectionViewController, NCWidgetProviding {

    let reuseIdentifier = "TimeGridCell"

    override func viewDidLoad() {
        super.viewDidLoad()
        self.extensionContext?.widgetLargestAvailableDisplayMode = NCWidgetDisplayMode.expanded
    }

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }

    override func collectionView(_ collectionView: UICollectionView,
                                 numberOfItemsInSection section: Int) -> Int {
        return 3
    }

    override func collectionView(_ collectionView: UICollectionView,
                                 cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier,
                for: indexPath) as! ArtistTimeGridTableViewCell
        cell.nameLabel.text = "blah blah"
        return cell
    }

    func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize) {
        if activeDisplayMode == .expanded {
            self.preferredContentSize = (self.collectionView?.contentSize)!
        } else if activeDisplayMode == .compact {
            self.preferredContentSize = maxSize

        }
    }
}

请注意,如果我删除 self.extensionContext?.widgetLargestAvailableDisplayMode = NCWidgetDisplayMode.expanded,那么我根本无法获得展开或折叠的选项,因此这是必需的。

这是问题的图片。第一张正确,第二张错误。

发现另一个人在谈论按钮无法正常工作的问题,他们的解决方案似乎对我有用,尽管没有很好的解释到底出了什么问题?这似乎是一个 OS 错误?

iOS10 widget "Show more" "Show less" bug

延迟设置内容大小可防止出现此问题

    let deadlineTime = DispatchTime.now() + 0.2
    if activeDisplayMode == .expanded {
        DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
            self.preferredContentSize = (self.collectionView?.contentSize)!
        }
    } else if activeDisplayMode == .compact {
        DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
            self.preferredContentSize = maxSize
        }
    }

我遇到了完全相同的问题,但我使用布局约束来设置展开状态的高度。对于遇到此问题的任何人,修复只是将 layoutIfNeeded 添加到 widgetActiveDisplayModeDidChange 的末尾。

用法示例:

func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize) {
    switch activeDisplayMode {
    case .compact:
        heightContstraint.constant = 0
    case .expanded:
        heightContstraint.constant = 44 * CGFloat((items.count))
    }
    view.layoutIfNeeded()
}

刚找到正确答案。

由于您允许扩展在 viewDidLoad 中扩展大小,因此直接从 viewDidLoad 调用 widgetActiveDisplayModeDidChange

问题在于在您的 widgetActiveDisplayModeDidChange 方法中访问 collection/table 视图属性(size/element 号),因为 collection/table 视图完全仅在 viewWillAppear.

后初始化

因此,就我而言,我只是在 widgetActiveDisplayModeDidChange 中复制了 numberOfRowsInSection 计算,然后一切都开始按预期工作。

在Swift3和4

override func viewDidLoad() {
            super.viewDidLoad()
                self.extensionContext?.widgetLargestAvailableDisplayMode = NCWidgetDisplayMode.expanded
        }

        func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize) {
            if activeDisplayMode == .expanded {
                self.preferredContentSize = (self.myTableView?.contentSize)!
          //Instead of table content you can user user own size
            } else if activeDisplayMode == .compact {
                self.preferredContentSize = maxSize

            }
    }

真正的问题是在 widgetActiveDisplayModeDidChange 期间,collectionView 还不知道 contentSize,所以它会给你一个较小的值。如果你在函数中打印出来,和viewWillAppear对比一下,你就会发现区别了。

0.2 秒的延迟似乎很老套,所以我更喜欢这样:

override func viewWillAppear(_ animated: Bool) {
    if (extensionContext?.widgetActiveDisplayMode == .expanded) {
        self.preferredContentSize = self.collectionView.contentSize
    }
}

它同样适用于 tableView,这是我正在使用的小部件。如果您滑动到主屏幕并向后滑动,上面的代码将处理这种情况。但是如果你只是点击显示它不会被触发more/less,所以你仍然需要在widgetActiveDisplayModeDidChange中维护相同的代码。