Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在SwiftUI中使用属性字符串_Swift_Swiftui - Fatal编程技术网

如何在SwiftUI中使用属性字符串

如何在SwiftUI中使用属性字符串,swift,swiftui,Swift,Swiftui,如何在SwiftUI中使用AttributeString。没有可供使用的API 在文本中使用AttributedStringiOS 15和Swift 5.5 Text现在支持降价,您还可以创建自定义属性: 您甚至可以远程获取定义的属性,如: 监督厅13和14 您可以将多个文本对象与一个简单的+运算符组合在一起,该运算符将处理一些属性: 每个修改器都可以有多个特定的修改器 一个完全支持的撤退! 由于它不直接支持文本(在iOS 15之前),因此您可以将UILabel带到那里,并以您喜欢的方

如何在SwiftUI中使用AttributeString。没有可供使用的API 在文本中使用AttributedString

iOS 15和Swift 5.5
Text
现在支持降价,您还可以创建自定义属性:

您甚至可以远程获取定义的属性,如:


监督厅13和14 您可以将多个
文本
对象与一个简单的
+
运算符组合在一起,该运算符将处理一些属性:

每个修改器都可以有多个特定的修改器


一个完全支持的撤退! 由于它不直接支持
文本
(在iOS 15之前),因此您可以将
UILabel
带到那里,并以您喜欢的方式对其进行修改:

实施:
属性字符串的概念是带有属性的字符串。在SwiftUI中,这个想法是通过
文本
属性修饰符和
+
操作符实现的。如以下示例所示:

Group {
    Text("Bold")
        .fontWeight(.bold) +
    Text("Underlined")
        .underline() +
    Text("Color")
        .foregroundColor(Color.red)
}


有许多答案都使用
UILabel
UITextView
。我很好奇是否有可能创建一个不依赖任何UIKit功能的本地SwiftUI实现。这是一个适合我当前需要的实现。它远不是
NSAttributedString
规范的一个完整实现,但它绝对足够满足最基本的需求。采用HTML字符串的
NSAttributedString
构造函数是我制作的自定义类别,非常容易实现。如果有人想用它来运行并创建一个更健壮、更完整的组件,你就是我的英雄。遗憾的是,我没有时间做这样的项目

//
//  AttributedText.swift
//
import SwiftUI

struct AttributedTextBlock {
    let content: String
    let font: Font?
    let color: Color?
}

struct AttributedText: View {
    var attributedText: NSAttributedString?
    
    private var descriptions: [AttributedTextBlock] = []
    
    init(_ attributedText: NSAttributedString?) {
        self.attributedText = attributedText
        
        self.extractDescriptions()
    }
    
    init(stringKey: String) {
        self.init(NSAttributedString(htmlString: NSLocalizedString(stringKey, comment: "")))
    }
    
    init(htmlString: String) {
        self.init(NSAttributedString(htmlString: htmlString))
    }
    
    private mutating func extractDescriptions()  {
        if let text = attributedText {
            text.enumerateAttributes(in: NSMakeRange(0, text.length), options: [], using: { (attribute, range, stop) in
                let substring = (text.string as NSString).substring(with: range)
                let font =  (attribute[.font] as? UIFont).map { Font.custom($0.fontName, size: $0.pointSize) }
                let color = (attribute[.foregroundColor] as? UIColor).map { Color($0) }
                descriptions.append(AttributedTextBlock(content: substring,
                                                        font: font,
                                                        color: color))
            })
        }
    }
    
    var body: some View {
        descriptions.map { description in
            Text(description.content)
                .font(description.font)
                .foregroundColor(description.color)
        }.reduce(Text("")) { (result, text) in
            result + text
        }
    }
}

struct AttributedText_Previews: PreviewProvider {
    static var previews: some View {
        AttributedText(htmlString: "Hello! <b>World</b>")
    }
}
//
//斯威夫特
//
导入快捷键
结构AttributedTextBlock{
让内容:字符串
让字体:字体?
让颜色:颜色?
}
结构AttributeText:视图{
var attributedText:NSAttributedString?
私有变量描述:[AttributedTextBlock]=[]
init(uuAttributeText:NSAttributedString?){
self.attributedText=attributedText
self.extractDescriptions()
}
init(stringKey:String){
self.init(NSAttributedString(htmlString:NSLocalizedString(stringKey,注释:))
}
init(htmlString:String){
self.init(NSAttributedString(htmlString:htmlString))
}
私有变异函数extractDescriptions(){
如果let text=attributedText{
枚举属性(在:NSMakeRange(0,text.length)中),选项:[],在中使用:{(属性,范围,停止)
let substring=(text.string作为NSString)。substring(with:range)
让font=(属性[.font]为?UIFont).map{font.custom($0.fontName,size:$0.pointSize)}
让color=(属性[.foregroundColor]为?UIColor).map{color($0)}
descriptions.append(AttributedTextBlock)(内容:子字符串,
字体:字体,
颜色:颜色)
})
}
}
var body:一些观点{
descriptions.map{中的description
文本(description.content)
.font(description.font)
.foregroundColor(描述.颜色)
}.reduce(Text(“”){(result,Text)in
结果+文本
}
}
}
结构AttributedText\u预览:PreviewProvider{
静态var预览:一些视图{
AttributeText(htmlString:“你好!世界”)
}
}

如果要使用NSAttributedString实现动态高度文本,可以使用以下方法:

实施: }

用法: iOS 15(测试版) 我们终于成功了!它真的很容易使用

要将属性应用于特定范围,请使用方法


有关更多详细信息,请参阅我的。还有,你可以

有没有办法让其中一个文本可以点击?TapSirture似乎不太合适,因为它返回的是
一些视图
,而不是
文本
?+1,更自然,但访问更少。它在格式化文本时覆盖了一些长度,而不添加额外和复杂的代码。用法:“传递给不带参数的调用的参数”SwiftUI 2.0有一个名为
Label
的结构。您可能忘记实现自己的
标签
,它与原始版本冲突@Ixx@MojtabaHosseini-如何在
UIKLabel
上启用对齐?尝试过在堆栈和自己的视图上换行,但似乎没有任何效果。如果您支持多种语言,这肯定不好。这里,如果我们这样使用,如果我们想添加单击颜色或任何其他文本,我们似乎无法使用它,尽管有可能在纯swift UI中创建属性字符串类型系统这是一项出色的工作!我添加了一个滚动视图,然后就去参加比赛了!我保存了40K+字节NSAttributedString的数据对象,视图会毫不延迟地打开它们(它们在出现之前需要5秒或更长时间)。如果可以,我会不止一次投票。干得好!不幸的是,获取日志:AttributeGraph:在视图中使用属性X时通过属性X检测到循环,最终导致崩溃:/有趣的是,我不知道为什么,可能是您的属性字符串有一个代码没有考虑的用例。如果你能找到bug,发布一个要点,我会用bug修复更新答案。
Group {
    Text("Bold")
        .fontWeight(.bold) +
    Text("Underlined")
        .underline() +
    Text("Color")
        .foregroundColor(Color.red)
}
//
//  AttributedText.swift
//
import SwiftUI

struct AttributedTextBlock {
    let content: String
    let font: Font?
    let color: Color?
}

struct AttributedText: View {
    var attributedText: NSAttributedString?
    
    private var descriptions: [AttributedTextBlock] = []
    
    init(_ attributedText: NSAttributedString?) {
        self.attributedText = attributedText
        
        self.extractDescriptions()
    }
    
    init(stringKey: String) {
        self.init(NSAttributedString(htmlString: NSLocalizedString(stringKey, comment: "")))
    }
    
    init(htmlString: String) {
        self.init(NSAttributedString(htmlString: htmlString))
    }
    
    private mutating func extractDescriptions()  {
        if let text = attributedText {
            text.enumerateAttributes(in: NSMakeRange(0, text.length), options: [], using: { (attribute, range, stop) in
                let substring = (text.string as NSString).substring(with: range)
                let font =  (attribute[.font] as? UIFont).map { Font.custom($0.fontName, size: $0.pointSize) }
                let color = (attribute[.foregroundColor] as? UIColor).map { Color($0) }
                descriptions.append(AttributedTextBlock(content: substring,
                                                        font: font,
                                                        color: color))
            })
        }
    }
    
    var body: some View {
        descriptions.map { description in
            Text(description.content)
                .font(description.font)
                .foregroundColor(description.color)
        }.reduce(Text("")) { (result, text) in
            result + text
        }
    }
}

struct AttributedText_Previews: PreviewProvider {
    static var previews: some View {
        AttributedText(htmlString: "Hello! <b>World</b>")
    }
}
struct TextWithAttributedString: View {

var attributedText: NSAttributedString
@State private var height: CGFloat = .zero

var body: some View {
    InternalTextView(attributedText: attributedText, dynamicHeight: $height)
        .frame(minHeight: height)
}

struct InternalTextView: UIViewRepresentable {

    var attributedText: NSAttributedString
    @Binding var dynamicHeight: CGFloat

    func makeUIView(context: Context) -> UITextView {
        let textView = UITextView()
        textView.textAlignment = .justified
        textView.isScrollEnabled = false
        textView.isUserInteractionEnabled = false
        textView.showsVerticalScrollIndicator = false
        textView.showsHorizontalScrollIndicator = false
        textView.allowsEditingTextAttributes = false
        textView.backgroundColor = .clear
        textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        textView.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
        return textView
    }

    func updateUIView(_ uiView: UITextView, context: Context) {
        uiView.attributedText = attributedText
        DispatchQueue.main.async {
            dynamicHeight = uiView.sizeThatFits(CGSize(width: uiView.bounds.width, height: CGFloat.greatestFiniteMagnitude)).height
        }
    }
}
    VStack {
       TextWithAttributedString(attributedText: viewModel.description)
         .padding([.leading, .trailing], self.horizontalPadding)
         .layoutPriority(1)
         .background(Color.clear)
    }
    .transition(.opacity)
    .animation(.linear)
struct ContentView: View {
    var body: some View {
        VStack(spacing: 40) {
            
            /// Note: You can replace `$0` with `string in string`
            
            VStack {
                Text("Regular")
                Text("Italics") { $0.font = Font.system(size: 17).italic() }
                Text("Bold") { $0.font = Font.system(size: 17).bold() }
                Text("Strikethrough") { $0.strikethroughColor = Color.red }
                Text("Code") { $0.font = Font.system(size: 17, design: .monospaced) }
                Text("Foreground Color") { $0.foregroundColor = Color.purple }
                Text("Background Color") { $0.backgroundColor = Color.yellow }
                Text("Underline") { $0.underlineColor = Color.green }
            }
            
            VStack {
                Text("Kern") { $0.kern = CGFloat(10) }
                Text("Tracking") { $0.tracking = CGFloat(10) }
            }
            
            VStack {
                Text("Baseline Offset") { $0.baselineOffset = CGFloat(10) }
                Text("Link") { $0.link = URL(string: "https://apple.com") }
            }
        }
    }
}

/// extension to make applying AttributedString even easier
extension Text {
    init(_ string: String, configure: ((inout AttributedString) -> Void)) {
        var attributedString = AttributedString(string) /// create an `AttributedString`
        configure(&attributedString) /// configure using the closure
        self.init(attributedString) /// initialize a `Text`
    }
}
struct ContentView: View {
    var body: some View {
        Text("Some Attributed String") { string in
            string.foregroundColor = .blue
            if let range = string.range(of: "Attributed") { /// here!
                string[range].foregroundColor = .red
            }
        }
    }
}