user2559108
user2559108

Reputation:

How can I concatenate NSAttributedStrings?

I need to search some strings and set some attributes prior to merging the strings, so having NSStrings -> Concatenate them -> Make NSAttributedString is not an option, is there any way to concatenate attributedString to another attributedString?

Upvotes: 192

Views: 117422

Answers (9)

Mateus
Mateus

Reputation: 407

private var fillAttributes:[NSMutableAttributedString.Key : Any]? = nil

fontAttributes = [.foregroundColor : SKColor.red,
                  .strokeWidth : 0.0,
                  .font : CPFont(name: "Verdana-Bold",
                  .size : 50,]

fontAttributes.updateValue(SKColor.green, forKey: .foregroundColor)

Upvotes: 0

Andrew_STOP_RU_WAR_IN_UA
Andrew_STOP_RU_WAR_IN_UA

Reputation: 11416

2020 | SWIFT 5.1:

You're able to add 2 NSMutableAttributedString by the following way:

let concatenated = NSAttrStr1.append(NSAttrStr2)

Another way works with NSMutableAttributedString and NSAttributedString both:

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

Another way is....

var full = NSAttrStr1 + NSAttrStr2 + NSAttrStr3

and:

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


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

You can do this with the following extension:

// 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
    }
}

Upvotes: 16

Josh O'Connor
Josh O'Connor

Reputation: 4962

Swift 3: Simply create a NSMutableAttributedString and append the attributed strings to them.

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
    ]

Upvotes: 43

Igor Palaguta
Igor Palaguta

Reputation: 3579

You can try SwiftyFormat It uses following syntax

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

Upvotes: 1

algal
algal

Reputation: 28094

If you're using Swift, you can just overload the + operator so that you can concatenate them in the same way you concatenate normal strings:

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

Now you can concatenate them just by adding them:

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

Upvotes: 110

gaussblurinc
gaussblurinc

Reputation: 3682

// 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;
}

Upvotes: 1

Linuxios
Linuxios

Reputation: 35783

Try this:

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

Where astring1 and astring2 are NSAttributedStrings.

Upvotes: 28

Mick MacCallum
Mick MacCallum

Reputation: 130183

I'd recommend you use a single mutable attributed string a @Linuxios suggested, and here's another example of that:

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

However, just for the sake of getting all the options out there, you could also create a single mutable attributed string, made from a formatted NSString containing the input strings already put together. You could then use addAttributes: range: to add the attributes after the fact to the ranges containing the input strings. I recommend the former way though.

Upvotes: 224

fatuhoku
fatuhoku

Reputation: 4911

If you're using Cocoapods, an alternative to both above answers that let you avoid mutability in your own code is to use the excellent NSAttributedString+CCLFormat category on NSAttributedStrings that lets you write something like:

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

It of course it just uses NSMutableAttributedString under the covers.

It also has the extra advantage of being a fully fledged formatting function — so it can do a lot more than appending strings together.

Upvotes: 4

Related Questions