Як я можу об'єднати NSAttributedStrings?


158

Мені потрібно здійснити пошук деяких рядків і встановити деякі атрибути до об'єднання рядків, тому мати NSStrings -> Concatenate -> Make NSAttributedString не є варіантом, чи є спосіб з'єднати attributedString з іншим attributedString?


13
Смішно, наскільки це важко досі у серпні 2016 року
Клін Мартін,

17
Навіть у 2018 році ...
DehMotth

11
ще в 2019 році;)
raistlin

8
ще в 2020 році ...
Хванхо Кім

Відповіді:


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

4
Ви можете використовувати змінний підтип у будь-якому контексті, який очікує незмінний батьківський тип, але не навпаки. Можливо, ви хочете переглянути підкласи та успадкування.
algal

6
Так, ви повинні зробити захисну копію, якщо хочете бути оборонною. (Не сарказм.)
algal

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

Де astring1і astring2є NSAttributedStringс.


13
Або [[aString1 mutableCopy] appendAttributedString: aString2].
JWWalker

@JWWalker ваш "oneliner" пошкоджений. Ви не можете отримати цей результат "конкатенації", оскільки appendAttributedString не повертає рядок. Та сама історія зі словниками
gaussblurinc

@gaussblurinc: Добре, звичайно, ваша критика стосується і відповіді, яку ми коментуємо. Це повинно бути NSMutableAttributedString* aString3 = [aString1 mutableCopy]; [aString3 appendAttributedString: aString2];.
JWWalker

@gaussblurinc, JWalker: Виправлено відповідь.
Linuxios

@Linuxios, також, ви повертаєтеся resultяк NSMutableAttributedString. це не те, що хоче бачити автор. stringByAppendingString- цей метод буде хорошим
gaussblurinc

5

2020 | SWIFT 5.1:

Ви можете додати 2 NSMutableAttributedStringнаступним способом:

let concatenated = NSAttrStr1.append(NSAttrStr2)

Інший спосіб роботи з NSMutableAttributedStringі NSAttributedStringтак:

[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)
Андрій

Оновлено мою відповідь із розширеннями для лише додавання двох NSAttrStrings :)
Андрій

4

Якщо ви використовуєте Cocoapods, альтернативою обом вищевказаним відповідям, які дозволяють уникнути змін у власному коді, є використання чудової категорії NSAttributedString + CCLFormat для NSAttributedStrings, яка дозволяє вам написати щось на зразок:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.