Skip to content

Commit f95f908

Browse files
author
Sergey Minakov
committed
[NSPredicate] NSCoding, NSCopying, .predicateFormat implementation and tests
1 parent 1db5065 commit f95f908

File tree

2 files changed

+68
-4
lines changed

2 files changed

+68
-4
lines changed

Foundation/NSPredicate.swift

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,60 @@ open class NSPredicate : NSObject, NSSecureCoding, NSCopying {
2626
}
2727

2828
public required init?(coder aDecoder: NSCoder) {
29-
NSUnimplemented()
29+
guard aDecoder.allowsKeyedCoding else {
30+
preconditionFailure("Unkeyed coding is unsupported.")
31+
}
32+
33+
let encodedBool = aDecoder.decodeBool(forKey: "NS.boolean.value")
34+
self.kind = .boolean(encodedBool)
35+
36+
super.init()
3037
}
3138

3239
open func encode(with aCoder: NSCoder) {
33-
NSUnimplemented()
40+
guard aCoder.allowsKeyedCoding else {
41+
preconditionFailure("Unkeyed coding is unsupported.")
42+
}
43+
44+
switch self.kind {
45+
case .boolean(let value):
46+
aCoder.encode(value, forKey: "NS.boolean.value")
47+
case .block:
48+
preconditionFailure("NSBlockPredicate cannot be encoded or decoded.")
49+
}
3450
}
3551

3652
open override func copy() -> Any {
3753
return copy(with: nil)
3854
}
3955

4056
open func copy(with zone: NSZone? = nil) -> Any {
41-
NSUnimplemented()
57+
switch self.kind {
58+
case .boolean(let value):
59+
return NSPredicate(value: value)
60+
case .block(let block):
61+
return NSPredicate(block: block)
62+
}
63+
}
64+
65+
open override func isEqual(_ object: Any?) -> Bool {
66+
if let other = object as? NSPredicate {
67+
if other === self {
68+
return true
69+
} else {
70+
switch (other.kind, self.kind) {
71+
case (.boolean(let otherBool), .boolean(let selfBool)):
72+
return otherBool == selfBool
73+
// TODO: case for init(format:argumentArray:)
74+
// TODO: case for init(fromMetadataQueryString:)
75+
// NSBlockPredicate returns false even for copy
76+
default:
77+
return false
78+
}
79+
}
80+
}
81+
82+
return false
4283
}
4384

4485
// Parse predicateFormat and return an appropriate predicate
@@ -58,7 +99,17 @@ open class NSPredicate : NSObject, NSSecureCoding, NSCopying {
5899
super.init()
59100
}
60101

61-
open var predicateFormat: String { NSUnimplemented() } // returns the format string of the predicate
102+
open var predicateFormat: String {
103+
switch self.kind {
104+
case .boolean(let value):
105+
return value ? "TRUEPREDICATE" : "FALSEPREDICATE"
106+
case .block:
107+
// TODO: Bring NSBlockPredicate's predicateFormat to macOS's Foundation version
108+
// let address = unsafeBitCast(block, to: Int.self)
109+
// return String(format:"BLOCKPREDICATE(%2X)", address)
110+
return "BLOCKPREDICATE"
111+
}
112+
}
62113

63114
open func withSubstitutionVariables(_ variables: [String : Any]) -> Self { NSUnimplemented() } // substitute constant values for variables
64115

TestFoundation/TestNSPredicate.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class TestNSPredicate: XCTestCase {
2727
("test_filterNSMutableSet", test_filterNSMutableSet),
2828
("test_filterNSOrderedSet", test_filterNSOrderedSet),
2929
("test_filterNSMutableOrderedSet", test_filterNSMutableOrderedSet),
30+
("test_NSCoding", test_NSCoding),
31+
("test_copy", test_copy),
3032
]
3133
}
3234

@@ -94,4 +96,15 @@ class TestNSPredicate: XCTestCase {
9496
expectedOrderedSet.addObjects(from: expectedArray)
9597
XCTAssertEqual(expectedOrderedSet, orderedSet)
9698
}
99+
100+
func test_NSCoding() {
101+
let predicateA = NSPredicate(value: true)
102+
let predicateB = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: predicateA)) as! NSPredicate
103+
XCTAssertEqual(predicateA, predicateB, "Archived then unarchived uuid must be equal.")
104+
}
105+
106+
func test_copy() {
107+
let predicate = NSPredicate(value: true)
108+
XCTAssert(predicate.isEqual(predicate.copy()))
109+
}
97110
}

0 commit comments

Comments
 (0)