如何连接NSAttributedStrings?


158

我需要搜索一些字符串并在合并字符串之前设置一些属性,因此让NSStrings->串联它们->使NSAttributedString不是一个选择,有没有办法将attributedString串联到另一个attributedString?


13
荒谬的是,在2016
。– Wedge Martin

17
即使在2018年……
DehMotth

11
仍然在2019年;)
raistlin '19

8
仍在2020年……
Hwangho Kim

Answers:


210

我建议您使用@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:用于将事实之后的属性添加到包含输入字符串的范围中。我推荐前一种方式。


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

86

如果您使用的是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 2015年

4
您可以在任何需要不可变父类型的上下文中使用可变子类型,反之亦然。您可能需要查看子类和继承。
藻类

6
是的,如果您想防御,就应该进行防御复制。(不嘲讽)
藻类

1
如果您真的想返回NSAttributedString,那么也许可以使用:return NSAttributedString(attributedString: result)
Alex

2
@ n13我将创建一个名为Helpers或的文件夹Extensions,并将此函数放在名为的文件中NSAttributedString+Concatenate.swift
大卫·劳森

34

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 upd:

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

25

试试这个:

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

哪里astring1astring2在哪里NSAttributedString


13
或者[[aString1 mutableCopy] appendAttributedString: aString2]
JWWalker 2013年

@JWWalker您的“ oneliner”已损坏。您无法获得此“串联”结果,因为appendAttributedString不返回字符串。字典也有同样的故事
gaussblurinc 2015年

@gaussblurinc:好的,当然,您的批评也适用于我们正在评论的答案。应该是NSMutableAttributedString* aString3 = [aString1 mutableCopy]; [aString3 appendAttributedString: aString2];
JWWalker,2015年

@ gaussblurinc,JWalker:更正了答案。
Linuxios 2015年

@Linuxios,也将返回resultNSMutableAttributedString。这不是作者想要看到的。stringByAppendingString-这种方法会很好
gaussblurinc

5

2020 | SWIFT 5.1:

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

let concatenated = NSAttrStr1.append(NSAttrStr2)

NSMutableAttributedStringNSAttributedString两者都可以使用的另一种方式:

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

另一种方法是...

var full = NSAttrStr1 + NSAttrStr2 + NSAttrStr3

和:

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


full += NSAttrStr1 // full == "hello 1"       
full += " world"   // full == "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

用扩展名更新了我的答案,仅添加了两个NSAttrStrings :)
Andrew

4

如果您使用的是Cocoapods,则上述两个答案的替代方法(可避免在自己的代码中发生变异)是NSAttributedStrings 上使用出色的NSAttributedString + CCLFormat类别,该类别可让您编写以下内容:

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;
}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.