在UIBarButtonItem上调用setTitleTextAttributes对iOS 11

时间:2018-05-02 10:38:52

标签: ios11 uibarbuttonitem navigationbar

我在didFinishLaunchingWithOptions中使用外观代理在项目中设置UIBarButtonItem标题字体,如下所示:

UIBarButtonItem.appearance().setTitleTextAttributes([
                NSAttributedStringKey.font: customFont
            ]
            , for: .normal)

我想要做的是根据用户选择更改此字体? 因此,当用户选择字体时,我将其存储在UserDefaults中,然后向我知道具有UIBarButtonItems的视图控制器发送本地通知,并按照以下方式直接重置:

navigationItem.leftBarButtonItems?.forEach { $0.setTitleTextAttributes([NSAttributedStringKey.font: ...], for: .normal) }
navigationItem.rightBarButtonItems?.forEach { $0.setTitleTextAttributes([NSAttributedStringKey.font: ...], for: .normal) }
navigationItem.backBarButtonItem?.setTitleTextAttributes([NSAttributedStringKey.font: customFont], for: .normal)

这在iOS 10中按预期工作,但在iOS 11中,它不会对左,右或后栏按钮项目产生直接影响。

如果弹出视图控制器然后再次按下导航堆栈,则后栏按钮项目会调整为新字体 - 条形按钮项目不会更改,直到下一个应用程序运行。

我自然会在导航栏标题中做同样的事情,所以在AppDelegate:

UINavigationBar.appearance().titleTextAttributes = [
        NSAttributedStringKey.font: ...
    ]
    if #available(iOS 11.0, *) {
        UINavigationBar.appearance().largeTitleTextAttributes = [
            NSAttributedStringKey.font : ...
        ]
    }

在每个视图控制器中,我再次重置这些值,标题立即改变字体。

我尝试将条形按钮项目标题文本属性设置为每种控制状态下的新字体,即:[.normal, .highlighted, .disabled]没有运气。

我还尝试将navigationItem.leftBarButtonItem设置为UIBarButonItem的新实例,希望这将有新字体,但按钮完全消失:D

我尝试的最后一件事是在导航栏上调用setNeedsDisplaylayoutIfNeeded,但仍然没有任何反应。

可以找到案例的示例项目here

1 个答案:

答案 0 :(得分:0)

这是一个超级hacky机制来解决看似明显的错误(或未记录的优化):

    for controlState in [UIControlState.disabled, .highlighted, .normal] {

        self.changeBarButtonFont(barButtonItem: self.updateButton, font: font, controlState: controlState)

        self.changeBarButtonFont(barButtonItem: self.selectButton, font: font, controlState: controlState)
    }


private func changeBarButtonFont(barButtonItem: UIBarButtonItem, font: UIFont, controlState: UIControlState) {
    barButtonItem.title = barButtonItem.title! + " "

    barButtonItem.setTitleTextAttributes([NSAttributedStringKey.font : font], for: controlState)

    DispatchQueue.main.async
    {
        barButtonItem.title = barButtonItem.title?.trimmingCharacters(in: CharacterSet.whitespaces)
    }
}

请注意,这不会100%工作,因为“更改字体”上的快速点击不会注册。但也许你可以解决这个问题?