Jak mogę połączyć NSAttributedStrings?


158

Muszę przeszukać niektóre ciągi i ustawić niektóre atrybuty przed scaleniem ciągów, więc posiadanie NSStrings -> Concatenate je -> Make NSAttributedString nie jest opcją, czy istnieje sposób, aby połączyć atrybuty atrybutu z innym ciągiem atrybutu?


13
To śmieszne, jak trudne jest to nadal w sierpniu 2016 r.
— Wedge Martin,

17
Nawet w 2018 roku ...
— DehMotth

11
jeszcze w 2019;)
— raistlin 28.02.19

8
jeszcze w 2020 ...
— Hwangho Kim

Odpowiedzi:


210

Zalecałbym użycie pojedynczego przypisywanego ciągu znaków, który zasugerował @Linuxios, a oto kolejny przykład:

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

Jednak tylko po to, aby uzyskać wszystkie dostępne opcje, możesz również utworzyć pojedynczy zmienny przypisany ciąg, utworzony ze sformatowanego ciągu NSString zawierającego ciągi wejściowe już zebrane. Następnie możesz użyć, addAttributes: range:aby dodać atrybuty po fakcie do zakresów zawierających ciągi wejściowe. Polecam jednak ten pierwszy sposób.


Dlaczego zalecamy dołączanie ciągów znaków zamiast dodawania atrybutów?
— ma11hew28

86

Jeśli używasz języka Swift, możesz po prostu przeciążać +operator, aby można było je łączyć w ten sam sposób, w jaki łączysz zwykłe ciągi:

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

Teraz możesz je połączyć, po prostu dodając je:

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

5
klasa zmienna jest podtypem klasy niezmiennej.
— glonów

4
Zmiennego podtypu można używać w dowolnym kontekście, który oczekuje niezmiennego typu nadrzędnego, ale nie odwrotnie. Możesz chcieć przejrzeć podklasy i dziedziczenie.
— glony

6
Tak, powinieneś zrobić kopię obronną, jeśli chcesz się bronić. (Nie sarkazm.)
— algal

1
Jeśli naprawdę chcesz zwrócić NSAttributedString, być może to zadziała:return NSAttributedString(attributedString: result)
— Alex

2
@ n13 Utworzyłbym folder o nazwie Helperslub Extensionsi umieściłbym tę funkcję w pliku o nazwie NSAttributedString+Concatenate.swift.
— David Lawson

34

Swift 3: Po prostu utwórz NSMutableAttributedString i dołącz do nich przypisane ciągi.

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

Spróbuj tego:

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

Gdzie astring1i astring2są NSAttributedStrings.


13
Lub [[aString1 mutableCopy] appendAttributedString: aString2].
— JWWalker

@JWWalker Twój „oneliner” jest uszkodzony. nie można uzyskać tego wyniku „konkatenacji”, ponieważ funkcja appendAttributedString nie zwraca ciągu. Ta sama historia ze słownikami
— gaussblurinc

@gaussblurinc: słuszna uwaga, oczywiście twoja krytyka dotyczy również odpowiedzi, którą komentujemy. Tak powinno być NSMutableAttributedString* aString3 = [aString1 mutableCopy]; [aString3 appendAttributedString: aString2];.
— JWWalker

@gaussblurinc, JWalker: Poprawiono odpowiedź.
— Linuxios

@Linuxios, również wrócisz resultjako NSMutableAttributedString. nie jest tym, co autor chce zobaczyć. stringByAppendingString- ta metoda będzie dobra
— gaussblurinc

5

2020 | SWIFT 5.1:

Możesz dodać 2 NSMutableAttributedStringw następujący sposób:

let concatenated = NSAttrStr1.append(NSAttrStr2)

Inny sposób działa z obydwoma NSMutableAttributedStringi NSAttributedString:

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

Innym sposobem jest ...

var full = NSAttrStr1 + NSAttrStr2 + NSAttrStr3

i:

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


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

Możesz to zrobić za pomocą następującego rozszerzenia:

// 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
Używam Swift 5.1 i nie mogę po prostu dodać dwóch NSAttrStrings razem ...
— PaulDoesDev

1
Dziwne. W tym przypadku po prostu użyjNSAttrStr1.append(NSAttrStr2)
— Andrew

Zaktualizowałem moją odpowiedź o rozszerzenia, aby dodać tylko dwa NSAttrStrings :)
— Andrew,

4

Jeśli używasz Cocoapods, alternatywą dla obu powyższych odpowiedzi, które pozwalają uniknąć zmienności we własnym kodzie, jest użycie doskonałej kategorii NSAttributedString + CCLFormat na NSAttributedStrings, która pozwala napisać coś takiego:

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

Oczywiście używa się go tylko NSMutableAttributedStringpod kołdrą.

Ma również tę dodatkową zaletę, że jest pełnoprawną funkcją formatowania - może więc zrobić o wiele więcej niż dołączanie ciągów do siebie.


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

Możesz spróbować SwiftyFormat Używa następującej składni

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

1
Czy możesz go bardziej rozwinąć? Jak to działa?
— Kandhal Bhutiya
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.