【问题标题】:How to change the state for an UIAction inside UIMenu at runtime?如何在运行时更改 UIMenu 内的 UIAction 的状态?
【发布时间】:2020-11-08 12:24:04
【问题描述】:

如何更改 UIAction 的状态?目标是在 UIMenu 内的 UIAction 旁边切换状态复选标记。

通过存储在视图控制器中的引用更改 UIAction 的 state 似乎根本不会更改状态。我错过了什么吗?

// View Controller
internal var menuAction: UIAction!

private func generatePullDownMenu() -> UIMenu {
    menuAction = UIAction(
        title: "Foo",
        image: UIImage(systemName: "chevron.down"),
        identifier: UIAction.Identifier("come.sample.action"),
        state:  .on
    ) { _ in self.menuAction.state = .off } // <--- THIS LINE


    let menu = UIMenu(
        title: "Sample Menu",
        image: nil,
        identifier: UIMenu.Identifier("com.sample.menu"),
        options: [],
        children: [menuAction]
    )

    return menu
}

// Inside UI setup code block
let buttonItem = UIBarButtonItem(
    title: "",
    image: UIImage(systemName: "chevron.down"),
    primaryAction: nil,
    menu: generatePullDownMenu()
)

尝试直接从闭包中更改action 状态并得到“操作是不可变的,因为它是菜单的子项”错误。现在我怀疑动作对象始终是不可变对象。

menuAction = UIAction(
    title: "Foo",
    image: UIImage(systemName: "chevron.down"),
    identifier: UIAction.Identifier("come.sample.action"),
    state:  .on
) { action in action.state = .off } // <--- THIS LINE

【问题讨论】:

    标签: ios swift uikit


    【解决方案1】:

    在状态更改时替换整个 UIMenu 对象就可以了。

    // view controller
    internal var barButton: UIBarButtonItem!
    
    // UI setup function
    barButton = UIBarButtonItem(
        image: UIImage(systemName: "arrow.up.arrow.down.square"),
        primaryAction: nil,
        menu: generatePullDownMenu()
    )
    
    // On state change inside UIAction 
    let actionNextSeen = UIAction(
        title: "foo",
        image: UIImage(systemName: "hourglass", )
        state: someVariable ? .off : .on
    ) { _ in
        someVariable = false
        self.barButton.menu = self.generatePullDownMenu()
    }
    

    参考

    https://developer.apple.com/forums/thread/653862

    【讨论】:

    • 这基本上就是我所说的。数据用作中介,您下次重新构建整个菜单。
    【解决方案2】:

    您需要重新创建菜单。此示例还将正确选择被点击的项目:

    private func setupViews()
        timeFrameButton = UIBarButtonItem(
            image: UIImage(systemName: "calendar"),
            menu: createMenu()
        )
        navigationItem.leftBarButtonItem = timeFrameButton
    }
    
    private func createMenu(actionTitle: String? = nil) -> UIMenu {
        let menu = UIMenu(title: "Menu", children: [
            UIAction(title: "Yesterday") { [unowned self] action in
                self.timeFrameButton.menu = createMenu(actionTitle: action.title)
            },
            UIAction(title: "Last week") { [unowned self] action in
                self.timeFrameButton.menu = createMenu(actionTitle: action.title)
            },
            UIAction(title: "Last month") { [unowned self] action in
                self.timeFrameButton.menu = createMenu(actionTitle: action.title)
            }
        ])
        
        if let actionTitle = actionTitle {
            menu.children.forEach { action in
                guard let action = action as? UIAction else {
                    return
                }
                if action.title == actionTitle {
                    action.state = .on
                }
            }
        } else {
            let action = menu.children.first as? UIAction
            action?.state = .on
        }
        
        return menu
    }
    

    【讨论】:

      【解决方案3】:

      不要在菜单显示时尝试更改菜单。通过更改您的数据来响应选择。同时,菜单消失了,因为用户选择了一个动作。但是现在您使用该数据在用户显示菜单时下一次构建菜单。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-17
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-13
      相关资源
      最近更新 更多