如何拼接NSAttributedStrings?

188

在合并字符串之前,我需要搜索一些字符串并设置一些属性,因此不能使用NSStrings ->连接它们->制作NSAttributedString的选项,有没有办法将attributedString连接到另一个attributedString中?


19
2016年8月,这件事情仍然如此困难,真是可笑。 - Wedge Martin
24
即使在2018年,女性在职场上仍然面临许多挑战和不平等待遇,例如性别歧视、工资差距和缺乏晋升机会。 - DehMotth
18
仍然是2019年 ;) - raistlin
23
2020 年仍然... - Hwangho Kim
9
啊...距离2021年还有两周!祝我们所有人圣诞快乐;) - Sapozhnik Ivan
显示剩余11条评论
9个回答

222

我建议你像@Linuxios建议的那样使用一个可变的属性字符串,这里提供另一个示例:

NSMutableAttributedString *mutableAttString = [[NSMutableAttributedString alloc] init];

NSString *plainString = // ...
NSDictionary *attributes = // ... a dictionary with your attributes.
NSAttributedString *newAttString = [[NSAttributedString alloc] initWithString:plainString attributes:attributes];

[mutableAttString appendAttributedString:newAttString];

然而,为了列举所有选项,你也可以创建一个可变的属性字符串,该字符串由一个包含已经组合好的输入字符串的格式化NSString创建。然后,您可以使用addAttributes:range:在包含输入字符串的范围之后添加属性。尽管如此,我还是推荐前一种方式。


1
为什么您建议追加字符串而不是添加属性? - ma11hew28

107
如果你正在使用 Swift,你可以重载 + 运算符,以便你可以像连接普通字符串一样连接它们。

如果您使用Swift,则可以重载 + 运算符,以便可以像连接普通字符串一样连接它们:

// concatenate attributed strings
func + (left: NSAttributedString, right: NSAttributedString) -> NSAttributedString
{
    let result = NSMutableAttributedString()
    result.append(left)
    result.append(right)
    return result
}

现在您可以通过将它们添加在一起来连接它们:

let helloworld = NSAttributedString(string: "Hello ") + NSAttributedString(string: "World")

5
可变类是不可变类的子类型。 - algal
4
您可以在任何需要不可变父类型的上下文中使用可变子类型,但反过来则不行。您可能需要复习子类化和继承的相关知识。 - algal
6
如果你想要防御性编程,那么你应该进行防御性拷贝。(不是讽刺) - algal
1
如果你真的想要返回NSAttributedString,那么也许这个会起作用:return NSAttributedString(attributedString: result) - Alex
2
@n13 我会创建一个名为 HelpersExtensions 的文件夹,并将此函数放在名为 NSAttributedString+Concatenate.swift 的文件中。 - David Lawson
显示剩余4条评论

42

Swift 3:只需创建一个NSMutableAttributedString并将属性字符串附加到其中即可。

let mutableAttributedString = NSMutableAttributedString()

let boldAttribute = [
    NSFontAttributeName: UIFont(name: "GothamPro-Medium", size: 13)!,
    NSForegroundColorAttributeName: Constants.defaultBlackColor
]

let regularAttribute = [
    NSFontAttributeName: UIFont(name: "Gotham Pro", size: 13)!,
    NSForegroundColorAttributeName: Constants.defaultBlackColor
]

let boldAttributedString = NSAttributedString(string: "Warning: ", attributes: boldAttribute)
let regularAttributedString = NSAttributedString(string: "All tasks within this project will be deleted.  If you're sure you want to delete all tasks and this project, type DELETE to confirm.", attributes: regularAttribute)
mutableAttributedString.append(boldAttributedString)
mutableAttributedString.append(regularAttributedString)

descriptionTextView.attributedText = mutableAttributedString

Swift5更新:

    let captionAttribute = [
        NSAttributedString.Key.font: Font.captionsRegular,
        NSAttributedString.Key.foregroundColor: UIColor.appGray
    ]

28

试一下这个:

NSMutableAttributedString* result = [astring1 mutableCopy];
[result appendAttributedString:astring2];

astring1astring2NSAttributedString


13
或者[[aString1 mutableCopy] appendAttributedString: aString2]。意思是将字符串aString2追加到aString1后面,并创建一个可变的字符串对象来完成操作。 - JWWalker
@JWWalker,你的“一行代码”已经损坏了。你不能得到这个“连接”结果,因为appendAttributedString并不返回字符串。字典也是同样的情况。 - gaussblurinc
@gauusblurinc:说得好,当然你的批评也适用于我们正在评论的答案。应该是NSMutableAttributedString* aString3 = [aString1 mutableCopy]; [aString3 appendAttributedString: aString2]; - JWWalker
@Linuxios 这意味着你的方法在安全/稳定性方面存在潜在问题。不可变对象更好,因为它们不能被第三方人员更改。例如,NSString类型的所有属性都应该有复制属性,因为它们不应该被任何拥有指向它们的指针的人更改。 - gaussblurinc
让我们在聊天中继续这个讨论 - Linuxios
显示剩余5条评论

16

2020年| SWIFT 5.1:

您可以通过以下方式添加2个NSMutableAttributedString

let concatenated = NSAttrStr1.append(NSAttrStr2)

另一种方法使用NSMutableAttributedStringNSAttributedString

[NSAttrStr1, NSAttrStr2].joinWith(separator: "")

另外一种方式是....

var full = NSAttrStr1 + NSAttrStr2 + NSAttrStr3

和:

var full = NSMutableAttributedString(string: "hello ")
// NSAttrStr1 == 1


full += NSAttrStr1 // "hello 1"       
full += " world"   // "hello 1 world"

您可以使用以下扩展程序来完成此操作:

// works with NSAttributedString and NSMutableAttributedString!
public extension NSAttributedString {
    static func + (left: NSAttributedString, right: NSAttributedString) -> NSAttributedString {
        let leftCopy = NSMutableAttributedString(attributedString: left)
        leftCopy.append(right)
        return leftCopy
    }
    
    static func + (left: NSAttributedString, right: String) -> NSAttributedString {
        let leftCopy = NSMutableAttributedString(attributedString: left)
        let rightAttr = NSMutableAttributedString(string: right)
        leftCopy.append(rightAttr)
        return leftCopy
    }
    
    static func + (left: String, right: NSAttributedString) -> NSAttributedString {
        let leftAttr = NSMutableAttributedString(string: left)
        leftAttr.append(right)
        return leftAttr
    }
}

public extension NSMutableAttributedString {
    static func += (left: NSMutableAttributedString, right: String) -> NSMutableAttributedString {
        let rightAttr = NSMutableAttributedString(string: right)
        left.append(rightAttr)
        return left
    }
    
    static func += (left: NSMutableAttributedString, right: NSAttributedString) -> NSMutableAttributedString {
        left.append(right)
        return left
    }
}

2
我正在使用Swift 5.1,似乎无法将两个NSAttrStrings简单地相加... - PaulDoesDev
1
奇怪。在这种情况下,只需使用 NSAttrStr1.append(NSAttrStr2) - Andrew_STOP_RU_WAR_IN_UA
更新了我的答案,添加了仅用于添加两个NSAttrStrings的扩展 :) - Andrew_STOP_RU_WAR_IN_UA
1
使用 Swift 5 的 joinWith 方法似乎无法正常工作...最终使用了 append 方法。 - Ultimate_93

4
如果你正在使用Cocoapods,避免在自己的代码中使用可变性的另一种选择是使用优秀的NSAttributedString+CCLFormat类别,它可以让你像这样编写:NSAttributedString
NSAttributedString *first = ...;
NSAttributedString *second = ...;
NSAttributedString *combined = [NSAttributedString attributedStringWithFormat:@"%@%@", first, second];

当然,它只是在底层使用了NSMutableAttributedString

它还具有完整的格式化功能,因此它可以做比仅追加字符串更多的事情。


1
// Immutable approach
// class method

+ (NSAttributedString *)stringByAppendingString:(NSAttributedString *)append toString:(NSAttributedString *)string {
  NSMutableAttributedString *result = [string mutableCopy];
  [result appendAttributedString:append];
  NSAttributedString *copy = [result copy];
  return copy;
}

//Instance method
- (NSAttributedString *)stringByAppendingString:(NSAttributedString *)append {
  NSMutableAttributedString *result = [self mutableCopy];
  [result appendAttributedString:append];
  NSAttributedString *copy = [result copy];
  return copy;
}

1

你可以尝试使用SwiftyFormat。它使用以下语法。

let format = "#{{user}} mentioned you in a comment. #{{comment}}"
let message = NSAttributedString(format: format,
                                 attributes: commonAttributes,
                                 mapping: ["user": attributedName, "comment": attributedComment])

1
你能否详细说明一下吗?它的工作原理是什么? - Kandhal Bhutiya

0
private var fillAttributes:[NSMutableAttributedString.Key : Any]? = nil

fontAttributes = [.foregroundColor : SKColor.red,
                  .strokeWidth : 0.0,
                  .font : CPFont(name: "Verdana-Bold",
                  .size : 50,]

fontAttributes.updateValue(SKColor.green, forKey: .foregroundColor)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接