0

With my newbie swift skills I'm struggling to figure out the correct swift syntax to get this playground to work. Depending how I try to solve it I either get

Cannot invoke 'encode' with an argument list of type '(Encodable)'

which is similar to what was solved in this question Using JSON Encoder to encode a variable with Codable as type or I get

' (T) -> ()' requires that 'Encodable' conform to 'Encodable'

I'd really appreciate a solution with explanation

EDIT To provide some more context, the pattern I'm trying to implement here is for a middleware router. Depending on the actions made in the app, the router will construct the network request. The intent of the codableParam is to deliver the conforming structure for the use case. All cases would therefore return either nil or a Codable type.

struct unityAuthenticationRequest: Codable {
    var username : String
    var password : String
}

enum test  {
    case volume
    case num2
    case num3

    var codableParam: Encodable? {
        switch self {
        case .volume:
            return unityAuthenticationRequest(username: "uname", password: "pwrods")
        default:
            return nil
        }
    }
}

func saveObject<T:Encodable>(_ object: T) {
    let data = try? JSONEncoder().encode(object)
}

func dx<T: Codable>(fx: T) {
    let datax = try? JSONEncoder().encode(fx)
}

let r = test.volume
saveObject(r.codableParam)
300baud
  • 540
  • 4
  • 17
  • What is it that you are trying to achieve? Your example seems quite contrived without an explanation of what is your code supposed to do. You cannot return an `Encodable` and supply that as input to `saveObject`, since `Encodable` cannot be used as a concrete type, which is what the error message actually tells you if you check both errors on the problematic line. – Dávid Pásztor Jun 14 '18 at 11:37
  • Edited and added intent as requested – 300baud Jun 14 '18 at 19:27
  • One option I was considering was for the codableParam function to morph into codableData - where the encode has been performed within the function - but this seemed like a workaround – 300baud Jun 14 '18 at 19:37
  • Now I'm even more confused. If you're trying to create `URLRequest`s, why are you returning `Codable`? Why would you want to encode a `URLRequest` into JSON? How do you plan on executing a `URLRequest` after encoding it to JSON? Btw you should conform to the Swift naming convention, which is UpperCamelCase for type names, so `Test` and `UnityAuthenticationRequest` would be appropriate. – Dávid Pásztor Jun 14 '18 at 19:55
  • I was using this https://medium.com/@AladinWay/write-a-networking-layer-in-swift-4-using-alamofire-and-codable-part-1-api-router-349699a47569 as an example - this will show you the broader context. In this example it uses JSONSerialisation, but I wanted to understand if Codable was a better option. – 300baud Jun 14 '18 at 20:07

1 Answers1

0

The error message pretty much tells you what is going on:

Fatal error: Optional<Encodable> does not conform to Encodable
  because Encodable does not conform to itself.
  You must use a concrete type to encode or decode.:
    file /BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-900.0.74.1/src/swift/stdlib/public/core/Codable.swift, line 3960

It is however easy enough to fix, just change your first line like this:

var codableParam: unityAuthenticationRequest? {
    switch self {
    case .volume:
        return unityAuthenticationRequest(username: "uname", password: "pwrods")
    default:
        return nil
    }
}

Now your parameter does have a concrete type and the requirements are satisfied with minimal syntactic changes.

I am still having a hard time figuring out how this type of code might transfer your intentions in the most comprehensible way possible, but we would have to know more about your intentions in order to improve upon it.

Patru
  • 4,481
  • 2
  • 32
  • 42
  • Thx @Patru - I did think about this, but because different cases will return different structs, I didn't progress this (have clarified in main question now). Is it possible to subclass the types and use the base class as the type (again, limited swift knowledge for this suggestion) – 300baud Jun 14 '18 at 19:30
  • Your class must be concrete, it cannot be a `protocol` at this point. You should be able to derive different subclasses from a common base class (which implements `Codable`) and have your `enum` method return the base class. However I cannot quite see if associated values would result in better code without some more concrete examples. – Patru Jun 15 '18 at 17:43