Использование JSON Encoder с вычисляемой переменной типа Codable

С моими навыками Swift новичка я изо всех сил пытаюсь выяснить правильный синтаксис Swift, чтобы эта игровая площадка заработала. В зависимости от того, как я пытаюсь решить эту проблему, я либо получаю

Невозможно вызвать 'encode' со списком аргументов типа '(Encodable)'

который аналогичен тому, что было решено в этом вопросе Использование JSON Encoder для кодирования переменной с Codable as type, или я получаю

'(T) -> ()' требует, чтобы 'Encodable' соответствовал 'Encodable'

Я был бы очень признателен за решение с объяснением

ИЗМЕНИТЬ. Чтобы предоставить дополнительный контекст, шаблон, который я пытаюсь реализовать, предназначен для маршрутизатора промежуточного программного обеспечения. В зависимости от действий, выполненных в приложении, маршрутизатор сформирует сетевой запрос. Назначение codableParam - предоставить соответствующую структуру для варианта использования. Таким образом, все варианты вернут либо nil, либо тип Codable.

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)

person 300baud    schedule 14.06.2018    source источник
comment
Чего вы пытаетесь достичь? Ваш пример кажется довольно надуманным без объяснения того, что должен делать ваш код. Вы не можете вернуть Encodable и передать его в качестве входных данных для saveObject, поскольку Encodable не может использоваться как конкретный тип, о чем на самом деле сообщает вам сообщение об ошибке, если вы проверяете обе ошибки в проблемной строке.   -  person Dávid Pásztor    schedule 14.06.2018
comment
Отредактировано и добавлено намерение по запросу   -  person 300baud    schedule 14.06.2018
comment
Один из вариантов, который я рассматривал, заключался в том, чтобы функция codableParam трансформировалась в codableData, где кодирование выполнялось внутри функции, но это казалось обходным путем.   -  person 300baud    schedule 14.06.2018
comment
Теперь я еще больше запутался. Если вы пытаетесь создать URLRequests, почему вы возвращаете Codable? Зачем вам нужно кодировать URLRequest в JSON? Как вы планируете выполнять URLRequest после его кодирования в JSON? Кстати, вы должны соответствовать соглашению об именах Swift, которое является UpperCamelCase для имен типов, поэтому Test и UnityAuthenticationRequest будут подходящими.   -  person Dávid Pásztor    schedule 14.06.2018
comment
Я использовал этот medium.com/@AladinWay/ в качестве примера - это покажет вам более широкий контекст. В этом примере используется JSONSerialisation, но я хотел понять, был ли Codable лучшим вариантом.   -  person 300baud    schedule 14.06.2018


Ответы (1)


Сообщение об ошибке в значительной степени говорит вам, что происходит:

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

Однако это достаточно легко исправить, просто измените свою первую строку следующим образом:

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

Теперь у вашего параметра есть конкретный тип, и требования удовлетворены с минимальными синтаксическими изменениями.

Мне все еще трудно понять, как этот тип кода может передать ваши намерения наиболее понятным способом, но нам нужно больше узнать о ваших намерениях, чтобы улучшить его.

person Patru    schedule 14.06.2018
comment
Спасибо @Patru - я действительно думал об этом, но поскольку разные случаи будут возвращать разные структуры, я не продвинулся в этом (сейчас пояснил в основном вопросе). Можно ли подклассифицировать типы и использовать базовый класс в качестве типа (опять же, ограниченные быстрые знания для этого предложения) - person 300baud; 14.06.2018
comment
Ваш класс должен быть конкретным, на данном этапе он не может быть protocol. Вы должны иметь возможность наследовать различные подклассы от общего базового класса (который реализует Codable), и ваш метод enum должен возвращать базовый класс. Однако я не совсем понимаю, приведут ли связанные значения к лучшему коду без некоторых более конкретных примеров. - person Patru; 15.06.2018