Search code examples
iosrealmios11swift4xcode9

Swift 4 - Ambigous reference to member '>' (iOS 11)


I am getting this misleading error message after converting to Swift 4 syntax.

Ambiguous reference to member '>'

on this line of code :

redCount = alerts!.filter { $0.dangerLevels.filter { $0.level.value == 4 }.count > 0 }.count

full context code :

alerts = realm.objects(Alerts).filter(NSPredicate(format: "department != nil")).sorted(byKeyPath: "departmentNumber")

redCount = alerts!.filter { $0.dangerLevels.filter { $0.level.value == 4 }.count > 0 }.count

The error message isn't explicit at all, can I have some hints ?

Keep in mind that alerts is of type Results<Alert>?

and dangerLevel is declared as following: let dangerLevels = List<DangerLevel>()

EDIT:

Here are some additional informations concerning the types inside the closure.

let level = RealmOptional<Int>()

and value is from RealmOptional

public var value: T? {
        get {
            return underlyingValue.map(dynamicBridgeCast)
        }
        set {
            underlyingValue = newValue.map(dynamicBridgeCast)
        }
    }

EDIT 2: I have rewritten the syntax for better readability but here are my results :

redCount = alerts!.filter { $0.dangerLevels.contains { ($0.level.value as! Int) == 4 } }.count

enter image description here


Solution

  • The value is a generic method and when comparing with a literal (that is, something without a defined type), the compiler has a problem to figure out what type to infer there. One workaround is to add as Int to one side of the expression:

    (slightly rewritten for readability)

    let alerts = realm.objects(Alerts).filter(NSPredicate(format: "department != nil")).sorted(byKeyPath: "departmentNumber")
    
    let isRedLevel: (DangerLevel) -> Bool = { dangerLevel in
       ($0.level.value as Int) == 4
    }
    let hasRedLevels: (Alert) -> Bool = { alert in
        alert.dangerLevels.contains(where: isRedLevel)
    }
    
    redCount = alerts!.filter(hasRedLevels).count
    

    What would also work is to define a constant:

    let redAlertType: Int = 4
    

    and use it instead of the literal 4.