iosswiftxcode11argo

Binary operator '<^>' cannot be applied to operands of type


I has the follow code implemented to work with Argo framework, has been working until the Xcode 11.2.1 update. when I updated my Xcode Version the follow error appears:

Binary operator '<^>' cannot be applied to operands of type '(()) -> VoiceMailNumberResponse' and 'Decoded<_?>'

Here's my code:

struct VoiceMailNumberResponse{
    var name: String?
    var value: String?
}

extension VoiceMailNumberResponse: Argo.Decodable {
    static func decode(_ json: JSON) -> Decoded<VoiceMailNumberResponse> {
        let voiceMailNumberResponse = curry(VoiceMailNumberResponse.init)
        return voiceMailNumberResponse
            <^> json <|?  "name"
            <*> json <|?  "value"
    }
}

Error appears on line: "<^> json <|? "name"

In addition I'm using Argo, Curry and Runes for parsing JSON.


Solution

  • Note: This answer is based only off your code sample and has not been tested.

    As both the properties of VoiceMailNumberResponse are optional then Xcode 10.1/Swift 4.2 (the version tested with) produces two init methods:

    init()
    init(name: String?, value: String?)
    

    If neither, or just one, property is an optional only the second init is produced. From the question it appears Xcode 11.2.1/Swift 5.1 behaves the same way.

    The type in the error message:

    (()) -> VoiceMailNumberResponse
    

    indicates that the compiler has selected the init() to pass to curry, while the code expects the init(name: String?, value: String?) to be passed.

    As the code apparently worked with some previous Xcode/Swift this would appear to be a change in behaviour.

    This could be a change to, or "feature" of, the language and/or compiler. You can probably work around it by explicitly specifying which init to use by including the parameter names, e.g. something like:

    ...
    let voiceMailNumberResponse = curry(VoiceMailNumberResponse.init(name:value:))
    ...
    

    That said it would be best to figure out if:

    You might also want to look at using Swift's Decodable, introduced in Xcode 9, to decode the JSON as an alternative to using these third-party packages.

    HTH