Быстрое игнорирование типов параметров, определенных в сигнатуре блока - PullRequest
0 голосов
/ 31 октября 2019

У меня есть код ниже, которым компилятор доволен:

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
}

Но как только я определяю тип item в сигнатуре блока, я получаю сообщение об ошибке в строке возврата:

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
}

Там написано Value of type 'Any?' has no member 'ColorCode'. Как я могу решить это? Почему он все еще использует тип Any по умолчанию, предоставленный блоком?

1 Ответ

1 голос
/ 31 октября 2019

Если вы посмотрите на подпись для NSPredicate.init(block:), то увидите, что блок принимает два параметра и возвращает логическое значение: (Any?, [String : Any]?) -> Bool), а первый параметр действительно Any.

В вашем первом примере вы используете принудительное приведение с as!, поэтому оно работает (это может произойти сбой, если тип на самом деле не был Paint упакован в Any. Ваш второй пример выдает ошибку, потому чтоваша типовая аннотация неверна, компилятор ожидает, что первый параметр будет Any, а не Paint?; он действительно должен выдавать вам ошибку в строке выше, но кажется, что он первым перехватывает его в строке с возвратом.

Если вы хотите безопасно развернуть, это должно быть:

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...