Como concatenar NSAttributedStrings?

159

Eu preciso pesquisar algumas strings e definir alguns atributos antes de mesclar as strings, portanto, ter NSStrings -> Concatenate them -> Make NSAttributedString não é uma opção. Existe alguma maneira de concatenar attributeString para outro attributeString?

Imanou Petit
fonte
13
É ridículo quão difícil isso ainda é em agosto de 2016.
Wedge Martin
17
Mesmo em 2018 ...
DehMotth
11
ainda em 2019;)
raistlin
8
ainda em 2020 ...
Hwangho Kim 17/03

Respostas:

210

Eu recomendo que você use uma única string atribuível mutável sugerida pelo @Linuxios, e aqui está outro exemplo disso:

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

No entanto, apenas para obter todas as opções disponíveis, você também pode criar uma única sequência mutável atribuída, feita a partir de uma NSString formatada contendo as seqüências de entrada já reunidas. Você pode usar addAttributes: range:para adicionar os atributos após o fato aos intervalos que contêm as cadeias de entrada. Eu recomendo o caminho antigo embora.

Mick MacCallum
fonte
Por que você recomenda anexar cadeias em vez de adicionar atributos?
precisa saber é o seguinte
87

Se você estiver usando o Swift, poderá sobrecarregar o +operador para concatená-los da mesma maneira que concatenar seqüências normais:

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

Agora você pode concatená-los apenas adicionando-os:

let helloworld = NSAttributedString(string: "Hello ") + NSAttributedString(string: "World")
algal
fonte
5
a classe mutável é um subtipo da classe imutável.
perfil completo de algal
4
Você pode usar o subtipo mutável em qualquer contexto que espere o tipo pai imutável, mas não vice-versa. Você pode revisar subclassificação e herança.
algal
6
Sim, você deve fazer uma cópia defensiva se quiser ficar na defensiva. (Não é sarcasmo.)
algal
1
Se você realmente quer voltar NSAttributedString, então talvez isso iria funcionar:return NSAttributedString(attributedString: result)
Alex
2
@ n13 Eu criaria uma pasta chamada Helpersor Extensionse colocaria essa função em um arquivo chamado NSAttributedString+Concatenate.swift.
David Lawson
34

Swift 3: basta criar um NSMutableAttributedString e acrescentar as strings atribuídas a eles.

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

atualização swift5:

    let captionAttribute = [
        NSAttributedString.Key.font: Font.captionsRegular,
        NSAttributedString.Key.foregroundColor: UIColor.appGray
    ]
Josh O'Connor
fonte
25

Tente o seguinte:

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

Onde astring1e astring2estão NSAttributedStrings.

Linuxios
fonte
13
Or [[aString1 mutableCopy] appendAttributedString: aString2].
JWWalker
@JWWalker o seu 'oneliner' está corrompido. você não pode obter esse resultado de "concatenação" porque appendAttributedString não retorna string. Mesma história com dicionários
gaussblurinc 12/11/2015
@gaussblurinc: bom ponto, é claro que suas críticas também se aplicam à resposta que estamos comentando. Deveria ser NSMutableAttributedString* aString3 = [aString1 mutableCopy]; [aString3 appendAttributedString: aString2];.
JWWalker
@gaussblurinc, JWalker: Corrigida a resposta.
Linuxios
@ Linuxios, também, você retorna resultcomo NSMutableAttributedString. não é o que o autor deseja ver. stringByAppendingString- este método vai ser bom
gaussblurinc
5

2020 SWIFT 5.1:

Você pode adicionar 2 NSMutableAttributedStringda seguinte maneira:

let concatenated = NSAttrStr1.append(NSAttrStr2)

Outra maneira funciona com NSMutableAttributedStringe com NSAttributedStringambos:

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

Outra maneira é ....

var full = NSAttrStr1 + NSAttrStr2 + NSAttrStr3

e:

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


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

Você pode fazer isso com a seguinte extensão:

// 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
fonte
2
Estou usando o Swift 5.1 e não consigo adicionar apenas duas NSAttrStrings ...
PaulDoesDev 25/02
1
Estranho. Neste caso, basta usarNSAttrStr1.append(NSAttrStr2)
Andrew
Atualizei minha resposta com extensões para adicionar apenas duas NSAttrStrings :)
Andrew
4

Se você estiver usando Cocoapods, uma alternativa para as duas respostas acima que permitem evitar a mutabilidade em seu próprio código é usar a excelente categoria NSAttributedString + CCLFormat em NSAttributedStrings, que permite escrever algo como:

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

É claro que ele apenas usa NSMutableAttributedStringdebaixo das cobertas.

Ele também tem a vantagem extra de ser uma função de formatação completa - para que ele possa fazer muito mais do que anexar seqüências de caracteres.

fatuhoku
fonte
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
fonte
1

Você pode tentar SwiftyFormat Ele usa a seguinte sintaxe

let format = "#{{user}} mentioned you in a comment. #{{comment}}"
let message = NSAttributedString(format: format,
                                 attributes: commonAttributes,
                                 mapping: ["user": attributedName, "comment": attributedComment])
Igor Palaguta
fonte
1
Você pode elaborar mais? Como funciona a vontade?
Kandhal Bhutiya