Bagaimana saya bisa menggabungkan NSAttributedStrings?

159

Saya perlu mencari beberapa string dan menetapkan beberapa atribut sebelum menggabungkan string, sehingga memiliki NSStrings -> Menggabungkan mereka -> Membuat NSAttributedString bukan merupakan pilihan, apakah ada cara untuk menggabungkan string yang dikaitkan dengan Tring ke yang lain dikaitkan dengan Trtring?

Imanou Petit
sumber
13
Sungguh konyol betapa sulitnya ini masih pada bulan Agustus 2016.
Wedge Martin
17
Bahkan pada tahun 2018 ...
DehMotth
11
masih pada 2019;)
raistlin
8
masih pada tahun 2020 ...
Hwangho Kim

Jawaban:

210

Saya akan merekomendasikan Anda menggunakan string yang dikaitkan tunggal yang dapat diubah yang disarankan oleh @Linuxios, dan inilah contoh lain dari itu:

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

Namun, hanya demi mendapatkan semua opsi di luar sana, Anda juga bisa membuat string tunggal yang dapat diubah, dibuat dari NSString yang diformat yang berisi string input yang sudah disatukan. Anda kemudian dapat menggunakan addAttributes: range:untuk menambahkan atribut setelah fakta ke rentang yang berisi string input. Saya merekomendasikan cara sebelumnya.

Mick MacCallum
sumber
Mengapa Anda merekomendasikan menambahkan string daripada menambahkan atribut?
ma11hew28
87

Jika Anda menggunakan Swift, Anda bisa membebani +operator terlalu banyak sehingga Anda dapat menggabungkannya dengan cara yang sama dengan Anda menggabungkan string normal:

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

Sekarang Anda dapat menggabungkannya hanya dengan menambahkannya:

let helloworld = NSAttributedString(string: "Hello ") + NSAttributedString(string: "World")
ganggang
sumber
5
kelas yang bisa berubah adalah subtipe dari kelas yang tidak dapat diubah.
algal
4
Anda dapat menggunakan subtipe yang bisa berubah dalam konteks apa pun yang mengharapkan tipe induk yang tidak dapat diubah tetapi tidak sebaliknya. Anda mungkin ingin meninjau subclassing dan inheritance.
algal
6
Ya, Anda harus melakukan salinan defensif jika Anda ingin bersikap defensif. (Bukan sarkasme.)
algal
1
Jika Anda benar-benar ingin mengembalikan NSAttributedString, maka mungkin ini akan berhasil:return NSAttributedString(attributedString: result)
Alex
2
@ n13 Saya akan membuat folder bernama Helpersatau Extensionsdan menempatkan fungsi ini dalam file bernama NSAttributedString+Concatenate.swift.
David Lawson
34

Swift 3: Cukup buat NSMutableAttributedString dan tambahkan string yang dikaitkan dengannya.

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
    ]
Josh O'Connor
sumber
25

Coba ini:

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

Di mana astring1dan astring2adalah NSAttributedStrings.

Linuxios
sumber
13
Atau [[aString1 mutableCopy] appendAttributedString: aString2].
JWWalker
@JWWalker 'oneliner' Anda rusak. Anda tidak bisa mendapatkan hasil "concatenation" ini karena appendAttributedString tidak mengembalikan string. Kisah yang sama dengan kamus
gaussblurinc
@gaussblurinc: poin bagus, tentu saja kritik Anda juga berlaku untuk jawaban yang kami komentari. Seharusnya begitu NSMutableAttributedString* aString3 = [aString1 mutableCopy]; [aString3 appendAttributedString: aString2];.
JWWalker
@gaussblurinc, JWalker: Mengoreksi jawabannya.
Linuxios
@Linuxios, juga, Anda kembali resultsebagai NSMutableAttributedString. bukan apa yang ingin dilihat penulis. stringByAppendingString- metode ini akan bagus
gaussblurinc
5

2020 | SWIFT 5.1:

Anda dapat menambahkan 2 NSMutableAttributedStringdengan cara berikut:

let concatenated = NSAttrStr1.append(NSAttrStr2)

Cara lain bekerja dengan NSMutableAttributedStringdan NSAttributedStringkeduanya:

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

Cara lain adalah ....

var full = NSAttrStr1 + NSAttrStr2 + NSAttrStr3

dan:

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


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

Anda dapat melakukan ini dengan ekstensi berikut:

// 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
    }
}
Andrew
sumber
2
Saya menggunakan Swift 5.1 dan sepertinya saya tidak bisa menambahkan dua NSAttrStrings bersamaan ...
PaulDoesDev
1
Aneh. Dalam hal ini gunakan sajaNSAttrStr1.append(NSAttrStr2)
Andrew
Memperbarui jawaban saya dengan ekstensi hanya dengan menambahkan dua NSAttrStrings :)
Andrew
4

Jika Anda menggunakan Cocoapods, alternatif untuk kedua jawaban di atas yang memungkinkan Anda terhindar dari ketidakmampuan dalam kode Anda sendiri adalah dengan menggunakan kategori NSAttributedString + CCLFormat yang sangat baik di NSAttributedStrings yang memungkinkan Anda menulis sesuatu seperti:

NSAttributedString *first = ...;
NSAttributedString *second = ...;
NSAttributedString *combined = [NSAttributedString attributedStringWithFormat:@"%@%@", first, second];

Tentu saja itu hanya digunakan di NSMutableAttributedStringbawah selimut.

Ini juga memiliki keuntungan ekstra sebagai fungsi pemformatan yang lengkap - sehingga bisa melakukan lebih banyak daripada menambahkan string bersama.

fatuhoku
sumber
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;
}
gaussblurinc
sumber
1

Anda dapat mencoba SwiftyFormat Ini menggunakan sintaks berikut

let format = "#{{user}} mentioned you in a comment. #{{comment}}"
let message = NSAttributedString(format: format,
                                 attributes: commonAttributes,
                                 mapping: ["user": attributedName, "comment": attributedComment])
Igor Palaguta
sumber
1
Bisakah Anda menjelaskannya lebih lanjut? Bagaimana cara kerjanya?
Kandhal Bhutiya