从iOS 15开始,SWIFT提供了AttributedString struct ,该 struct 包含字符串的文本及其样式属性.问:给定一个现有的AttributedString,并假设(为了简单起见)属性由单个样式运行组成,您如何更改AttributedString的just the string part个呢?


这是一个典型的用例--UIButton.假设我有一个基于配置的按钮,它有一个属性标题:

let button = UIButton(configuration: .plain())
let font = UIFont(name: "Georgia", size: 16)
button.configuration?.attributedTitle = AttributedString(
    "Hello", attributes: AttributeContainer.font(font!)
)

如果我稍后将配置的标题设置为不同的标题,则属性信息将丢失.例如:

button.configuration?.title = "Goodbye"
// Button title is no longer in Georgia font!

显然,我想在这里做的是在不干扰其attributes的情况下替换属性字符串标题的text.但SWIFT的AttributedString似乎并没有提供这样一种方法.

因此,正如我在开始时所问的:这里的正确方法是什么?

推荐答案

更改AttributedString的文本非常棘手.您必须替换属性字符串的字符视图的内容-它的characters属性.要使事情变得更加困难,您不能简单地通过分配另一个字符串来做到这一点!

以我们的按钮为例,这将不会编译:

button.configuration?.attributedTitle?.characters = "Goodbye" // error

仅从简单的字符串派生字符视图也是不够的.这也不能编译:

button.configuration?.attributedTitle?.characters = "Goodbye".characters // error

这是因为简单字符串的单独字符视图不再存在;您仍在try 将字符串分配到字符视图中,而我们已经知道您不能这样做.

相反,您可以直接从您的字符串创建一个AttributedString.CharacterView,并将that赋给目标属性化字符串的characters属性.Swift 推断打字在这方面帮了大忙:

button.configuration?.attributedTitle?.characters = .init("Goodbye")

这将替换按钮的标题,而不会干扰按钮的标题的样式属性.

有关按钮的更多信息

替换按钮的标题是一件非常有用的事情,我在UIButton上做了一个小的实用程序扩展,涵盖了所有情况-一个不基于配置的按钮,一个基于配置但没有属性标题的按钮,以及一个基于配置并具有属性标题的按钮:

extension UIButton {
    func replaceTitle(_ newTitle: String) {
        guard configuration != nil else {
            setTitle(newTitle, for: .normal)
            return
        }
        guard configuration?.attributedTitle != nil else {
            configuration?.title = newTitle
            return
        }
        configuration?.attributedTitle?.characters = .init(newTitle)
    }
}

更多关于按钮的信息

对于基于配置的按钮,人们可能会问(也已经问过),为什么要使用attributedTitle?为什么不在按钮配置的buttonConfig.titleTextAttributesTransformer中设置字体?

答案是,这不适用于需要动态响应用户更改文本大小首选项的真实字体.要理解我的意思,请try 下面的示例:

let button = UIButton(configuration: .plain())
let font = UIFontMetrics(forTextStyle: .subheadline)
    .scaledFont(for: UIFont(name: "Georgia", size: 16)!)
button.configuration?.title = "Hello"
button.configuration?.titleTextAttributesTransformer = .init { container in
    container.merging(AttributeContainer.font(font))
}

您将看到,尽管按钮标题最初以正确的字体显示,尽管字体在设置按钮的配置标题后仍然存在,但字体大小的dynamism已经丢失.使用动态大小的字体,您可以将字体设置为属性标题的一部分.

事实上,这就是最终启发了我最初问题的用例,并因此得到了这个答案.

Ios相关问答推荐

滚动时突出显示工具栏项目

如何在SwiftUI中扩展双击的可检测区域?

Swift导航远离视频导致崩溃

在相机动作之前快速防止场景视点重置

由于已存在同名项目,因此无法将Mapbox.xcframework-ios.sign复制到Signature中

JSON响应中的键有时为Int,有时为字符串

如何在HStack中将sfsymbol与Text视图对齐?

Swift locationManager.requestWhenInUseAuthorization() 不提示用户

使用 Objective-C 创建 iOS 框架

如何从单独的视图更改修饰符的值

SwiftUI 故障/错误 - 在 LazyVStack 和 ScrollView 中使用 AVPlayer 时状态栏不显示

CarPlay:现在播放alert 可能吗?

在 SwiftUI 中重构提取到子视图的 GeometryReader 代码

swiftUI中的剪辑形状无法使用旋转效果

如何在不同设备的segment控制中管理文本大小(text size)?

滑动列表项以获取更多选项(Flutter)

Storyboard Segue 从视图控制器到自身

有什么方法可以加粗 NSString 的一部分?

UITextView 内容插图

为给定的 UIColor 获取更亮和更暗的 colored颜色 变化