@@ -15,8 +15,8 @@ open class NSPredicate : NSObject, NSSecureCoding, NSCopying {
15
15
private enum PredicateKind {
16
16
case boolean( Bool )
17
17
case block( ( Any ? , [ String : Any ] ? ) -> Bool )
18
- // TODO: case for init( format:argumentArray: )
19
- // TODO: case for init(fromMetadataQueryString: )
18
+ case format( String )
19
+ case metadataQuery ( String )
20
20
}
21
21
22
22
private let kind : PredicateKind
@@ -26,19 +26,72 @@ open class NSPredicate : NSObject, NSSecureCoding, NSCopying {
26
26
}
27
27
28
28
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 ( )
30
37
}
31
38
32
39
open func encode( with aCoder: NSCoder ) {
33
- NSUnimplemented ( )
40
+ guard aCoder. allowsKeyedCoding else {
41
+ preconditionFailure ( " Unkeyed coding is unsupported. " )
42
+ }
43
+
44
+ //TODO: store kind key for .boolean, .format, .metadataQuery
45
+
46
+ switch self . kind {
47
+ case . boolean( let value) :
48
+ aCoder. encode ( value, forKey: " NS.boolean.value " )
49
+ case . block:
50
+ preconditionFailure ( " NSBlockPredicate cannot be encoded or decoded. " )
51
+ case . format:
52
+ NSUnimplemented ( )
53
+ case . metadataQuery:
54
+ NSUnimplemented ( )
55
+ }
34
56
}
35
57
36
58
open override func copy( ) -> Any {
37
59
return copy ( with: nil )
38
60
}
39
61
40
62
open func copy( with zone: NSZone ? = nil ) -> Any {
41
- NSUnimplemented ( )
63
+ switch self . kind {
64
+ case . boolean( let value) :
65
+ return NSPredicate ( value: value)
66
+ case . block( let block) :
67
+ return NSPredicate ( block: block)
68
+ case . format:
69
+ NSUnimplemented ( )
70
+ case . metadataQuery:
71
+ NSUnimplemented ( )
72
+ }
73
+ }
74
+
75
+ open override func isEqual( _ object: Any ? ) -> Bool {
76
+ if let other = object as? NSPredicate {
77
+ if other === self {
78
+ return true
79
+ } else {
80
+ switch ( other. kind, self . kind) {
81
+ case ( . boolean( let otherBool) , . boolean( let selfBool) ) :
82
+ return otherBool == selfBool
83
+ case ( . format, . format) :
84
+ NSUnimplemented ( )
85
+ case ( . metadataQuery, . metadataQuery) :
86
+ NSUnimplemented ( )
87
+ default :
88
+ // NSBlockPredicate returns false even for copy
89
+ return false
90
+ }
91
+ }
92
+ }
93
+
94
+ return false
42
95
}
43
96
44
97
// Parse predicateFormat and return an appropriate predicate
@@ -58,7 +111,21 @@ open class NSPredicate : NSObject, NSSecureCoding, NSCopying {
58
111
super. init ( )
59
112
}
60
113
61
- open var predicateFormat : String { NSUnimplemented ( ) } // returns the format string of the predicate
114
+ open var predicateFormat : String {
115
+ switch self . kind {
116
+ case . boolean( let value) :
117
+ return value ? " TRUEPREDICATE " : " FALSEPREDICATE "
118
+ case . block:
119
+ // TODO: Bring NSBlockPredicate's predicateFormat to macOS's Foundation version
120
+ // let address = unsafeBitCast(block, to: Int.self)
121
+ // return String(format:"BLOCKPREDICATE(%2X)", address)
122
+ return " BLOCKPREDICATE "
123
+ case . format:
124
+ NSUnimplemented ( )
125
+ case . metadataQuery:
126
+ NSUnimplemented ( )
127
+ }
128
+ }
62
129
63
130
open func withSubstitutionVariables( _ variables: [ String : Any ] ) -> Self { NSUnimplemented ( ) } // substitute constant values for variables
64
131
@@ -76,6 +143,10 @@ open class NSPredicate : NSObject, NSSecureCoding, NSCopying {
76
143
return value
77
144
case let . block( block) :
78
145
return block ( object, bindings)
146
+ case . format:
147
+ NSUnimplemented ( )
148
+ case . metadataQuery:
149
+ NSUnimplemented ( )
79
150
}
80
151
} // single pass evaluation substituting variables from the bindings dictionary for any variable expressions encountered
81
152
0 commit comments