Skip to content

Commit 7f3fca5

Browse files
committed
update NSDictionary coder init method to be more in pairty with the logic on darwin
This handles non keyed coding and fast paths reserved for NSKeyedUnarchiver as well as updating failWithError cases for early coder termination on corrupt archives
1 parent 75895f9 commit 7f3fca5

File tree

1 file changed

+33
-9
lines changed

1 file changed

+33
-9
lines changed

Foundation/NSDictionary.swift

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -136,17 +136,41 @@ public class NSDictionary : NSObject, NSCopying, NSMutableCopying, NSSecureCodin
136136
}
137137

138138
public required convenience init?(coder aDecoder: NSCoder) {
139-
if let keyedUnarchiver = aDecoder as? NSKeyedUnarchiver {
140-
let keys = keyedUnarchiver._decodeArrayOfObjects("NS.keys") as? [NSObject]
141-
let objects = keyedUnarchiver._decodeArrayOfObjects("NS.objects")
142-
143-
if keys != nil && objects != nil && keys!.count == objects!.count {
144-
self.init(objects: objects!, forKeys: keys!)
145-
} else {
146-
self.init()
139+
if !aDecoder.allowsKeyedCoding {
140+
var cnt: UInt32 = 0
141+
// We're stuck with (int) here (rather than unsigned int)
142+
// because that's the way the code was originally written, unless
143+
// we go to a new version of the class, which has its own problems.
144+
withUnsafeMutablePointer(&cnt) { (ptr: UnsafeMutablePointer<UInt32>) -> Void in
145+
aDecoder.decodeValueOfObjCType("i", at: UnsafeMutablePointer<Void>(ptr))
146+
}
147+
let keys = UnsafeMutablePointer<NSObject>.alloc(Int(cnt))
148+
let objects = UnsafeMutablePointer<AnyObject>.alloc(Int(cnt))
149+
for idx in 0..<cnt {
150+
keys.advancedBy(Int(idx)).initialize(aDecoder.decodeObject()! as! NSObject)
151+
objects.advancedBy(Int(idx)).initialize(aDecoder.decodeObject()!)
147152
}
153+
self.init(objects: UnsafePointer<AnyObject>(objects), forKeys: UnsafePointer<NSObject>(keys), count: Int(cnt))
154+
keys.destroy(Int(cnt))
155+
keys.dealloc(Int(cnt))
156+
objects.destroy(Int(cnt))
157+
objects.dealloc(Int(cnt))
158+
159+
} else if aDecoder.dynamicType == NSKeyedUnarchiver.self || aDecoder.containsValueForKey("NS.objects") {
160+
let keys = aDecoder._decodeArrayOfObjectsForKey("NS.keys").map() { return $0 as! NSObject }
161+
let objects = aDecoder._decodeArrayOfObjectsForKey("NS.objects")
162+
self.init(objects: objects, forKeys: keys)
148163
} else {
149-
NSUnimplemented()
164+
var objects = [AnyObject]()
165+
var keys = [NSObject]()
166+
var count = 0
167+
while let key = aDecoder.decodeObjectForKey("NS.key.\(count)"),
168+
let object = aDecoder.decodeObjectForKey("NS.object.\(count)") {
169+
keys.append(key as! NSObject)
170+
objects.append(object)
171+
count++
172+
}
173+
self.init(objects: objects, forKeys: keys)
150174
}
151175
}
152176

0 commit comments

Comments
 (0)