extension NSMutableAttributedString {
private func check(_ range: inout NSRange) {
if range.location + range.length > string.count {
range = NSRange(location: range.location, length: string.count - range.location)
}
}
private var allRange : NSRange {
return NSRange(location: 0, length: string.count)
}
}
extension NSMutableAttributedString {
subscript<T>(_ key: NSAttributedString.Key) -> T? {
get {
var range = allRange
return attribute(key, at: 0, effectiveRange: &range) as? T
}
set {
if let value = newValue {
let range = allRange
addAttribute(key, value: value, range: range)
}
}
}
}
extension NSMutableAttributedString {
subscript<T>(_ key: NSAttributedString.Key, r: Range<Int>) -> T? {
get {
var range = NSRange(location: r.lowerBound, length: r.upperBound - r.lowerBound)
check(&range)
return attribute(key, at: 0, effectiveRange: &range) as? T
}
set {
if let value = newValue {
var range = NSRange(location: r.lowerBound, length: r.upperBound - r.lowerBound)
check(&range)
addAttribute(key, value: value, range: range)
}
}
}
subscript<T>(_ key: NSAttributedString.Key, r: Range<String.Index>) -> T? {
get {
let lowerBound = r.lowerBound.encodedOffset
let upperBound = r.upperBound.encodedOffset
var range = NSRange(location: lowerBound, length: upperBound - lowerBound)
check(&range)
return attribute(key, at: 0, effectiveRange: &range) as? T
}
set {
if let value = newValue {
let lowerBound = r.lowerBound.encodedOffset
let upperBound = r.upperBound.encodedOffset
var range = NSRange(location: lowerBound, length: upperBound - lowerBound)
check(&range)
addAttribute(key, value: value, range: range)
}
}
}
subscript<T>(_ r: Range<Int>) -> [NSAttributedString.Key: T]? {
get {
var range = NSRange(location: r.lowerBound, length: r.upperBound - r.lowerBound)
check(&range)
var dict : [NSAttributedString.Key: T] = [:]
enumerateAttributes(in: range, options: .longestEffectiveRangeNotRequired) { (atts, range, pointer) in
dict = atts as! [NSAttributedString.Key : T]
}
return dict
}
set {
if let value = newValue {
var range = NSRange(location: r.lowerBound, length: r.upperBound - r.lowerBound)
check(&range)
value.forEach {
addAttribute($0, value: $1, range: range)
}
}
}
}
}
extension NSMutableAttributedString {
subscript<T>(_ key: NSAttributedString.Key, r: ClosedRange<Int>) -> T? {
get {
var range = NSRange(location: r.lowerBound, length: r.upperBound - r.lowerBound + 1)
check(&range)
return attribute(key, at: 0, effectiveRange: &range) as? T
}
set {
if let value = newValue {
var range = NSRange(location: r.lowerBound, length: r.upperBound - r.lowerBound + 1)
check(&range)
addAttribute(key, value: value, range: range)
}
}
}
subscript<T>(_ r: ClosedRange<Int>) -> [NSAttributedString.Key: T]? {
get {
var range = NSRange(location: r.lowerBound, length: r.upperBound - r.lowerBound + 1)
check(&range)
var dict : [NSAttributedString.Key: T] = [:]
enumerateAttributes(in: range, options: .longestEffectiveRangeNotRequired) { (atts, range, pointer) in
dict = atts as! [NSAttributedString.Key : T]
}
return dict
}
set {
if let value = newValue {
var range = NSRange(location: r.lowerBound, length: r.upperBound - r.lowerBound + 1)
check(&range)
value.forEach {
addAttribute($0, value: $1, range: range)
}
}
}
}
}
extension NSMutableAttributedString {
subscript<T>(_ key: NSAttributedString.Key, r: PartialRangeFrom<Int>) -> T? {
get {
var range = NSRange(location: r.lowerBound, length: string.count - r.lowerBound)
check(&range)
return attribute(key, at: 0, effectiveRange: &range) as? T
}
set {
if let value = newValue {
var range = NSRange(location: r.lowerBound, length: string.count - r.lowerBound)
check(&range)
addAttribute(key, value: value, range: range)
}
}
}
subscript<T>(_ r: PartialRangeFrom<Int>) -> [NSAttributedString.Key: T]? {
get {
var range = NSRange(location: r.lowerBound, length: string.count - r.lowerBound)
check(&range)
var dict : [NSAttributedString.Key: T] = [:]
enumerateAttributes(in: range, options: .longestEffectiveRangeNotRequired) { (atts, range, pointer) in
dict = atts as! [NSAttributedString.Key : T]
}
return dict
}
set {
if let value = newValue {
var range = NSRange(location: r.lowerBound, length: string.count - r.lowerBound)
check(&range)
value.forEach {
addAttribute($0, value: $1, range: range)
}
}
}
}
}