Come posso concatenare NSAttributedStrings?


159

Ho bisogno di cercare alcune stringhe e impostare alcuni attributi prima di unire le stringhe, quindi avere NSStrings -> Concatenali -> Rendi NSAttributedString non è un'opzione, c'è un modo per concatenare attributoString con un altro attributoString?


13
È ridicolo quanto sia ancora difficile nell'agosto del 2016.
Wedge Martin,

17
Anche nel 2018 ...
DehMotth il

11
ancora nel 2019;)
raistlin,

8
ancora nel 2020 ...
Hwangho Kim il

Risposte:


210

Ti consiglierei di usare una singola stringa attribuibile mutabile suggerita da @Linuxios, ed ecco un altro esempio:

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

Tuttavia, solo per ottenere tutte le opzioni disponibili, puoi anche creare una singola stringa attribuibile mutabile, composta da una stringa NSS formattata contenente le stringhe di input già messe insieme. È quindi possibile utilizzare addAttributes: range:per aggiungere gli attributi dopo il fatto agli intervalli contenenti le stringhe di input. Raccomando il modo precedente però.


Perché consigli di aggiungere stringhe invece di aggiungere attributi?
ma11hew28,

87

Se stai usando Swift, puoi semplicemente sovraccaricare l' +operatore in modo da poterli concatenare nello stesso modo in cui concateni le stringhe normali:

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

Ora puoi concatenarli semplicemente aggiungendoli:

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

5
la classe mutabile è un sottotipo della classe immutabile.
Algal,

4
È possibile utilizzare il sottotipo mutabile in qualsiasi contesto che prevede il tipo di padre immutabile ma non viceversa. Potresti voler rivedere la sottoclasse e l'ereditarietà.
algal

6
Sì, dovresti fare una copia difensiva se vuoi essere difensivo. (Non sarcasmo.)
Algal

1
Se vuoi davvero restituire NSAttributedString, allora forse questo funzionerebbe:return NSAttributedString(attributedString: result)
Alex

2
@ n13 Vorrei creare una cartella denominata Helperso Extensionse inserire questa funzione in un file denominato NSAttributedString+Concatenate.swift.
David Lawson,

34

Swift 3: crea semplicemente un NSMutableAttributedString e aggiungi loro le stringhe attribuite.

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

Prova questo:

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

Dove astring1e astring2sono NSAttributedStrings.


13
Or [[aString1 mutableCopy] appendAttributedString: aString2].
JWWalker,

@JWWalker il tuo 'oneliner' è danneggiato. non è possibile ottenere questo risultato di "concatenazione" perché appendAttributedString non restituisce stringa. Stessa storia con dizionari
gaussblurinc

@gaussblurinc: buon punto, ovviamente le tue critiche si applicano anche alla risposta che stiamo commentando. Dovrebbe essere NSMutableAttributedString* aString3 = [aString1 mutableCopy]; [aString3 appendAttributedString: aString2];.
JWWalker,

@gaussblurinc, JWalker: corretta la risposta.
Linuxios,

@Linuxios, inoltre, ritorni resultcome NSMutableAttributedString. non è ciò che l'autore vuole vedere. stringByAppendingString- questo metodo sarà buono
gaussblurinc,

5

2020 | SWIFT 5.1:

Puoi aggiungere 2 NSMutableAttributedStringnel modo seguente:

let concatenated = NSAttrStr1.append(NSAttrStr2)

Un altro modo funziona con entrambi NSMutableAttributedStringe NSAttributedString:

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

Un altro modo è ....

var full = NSAttrStr1 + NSAttrStr2 + NSAttrStr3

e:

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


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

Puoi farlo con la seguente estensione:

// 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
Sto usando Swift 5.1 e non riesco proprio ad aggiungere due NSAttrStrings insieme ...
PaulDoesDev

1
Strano. In questo caso basta usareNSAttrStr1.append(NSAttrStr2)
Andrew il

Aggiornato la mia risposta con le estensioni per l'aggiunta di due NSAttrStrings :)
Andrew

4

Se stai usando Cocoapods, un'alternativa a entrambe le risposte sopra che ti consentono di evitare la mutabilità nel tuo codice è quella di utilizzare l'eccellente categoria NSAttributedString + CCLFormat su NSAttributedStrings che ti consente di scrivere qualcosa del tipo:

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

Ovviamente lo usa solo NSMutableAttributedStringsotto le coperte.

Ha anche il vantaggio di essere una funzione di formattazione completa, quindi può fare molto di più che aggiungere stringhe insieme.


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

Puoi provare SwiftyFormat che utilizza la seguente sintassi

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

1
Puoi per favore elaborarlo di più? Come funzionerà?
Kandhal Bhutiya,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.