Merge pull request #171 from sgl0v/nsnotificationqueue

Initial implementation of the NSNotificationQueue
diff --git a/Foundation/NSArray.swift b/Foundation/NSArray.swift
index ed9ad55..d79b863 100644
--- a/Foundation/NSArray.swift
+++ b/Foundation/NSArray.swift
@@ -84,7 +84,15 @@
     }
     
     public func copyWithZone(zone: NSZone) -> AnyObject {
-        return self
+        if self.dynamicType === NSArray.self {
+            // return self for immutable type
+            return self
+        } else if self.dynamicType === NSMutableArray.self {
+            let array = NSArray()
+            array._storage = self._storage
+            return array
+        }
+        return NSArray(array: self.allObjects)
     }
     
     public override func mutableCopy() -> AnyObject {
@@ -92,7 +100,13 @@
     }
     
     public func mutableCopyWithZone(zone: NSZone) -> AnyObject {
-        return NSMutableArray(array: _swiftObject)
+        if self.dynamicType === NSArray.self || self.dynamicType === NSMutableArray.self {
+            // always create and return an NSMutableArray
+            let mutableArray = NSMutableArray()
+            mutableArray._storage = self._storage
+            return mutableArray
+        }
+        return NSMutableArray(array: self.allObjects)
     }
 
     public convenience init(object anObject: AnyObject) {
diff --git a/Foundation/NSDictionary.swift b/Foundation/NSDictionary.swift
index 9b90452..c9848f7 100644
--- a/Foundation/NSDictionary.swift
+++ b/Foundation/NSDictionary.swift
@@ -150,17 +150,31 @@
     public override func copy() -> AnyObject {
         return copyWithZone(nil)
     }
-    
+
     public func copyWithZone(zone: NSZone) -> AnyObject {
-        NSUnimplemented()
+        if self.dynamicType === NSDictionary.self {
+            // return self for immutable type
+            return self
+        } else if self.dynamicType === NSMutableDictionary.self {
+            let dictionary = NSDictionary()
+            dictionary._storage = self._storage
+            return dictionary
+        }
+        return NSDictionary(objects: self.allValues, forKeys: self.allKeys.map({ $0 as! NSObject}))
     }
-    
+
     public override func mutableCopy() -> AnyObject {
         return mutableCopyWithZone(nil)
     }
-    
+
     public func mutableCopyWithZone(zone: NSZone) -> AnyObject {
-        NSUnimplemented()
+        if self.dynamicType === NSDictionary.self || self.dynamicType === NSMutableDictionary.self {
+            // always create and return an NSMutableDictionary
+            let mutableDictionary = NSMutableDictionary()
+            mutableDictionary._storage = self._storage
+            return mutableDictionary
+        }
+        return NSMutableDictionary(objects: self.allValues, forKeys: self.allKeys.map({ $0 as! NSObject}))
     }
 
     public convenience init(object: AnyObject, forKey key: NSCopying) {
diff --git a/Foundation/NSSet.swift b/Foundation/NSSet.swift
index 0c4c172..d7b22ac 100644
--- a/Foundation/NSSet.swift
+++ b/Foundation/NSSet.swift
@@ -129,17 +129,31 @@
     }
     
     public func copyWithZone(zone: NSZone) -> AnyObject {
-        NSUnimplemented()
+        if self.dynamicType === NSSet.self {
+            // return self for immutable type
+            return self
+        } else if self.dynamicType === NSMutableSet.self {
+            let set = NSSet()
+            set._storage = self._storage
+            return set
+        }
+        return NSSet(array: self.allObjects)
     }
     
     public override func mutableCopy() -> AnyObject {
         return mutableCopyWithZone(nil)
     }
-    
+
     public func mutableCopyWithZone(zone: NSZone) -> AnyObject {
-        NSUnimplemented()
+        if self.dynamicType === NSSet.self || self.dynamicType === NSMutableSet.self {
+            // always create and return an NSMutableSet
+            let mutableSet = NSMutableSet()
+            mutableSet._storage = self._storage
+            return mutableSet
+        }
+        return NSMutableSet(array: self.allObjects)
     }
-    
+
     public static func supportsSecureCoding() -> Bool {
         return true
     }
diff --git a/TestFoundation/TestNSArray.swift b/TestFoundation/TestNSArray.swift
index 9216a0d..5d3b560 100644
--- a/TestFoundation/TestNSArray.swift
+++ b/TestFoundation/TestNSArray.swift
@@ -39,6 +39,8 @@
             ("test_sortUsingFunction", test_sortUsingFunction),
             ("test_sortUsingComparator", test_sortUsingComparator),
             ("test_equality", test_equality),
+            ("test_copying", test_copying),
+            ("test_mutableCopying", test_mutableCopying),
         ]
     }
     
@@ -369,4 +371,38 @@
         XCTAssertFalse(array1.isEqual(NSObject()))
     }
 
+    func test_copying() {
+        let array = ["this", "is", "a", "test", "of", "copy", "with", "strings"].bridge()
+
+        let arrayCopy1 = array.copy() as! NSArray
+        XCTAssertTrue(array === arrayCopy1)
+
+        let arrayMutableCopy = array.mutableCopy() as! NSMutableArray
+        let arrayCopy2 = arrayMutableCopy.copy() as! NSArray
+        XCTAssertTrue(arrayCopy2.dynamicType === NSArray.self)
+        XCTAssertFalse(arrayMutableCopy === arrayCopy2)
+        for entry in arrayCopy2 {
+            XCTAssertTrue(array.indexOfObjectIdenticalTo(entry) != NSNotFound)
+        }
+
+    }
+
+    func test_mutableCopying() {
+        let array = ["this", "is", "a", "test", "of", "mutableCopy", "with", "strings"].bridge()
+
+        let arrayMutableCopy1 = array.mutableCopy() as! NSMutableArray
+        XCTAssertTrue(arrayMutableCopy1.dynamicType === NSMutableArray.self)
+        XCTAssertFalse(array === arrayMutableCopy1)
+        for entry in arrayMutableCopy1 {
+            XCTAssertTrue(array.indexOfObjectIdenticalTo(entry) != NSNotFound)
+        }
+
+        let arrayMutableCopy2 = arrayMutableCopy1.mutableCopy() as! NSMutableArray
+        XCTAssertTrue(arrayMutableCopy2.dynamicType === NSMutableArray.self)
+        XCTAssertFalse(arrayMutableCopy2 === arrayMutableCopy1)
+        for entry in arrayMutableCopy2 {
+            XCTAssertTrue(arrayMutableCopy1.indexOfObjectIdenticalTo(entry) != NSNotFound)
+        }
+    }
+
 }
diff --git a/TestFoundation/TestNSDictionary.swift b/TestFoundation/TestNSDictionary.swift
index fd95b5e..23dfdf2 100644
--- a/TestFoundation/TestNSDictionary.swift
+++ b/TestFoundation/TestNSDictionary.swift
@@ -28,6 +28,8 @@
             ("test_description", test_description),
             ("test_enumeration", test_enumeration),
             ("test_equality", test_equality),
+            ("test_copying", test_copying),
+            ("test_mutableCopying", test_mutableCopying),
         ]
     }
         
@@ -125,4 +127,31 @@
         XCTAssertFalse(dict1.isEqual(NSObject()))
     }
 
-}
\ No newline at end of file
+    func test_copying() {
+        let inputDictionary : NSDictionary = ["foo" : "bar", "whiz" : "bang", "toil" : "trouble"].bridge()
+
+        let copy: NSDictionary = inputDictionary.copy() as! NSDictionary
+        XCTAssertTrue(inputDictionary === copy)
+
+        let dictMutableCopy = inputDictionary.mutableCopy() as! NSMutableDictionary
+        let dictCopy2 = dictMutableCopy.copy() as! NSDictionary
+        XCTAssertTrue(dictCopy2.dynamicType === NSDictionary.self)
+        XCTAssertFalse(dictMutableCopy === dictCopy2)
+        XCTAssertTrue(dictMutableCopy == dictCopy2)
+    }
+
+    func test_mutableCopying() {
+        let inputDictionary : NSDictionary = ["foo" : "bar", "whiz" : "bang", "toil" : "trouble"].bridge()
+
+        let dictMutableCopy1 = inputDictionary.mutableCopy() as! NSMutableDictionary
+        XCTAssertTrue(dictMutableCopy1.dynamicType === NSMutableDictionary.self)
+        XCTAssertFalse(inputDictionary === dictMutableCopy1)
+        XCTAssertTrue(inputDictionary == dictMutableCopy1)
+
+        let dictMutableCopy2 = dictMutableCopy1.mutableCopy() as! NSMutableDictionary
+        XCTAssertTrue(dictMutableCopy2.dynamicType === NSMutableDictionary.self)
+        XCTAssertFalse(dictMutableCopy2 === dictMutableCopy1)
+        XCTAssertTrue(dictMutableCopy2 == dictMutableCopy1)
+    }
+
+}
diff --git a/TestFoundation/TestNSSet.swift b/TestFoundation/TestNSSet.swift
index 4e98dbb..681dfbd 100644
--- a/TestFoundation/TestNSSet.swift
+++ b/TestFoundation/TestNSSet.swift
@@ -28,6 +28,8 @@
             ("test_sequenceType", test_sequenceType),
             ("test_setOperations", test_setOperations),
             ("test_equality", test_equality),
+            ("test_copying", test_copying),
+            ("test_mutableCopying", test_mutableCopying),
         ]
     }
     
@@ -89,4 +91,39 @@
         XCTAssertFalse(set1.isEqual(NSObject()))
     }
 
-}
\ No newline at end of file
+    func test_copying() {
+        let inputArray = ["this", "is", "a", "test", "of", "copy", "with", "strings"].bridge()
+        
+        let set = NSSet(array: inputArray.bridge())
+        let setCopy1 = set.copy() as! NSSet
+        XCTAssertTrue(set === setCopy1)
+
+        let setMutableCopy = set.mutableCopy() as! NSMutableSet
+        let setCopy2 = setMutableCopy.copy() as! NSSet
+        XCTAssertTrue(setCopy2.dynamicType === NSSet.self)
+        XCTAssertFalse(setMutableCopy === setCopy2)
+        for entry in setCopy2 {
+            XCTAssertTrue(setMutableCopy.allObjects.bridge().indexOfObjectIdenticalTo(entry) != NSNotFound)
+        }
+    }
+
+    func test_mutableCopying() {
+        let inputArray = ["this", "is", "a", "test", "of", "mutableCopy", "with", "strings"].bridge()
+        let set = NSSet(array: inputArray.bridge())
+
+        let setMutableCopy1 = set.mutableCopy() as! NSMutableSet
+        XCTAssertTrue(setMutableCopy1.dynamicType === NSMutableSet.self)
+        XCTAssertFalse(set === setMutableCopy1)
+        for entry in setMutableCopy1 {
+            XCTAssertTrue(set.allObjects.bridge().indexOfObjectIdenticalTo(entry) != NSNotFound)
+        }
+
+        let setMutableCopy2 = setMutableCopy1.mutableCopy() as! NSMutableSet
+        XCTAssertTrue(setMutableCopy2.dynamicType === NSMutableSet.self)
+        XCTAssertFalse(setMutableCopy2 === setMutableCopy1)
+        for entry in setMutableCopy2 {
+            XCTAssertTrue(setMutableCopy1.allObjects.bridge().indexOfObjectIdenticalTo(entry) != NSNotFound)
+        }
+    }
+
+}