@@ -12,8 +12,8 @@ import CoreFoundation
12
12
public class AttributedString : NSObject , NSCopying , NSMutableCopying , NSSecureCoding {
13
13
14
14
private let _cfinfo = _CFInfo ( typeID: CFAttributedStringGetTypeID ( ) )
15
- private let _string : NSString
16
- private let _attributeArray : CFRunArrayRef
15
+ private var _string : NSString
16
+ private var _attributeArray : CFRunArrayRef
17
17
18
18
public required init ? ( coder aDecoder: NSCoder ) {
19
19
NSUnimplemented ( )
@@ -48,57 +48,42 @@ public class AttributedString: NSObject, NSCopying, NSMutableCopying, NSSecureCo
48
48
}
49
49
50
50
public func attributesAtIndex( _ location: Int , effectiveRange range: NSRangePointer ) -> [ String : AnyObject ] {
51
- var cfRange = CFRange ( )
52
- return withUnsafeMutablePointer ( & cfRange) { ( rangePointer: UnsafeMutablePointer < CFRange > ) -> [ String : AnyObject ] in
53
- // Get attributes value using CoreFoundation function
54
- let value = CFAttributedStringGetAttributes ( _cfObject, location, rangePointer)
55
-
56
- // Convert the value to [String : AnyObject]
57
- let dictionary = unsafeBitCast ( value, to: NSDictionary . self)
58
- var results = [ String : AnyObject] ( )
59
- for (key, value) in dictionary {
60
- guard let stringKey = ( key as? NSString ) ? . _swiftObject else {
61
- continue
62
- }
63
- results [ stringKey] = value
64
- }
65
-
66
- // Update effective range
67
- let hasAttrs = results. count > 0
68
- range. pointee. location = hasAttrs ? rangePointer. pointee. location : NSNotFound
69
- range. pointee. length = hasAttrs ? rangePointer. pointee. length : 0
70
-
71
- return results
72
- }
51
+ let rangeInfo = RangeInfo (
52
+ rangePointer: range,
53
+ shouldFetchLongestEffectiveRange: false ,
54
+ longestEffectiveRangeSearchRange: nil )
55
+ return _attributesAtIndex ( location, rangeInfo: rangeInfo)
73
56
}
74
57
75
58
public var length : Int {
76
59
return CFAttributedStringGetLength ( _cfObject)
77
60
}
78
61
79
62
public func attribute( _ attrName: String , atIndex location: Int , effectiveRange range: NSRangePointer ) -> AnyObject ? {
80
- var cfRange = CFRange ( )
81
- return withUnsafeMutablePointer ( & cfRange) { ( rangePointer: UnsafeMutablePointer < CFRange > ) -> AnyObject ? in
82
- // Get attribute value using CoreFoundation function
83
- let attribute = CFAttributedStringGetAttribute ( _cfObject, location, attrName. _cfObject, rangePointer)
84
-
85
- // Update effective range and return the result
86
- if let attribute = attribute {
87
- range. pointee. location = rangePointer. pointee. location
88
- range. pointee. length = rangePointer. pointee. length
89
- return attribute
90
- } else {
91
- range. pointee. location = NSNotFound
92
- range. pointee. length = 0
93
- return nil
94
- }
95
- }
63
+ let rangeInfo = RangeInfo (
64
+ rangePointer: range,
65
+ shouldFetchLongestEffectiveRange: false ,
66
+ longestEffectiveRangeSearchRange: nil )
67
+ return _attribute ( attrName, atIndex: location, rangeInfo: rangeInfo)
96
68
}
97
69
98
70
public func attributedSubstringFromRange( _ range: NSRange ) -> AttributedString { NSUnimplemented ( ) }
99
71
100
- public func attributesAtIndex( _ location: Int , longestEffectiveRange range: NSRangePointer , inRange rangeLimit: NSRange ) -> [ String : AnyObject ] { NSUnimplemented ( ) }
101
- public func attribute( _ attrName: String , atIndex location: Int , longestEffectiveRange range: NSRangePointer , inRange rangeLimit: NSRange ) -> AnyObject ? { NSUnimplemented ( ) }
72
+ public func attributesAtIndex( _ location: Int , longestEffectiveRange range: NSRangePointer , inRange rangeLimit: NSRange ) -> [ String : AnyObject ] {
73
+ let rangeInfo = RangeInfo (
74
+ rangePointer: range,
75
+ shouldFetchLongestEffectiveRange: true ,
76
+ longestEffectiveRangeSearchRange: rangeLimit)
77
+ return _attributesAtIndex ( location, rangeInfo: rangeInfo)
78
+ }
79
+
80
+ public func attribute( _ attrName: String , atIndex location: Int , longestEffectiveRange range: NSRangePointer , inRange rangeLimit: NSRange ) -> AnyObject ? {
81
+ let rangeInfo = RangeInfo (
82
+ rangePointer: range,
83
+ shouldFetchLongestEffectiveRange: true ,
84
+ longestEffectiveRangeSearchRange: rangeLimit)
85
+ return _attribute ( attrName, atIndex: location, rangeInfo: rangeInfo)
86
+ }
102
87
103
88
public func isEqualToAttributedString( _ other: AttributedString ) -> Bool { NSUnimplemented ( ) }
104
89
@@ -119,6 +104,72 @@ public class AttributedString: NSObject, NSCopying, NSMutableCopying, NSSecureCo
119
104
}
120
105
121
106
public init ( attributedString attrStr: AttributedString ) { NSUnimplemented ( ) }
107
+
108
+ public func enumerateAttributesInRange( _ enumerationRange: NSRange , options opts: EnumerationOptions , usingBlock block: ( [ String : AnyObject ] , NSRange , UnsafeMutablePointer < ObjCBool > ) -> Void ) { NSUnimplemented ( ) }
109
+ public func enumerateAttribute( _ attrName: String , inRange enumerationRange: NSRange , options opts: EnumerationOptions , usingBlock block: ( AnyObject ? , NSRange , UnsafeMutablePointer < ObjCBool > ) -> Void ) { NSUnimplemented ( ) }
110
+
111
+ }
112
+
113
+ private extension AttributedString {
114
+ private struct RangeInfo {
115
+ let rangePointer : NSRangePointer
116
+ let shouldFetchLongestEffectiveRange : Bool
117
+ let longestEffectiveRangeSearchRange : NSRange ?
118
+ }
119
+
120
+ private func _attributesAtIndex( _ location: Int , rangeInfo: RangeInfo ) -> [ String : AnyObject ] {
121
+ var cfRange = CFRange ( )
122
+ return withUnsafeMutablePointer ( & cfRange) { ( cfRangePointer: UnsafeMutablePointer < CFRange > ) -> [ String : AnyObject ] in
123
+ // Get attributes value using CoreFoundation function
124
+ let value : CFDictionary
125
+ if rangeInfo. shouldFetchLongestEffectiveRange, let searchRange = rangeInfo. longestEffectiveRangeSearchRange {
126
+ value = CFAttributedStringGetAttributesAndLongestEffectiveRange ( _cfObject, location, CFRange ( searchRange) , cfRangePointer)
127
+ } else {
128
+ value = CFAttributedStringGetAttributes ( _cfObject, location, cfRangePointer)
129
+ }
130
+
131
+ // Convert the value to [String : AnyObject]
132
+ let dictionary = unsafeBitCast ( value, to: NSDictionary . self)
133
+ var results = [ String : AnyObject] ( )
134
+ for (key, value) in dictionary {
135
+ guard let stringKey = ( key as? NSString ) ? . _swiftObject else {
136
+ continue
137
+ }
138
+ results [ stringKey] = value
139
+ }
140
+
141
+ // Update effective range
142
+ let hasAttrs = results. count > 0
143
+ rangeInfo. rangePointer. pointee. location = hasAttrs ? cfRangePointer. pointee. location : NSNotFound
144
+ rangeInfo. rangePointer. pointee. length = hasAttrs ? cfRangePointer. pointee. length : 0
145
+
146
+ return results
147
+ }
148
+ }
149
+
150
+ private func _attribute( _ attrName: String , atIndex location: Int , rangeInfo: RangeInfo ) -> AnyObject ? {
151
+ var cfRange = CFRange ( )
152
+ return withUnsafeMutablePointer ( & cfRange) { ( cfRangePointer: UnsafeMutablePointer < CFRange > ) -> AnyObject ? in
153
+ // Get attribute value using CoreFoundation function
154
+ let attribute : AnyObject ?
155
+ if rangeInfo. shouldFetchLongestEffectiveRange, let searchRange = rangeInfo. longestEffectiveRangeSearchRange {
156
+ attribute = CFAttributedStringGetAttributeAndLongestEffectiveRange ( _cfObject, location, attrName. _cfObject, CFRange ( searchRange) , cfRangePointer)
157
+ } else {
158
+ attribute = CFAttributedStringGetAttribute ( _cfObject, location, attrName. _cfObject, cfRangePointer)
159
+ }
160
+
161
+ // Update effective range and return the result
162
+ if let attribute = attribute {
163
+ rangeInfo. rangePointer. pointee. location = cfRangePointer. pointee. location
164
+ rangeInfo. rangePointer. pointee. length = cfRangePointer. pointee. length
165
+ return attribute
166
+ } else {
167
+ rangeInfo. rangePointer. pointee. location = NSNotFound
168
+ rangeInfo. rangePointer. pointee. length = 0
169
+ return nil
170
+ }
171
+ }
172
+ }
122
173
123
174
private func addAttributesToAttributeArray( attrs: [ String : AnyObject ] ? ) {
124
175
guard _string. length > 0 else {
@@ -133,9 +184,6 @@ public class AttributedString: NSObject, NSCopying, NSMutableCopying, NSSecureCo
133
184
CFRunArrayInsert ( _attributeArray, range, emptyAttrs. _cfObject)
134
185
}
135
186
}
136
-
137
- public func enumerateAttributesInRange( _ enumerationRange: NSRange , options opts: EnumerationOptions , usingBlock block: ( [ String : AnyObject ] , NSRange , UnsafeMutablePointer < ObjCBool > ) -> Void ) { NSUnimplemented ( ) }
138
- public func enumerateAttribute( _ attrName: String , inRange enumerationRange: NSRange , options opts: EnumerationOptions , usingBlock block: ( AnyObject ? , NSRange , UnsafeMutablePointer < ObjCBool > ) -> Void ) { NSUnimplemented ( ) }
139
187
}
140
188
141
189
extension AttributedString : _CFBridgable {
@@ -160,12 +208,17 @@ public class NSMutableAttributedString : AttributedString {
160
208
161
209
public func replaceCharactersInRange( _ range: NSRange , withString str: String ) { NSUnimplemented ( ) }
162
210
public func setAttributes( _ attrs: [ String : AnyObject ] ? , range: NSRange ) { NSUnimplemented ( ) }
163
-
164
211
165
- public var mutableString : NSMutableString { NSUnimplemented ( ) }
212
+ public var mutableString : NSMutableString {
213
+ return _string as! NSMutableString
214
+ }
215
+
216
+ public func addAttribute( _ name: String , value: AnyObject , range: NSRange ) {
217
+ CFAttributedStringSetAttribute ( _cfMutableObject, CFRange ( range) , name. _cfObject, value)
218
+ }
166
219
167
- public func addAttribute( _ name: String , value: AnyObject , range: NSRange ) { NSUnimplemented ( ) }
168
220
public func addAttributes( _ attrs: [ String : AnyObject ] , range: NSRange ) { NSUnimplemented ( ) }
221
+
169
222
public func removeAttribute( _ name: String , range: NSRange ) { NSUnimplemented ( ) }
170
223
171
224
public func replaceCharactersInRange( _ range: NSRange , withAttributedString attrString: AttributedString ) { NSUnimplemented ( ) }
@@ -176,5 +229,18 @@ public class NSMutableAttributedString : AttributedString {
176
229
177
230
public func beginEditing( ) { NSUnimplemented ( ) }
178
231
public func endEditing( ) { NSUnimplemented ( ) }
232
+
233
+ public override init ( string str: String ) {
234
+ super. init ( string: str)
235
+ _string = NSMutableString ( string: str)
236
+ }
237
+
238
+ public required init ? ( coder aDecoder: NSCoder ) {
239
+ NSUnimplemented ( )
240
+ }
241
+
179
242
}
180
243
244
+ extension NSMutableAttributedString {
245
+ internal var _cfMutableObject : CFMutableAttributedString { return unsafeBitCast ( self , to: CFMutableAttributedString . self) }
246
+ }
0 commit comments