Is there joinWithSeparator for attributed strings
Took this solution from SwifterSwift, it's similar to the other ones:
public extension Array where Element: NSAttributedString {
func joined(separator: NSAttributedString) -> NSAttributedString {
guard let firstElement = first else { return NSMutableAttributedString(string: "") }
return dropFirst().reduce(into: NSMutableAttributedString(attributedString: firstElement)) { result, element in
result.append(separator)
result.append(element)
}
}
func joined(separator: String) -> NSAttributedString {
guard let firstElement = first else { return NSMutableAttributedString(string: "") }
let attributedStringSeparator = NSAttributedString(string: separator)
return dropFirst().reduce(into: NSMutableAttributedString(attributedString: firstElement)) { result, element in
result.append(attributedStringSeparator)
result.append(element)
}
}
}
Updated answer for Swift 4, together with some basic documentation, using Sequence:
extension Sequence where Iterator.Element: NSAttributedString {
/// Returns a new attributed string by concatenating the elements of the sequence, adding the given separator between each element.
/// - parameters:
/// - separator: A string to insert between each of the elements in this sequence. The default separator is an empty string.
func joined(separator: NSAttributedString = NSAttributedString(string: "")) -> NSAttributedString {
var isFirst = true
return self.reduce(NSMutableAttributedString()) {
(r, e) in
if isFirst {
isFirst = false
} else {
r.append(separator)
}
r.append(e)
return r
}
}
/// Returns a new attributed string by concatenating the elements of the sequence, adding the given separator between each element.
/// - parameters:
/// - separator: A string to insert between each of the elements in this sequence. The default separator is an empty string.
func joined(separator: String = "") -> NSAttributedString {
return joined(separator: NSAttributedString(string: separator))
}
}
For Swift 3.0, Sequence type wasn't supported the I switch to Array. I also change the method name to use the swift 3.0 style
extension Array where Element: NSAttributedString {
func joined(separator: NSAttributedString) -> NSAttributedString {
var isFirst = true
return self.reduce(NSMutableAttributedString()) {
(r, e) in
if isFirst {
isFirst = false
} else {
r.append(separator)
}
r.append(e)
return r
}
}
func joined(separator: String) -> NSAttributedString {
return joined(separator: NSAttributedString(string: separator))
}
}
Swift 5:
import Foundation
extension Sequence where Iterator.Element == NSAttributedString {
func joined(with separator: NSAttributedString) -> NSAttributedString {
return self.reduce(NSMutableAttributedString()) {
(r, e) in
if r.length > 0 {
r.append(separator)
}
r.append(e)
return r
}
}
func joined(with separator: String = "") -> NSAttributedString {
return self.joined(with: NSAttributedString(string: separator))
}
}
Swift 4:
import Foundation
extension SequenceType where Generator.Element: NSAttributedString {
func joinWithSeparator(separator: NSAttributedString) -> NSAttributedString {
var isFirst = true
return self.reduce(NSMutableAttributedString()) {
(r, e) in
if isFirst {
isFirst = false
} else {
r.appendAttributedString(separator)
}
r.appendAttributedString(e)
return r
}
}
func joinWithSeparator(separator: String) -> NSAttributedString {
return joinWithSeparator(NSAttributedString(string: separator))
}
}