«Значение необязательного типа Self? Not unwrapped» внутри сбойного инициализатора с «try?»и "Self", как написать без распаковки - PullRequest
0 голосов
/ 05 октября 2018

Я пытаюсь добавить функцию десериализации JSON в мои протоколы, но не могу заставить функцию decode скомпилировать.Как мне написать инициализатор без принудительного распаковывания значения?

protocol Mappable: Codable {
  init?(jsonString: String)
}

extension Mappable {
  init?(jsonString: String) {
    guard let data = jsonString.data(using: .utf8) else {
        return nil
    }
    // TODO:- Value of optional type 'Self?' not unwrapped error
    self = try? JSONDecoder().decode(Self.self, from: data)
  }
}

Ответы [ 2 ]

0 голосов
/ 05 октября 2018

Сбрасываемый инициализатор будет работать лучше здесь:

protocol Mappable: Codable {
    init(jsonString: String) throws
}

extension Mappable {
    init(jsonString: String) throws {
        let data = jsonString.data(using: .utf8)! // this will never be nil
        self = try JSONDecoder().decode(Self.self, from: data)
    }
}

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

0 голосов
/ 05 октября 2018

try? возвращает необязательное значение.Но в отказавшем инициализаторе вы не присваиваете nil self, вы return nil.

. Следующие работы:

extension Mappable {
    init?(jsonString: String) {
        guard let data = jsonString.data(using: .utf8) else {
            return nil
        }

        do {
            self = try JSONDecoder().decode(Self.self, from: data)
        } catch {
            return nil
        }
    }
}

Как утверждали другие, некоторыедругие вещи, которые следует учитывать:

  1. String data(using:) с кодировкой .utf8 не может дать сбой, поэтому guard можно заменить принудительно развернутым.
  2. Рассмотреть возможность измененияэто от сбойного инициализатора к тому, который выбрасывает.
...