I have the code below, which the compiler is happy with:
func CheckPaintExists(colorCode : String, applicationCode : String) {
let checkRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Paint")
checkRequest.predicate = NSPredicate(block: { (item, bindings) -> Bool in
return (item as! Paint).ColorCode == colorCode
&& (item as! Paint).ApplicationCode == applicationCode
})
checkRequest.includesSubentities = false;
//managedContext.count(for: ...)do further stuff
}
But once I define the item
type in the block signature, I get an error on the return line:
func CheckPaintExists2(colorCode : String, applicationCode : String) {
let checkRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Paint")
checkRequest.predicate = NSPredicate(block: { (item : Paint?, bindings : NSDictionary?) -> Bool in
return item.ColorCode == colorCode //*Value of type 'Any?' has no member 'ColorCode'
&& item.ApplicationCode == applicationCode
})
checkRequest.includesSubentities = false;
//managedContext.count(for: ...)do further stuff
}
It says Value of type 'Any?' has no member 'ColorCode'
. How can I resolve this? Why is it still using the default Any type provided by the block?
If you look at the signature for NSPredicate.init(block:)
then you will see that block takes two parameters and returns a boolean: (Any?, [String : Any]?) -> Bool)
and the first parameter is indeed an Any
.
In your first example you are force casting with as!
which is why it works (it would crash here if the type was not actually Paint
boxed in an Any
. Your second example is giving you an error because your type annotation is wrong; the compiler expects the first parameter to be Any
and not Paint?
; it really should be giving you the error on the line above but it seems its first catching it on the line with the return.
If you want to unwrap safely it should be:
func CheckPaintExists(colorCode : String, applicationCode : String) {
let checkRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Paint")
checkRequest.predicate = NSPredicate(block: { (item, bindings) -> Bool in
guard let paint = item as? Paint else {
return false
}
return paint.ColorCode == colorCode
&& paint.ApplicationCode == applicationCode
})
checkRequest.includesSubentities = false;
//managedContext.count(for: ...)do further stuff
}