Merge pull request #815 from naithar/NSAffineTransform
diff --git a/Docs/Status.md b/Docs/Status.md
index d038e90..071a49c 100644
--- a/Docs/Status.md
+++ b/Docs/Status.md
@@ -226,7 +226,7 @@
| `NSGeometry` | Mostly Complete | Substantial | `NSIntegralRectWithOptions` `.AlignRectFlipped` support remains unimplemented |
| `CGFloat` | Complete | Substantial | |
| `AffineTransform` | Complete | None | |
- | `NSAffineTransform` | Mostly Complete | Substnatial | `NSCoding` remains unimplemented |
+ | `NSAffineTransform` | Complete | Substnatial | |
| `NSNumber` | Complete | Incomplete | |
| `NSConcreteValue` | N/A | N/A | For internal use only |
| `NSSpecialValue` | N/A | N/A | For internal use only |
diff --git a/Foundation/NSAffineTransform.swift b/Foundation/NSAffineTransform.swift
index 873e3b4..58b12c4 100644
--- a/Foundation/NSAffineTransform.swift
+++ b/Foundation/NSAffineTransform.swift
@@ -282,18 +282,66 @@
open class NSAffineTransform : NSObject, NSCopying, NSSecureCoding {
open func encode(with aCoder: NSCoder) {
- NSUnimplemented()
+ guard aCoder.allowsKeyedCoding else {
+ preconditionFailure("Unkeyed coding is unsupported.")
+ }
+
+ let array = [
+ Float(transformStruct.m11),
+ Float(transformStruct.m12),
+ Float(transformStruct.m21),
+ Float(transformStruct.m22),
+ Float(transformStruct.tX),
+ Float(transformStruct.tY),
+ ]
+
+ array.withUnsafeBytes { pointer in
+ aCoder.encodeValue(ofObjCType: "[6f]", at: UnsafeRawPointer(pointer.baseAddress!))
+ }
}
+
open func copy(with zone: NSZone? = nil) -> Any {
return NSAffineTransform(transform: self)
}
+
// Necessary because `NSObject.copy()` returns `self`.
open override func copy() -> Any {
return copy(with: nil)
}
+
public required init?(coder aDecoder: NSCoder) {
- NSUnimplemented()
+ guard aDecoder.allowsKeyedCoding else {
+ preconditionFailure("Unkeyed coding is unsupported.")
+ }
+
+ let pointer = UnsafeMutableRawPointer.allocate(bytes: MemoryLayout<Float>.stride * 6, alignedTo: 1)
+ defer {
+ pointer.deallocate(bytes: MemoryLayout<Float>.stride * 6, alignedTo: 1)
+ }
+ aDecoder.decodeValue(ofObjCType: "[6f]", at: pointer)
+
+ let floatPointer = pointer.bindMemory(to: Float.self, capacity: 6)
+ let m11 = floatPointer[0]
+ let m12 = floatPointer[1]
+ let m21 = floatPointer[2]
+ let m22 = floatPointer[3]
+ let tX = floatPointer[4]
+ let tY = floatPointer[5]
+
+ self.transformStruct = AffineTransform(m11: CGFloat(m11), m12: CGFloat(m12),
+ m21: CGFloat(m21), m22: CGFloat(m22),
+ tX: CGFloat(tX), tY: CGFloat(tY))
}
+
+ open override func isEqual(_ object: Any?) -> Bool {
+ if let other = object as? NSAffineTransform {
+ return other === self
+ || (other.transformStruct == self.transformStruct)
+ }
+
+ return false
+ }
+
public static var supportsSecureCoding: Bool {
return true
}
diff --git a/TestFoundation/TestNSAffineTransform.swift b/TestFoundation/TestNSAffineTransform.swift
index 914fbd7..cdbffe2 100644
--- a/TestFoundation/TestNSAffineTransform.swift
+++ b/TestFoundation/TestNSAffineTransform.swift
@@ -38,6 +38,8 @@
("test_AppendTransform", test_AppendTransform),
("test_PrependTransform", test_PrependTransform),
("test_TransformComposition", test_TransformComposition),
+ ("test_Equal", test_Equal),
+ ("test_NSCoding", test_NSCoding),
]
}
@@ -343,6 +345,21 @@
XCTAssertEqual(ref.hashValue, val.hashValue)
}
}
+
+ func test_Equal() {
+ let transform = NSAffineTransform()
+ let transform1 = NSAffineTransform()
+
+ XCTAssertEqual(transform1, transform)
+ XCTAssertFalse(transform === transform1)
+ }
+
+ func test_NSCoding() {
+ let transformA = NSAffineTransform()
+ transformA.scale(by: 2)
+ let transformB = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: transformA)) as! NSAffineTransform
+ XCTAssertEqual(transformA, transformB, "Archived then unarchived `NSAffineTransform` must be equal.")
+ }
}
extension NSAffineTransform {