Как вручную изменить выбранный UIAction внутри UIMenu?

Цель: попытаться создать экран выбора фильтра (в виде карточек), в котором есть кнопки UIButton с прикрепленными к ним элементами UIMenu. Когда я выбираю любой из фильтров и нажимаю кнопку «Применить фильтры», я закрываю контроллер представления фильтров и возвращаюсь к экрану представления коллекции, чтобы обновить данные с помощью выбранных фильтров.

Проблема: с уже выбранными фильтрами, когда я хочу вернуться снова, чтобы изменить какие-либо фильтры, я нажимаю кнопку фильтров, чтобы открыть контроллер просмотра фильтров, но, очевидно, ни один из вариантов UIMenu не сохраняется, поскольку они сначала сбрасываются до значений по умолчанию установка индекса.

Как решить ?: При передаче моих данных обратно из filterVC на главный экран списка я передаю заголовок выбранного UIMenu. Я думал, что могу передать это обратно в filterVC и по умолчанию меню для переданных данных (т.е. мог бы найти заголовок и сделать его выбранным UIAction в UIMenu), однако я, похоже, не могу найти способ вручную выберите, какой UIAction должен быть выбранным состоянием UIMenu!

          var spaceTypeMenu: UIMenu {
    return UIMenu(title: "Space Type", image: nil, identifier: nil, options: [], children: spaceTypeMenuItems)
}

    private var spaceTypeMenuItems: [UIAction] {
    return [
        UIAction(title: "All", handler: { (_) in }),
        UIAction(title: "Meeting Room", handler: { (_) in }),
        UIAction(title: "Desk", handler: { (_) in }),
        UIAction(title: "Boardroom", handler: { (_) in })
    ]
}

Затем из viewdidload() вызывается следующее:

      func createSpaceTypeMenu() {
    spaceTypeButton?.menu = spaceTypeMenu
    spaceTypeButton?.showsMenuAsPrimaryAction = true
}

После того, как фильтры были выбраны, я передаю их обратно в предыдущий VC:

      @IBAction func applyFiltersButtonPressed(_ sender: UIButton) {
    self.dismiss(animated: true) {
        let filter = Filters(site: self.siteButton?.titleLabel?.text,
                             spaceType: self.spaceTypeButton?.titleLabel?.text,
                             date: self.datePickerView.datePickerView?.date,
                             duration: self.selectedDuration)
        self.applyFiltersCallback?(filter)
    }
}

Site, Spacetype, duration - все это UIbuttons с UIMenu для параметров фильтра, которые на данный момент жестко запрограммированы, как указано выше.

Я хочу, чтобы если я выбрал «Рабочие столы» до того, как applyFiltersButtonPressed() был вызван для закрытия VC, когда я вернусь к этому FiltersVC, я хочу, чтобы «Рабочие столы» по-прежнему были выбраны в качестве текста в UIbutton, а также хочу, чтобы поставьте галочку рядом с «Рабочими столами» и не хотите, чтобы пункты меню по умолчанию возвращались к первому варианту, который был «Все».

Надеюсь, это имеет смысл?

2 ответа

Решение

Я сам узнал, как это сделать, надеюсь, это поможет кому-то еще в том же положении, что и я:

      private func updateActionState(actionTitle: String? = nil, menu: UIMenu) -> UIMenu {
    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
}

и может быть вызван:

      private func createSiteMenu(actionTitle: String? = nil) {
    let menu = UIMenu(title: "Site", image: nil, identifier: nil, options: [], children: siteMenuItems)
    siteButton?.menu = updateActionState(actionTitle: actionTitle, menu: menu)
    siteButton?.showsMenuAsPrimaryAction = true
}

Спасибо, это помогло решить мою аналогичную проблему. Я использую всплывающие и раскрывающиеся меню ios15, но хотел, чтобы меню заполнялось из перечисления с необработанными значениями в качестве параметров меню.

      enum SortOrder: String, Codable, CaseIterable {
    case name = "Name"
    case category = "Category"
    case qty = "Quantity"
    case value = "Value"
    case token = "Token"
}
let sortClosure = { [self] (action: UIAction) in  
    // closure actions based on self.sortOrderPopup.currentTitle!
}

var sortOrderPopupOptions: [UIAction] = []
for sortOption in ListLibrary.SortOrder.allCases {
    sortOrderPopupOptions.append(UIAction(title: sortOption.rawValue, handler: sortClosure))
}

sortOrderPopup.menu = UIMenu(children: sortOrderPopupOptions)
menuSelection = currentList.sortOrder.rawValue

sortOrderPopup.menu = updateActionState(actionTitle: menuSelection, menu: sortOrderPopup.menu!)

Ваше решение работает отлично и может быть изменено для изменения других свойств меню!

Другие вопросы по тегам