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.