I have the following Decodable
model:
struct VideoResponse: Decodable {
let videos: [Video]
let lastVideos: [Video]
enum CodingKeys: String, CodingKey {
case videos
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let videos = try container.decode([Video].self, forKey: .videos)
self.videos = sort(videos)
self.lastVideos = computeLastVideos(from: self.videos)
}
}
The above does not compile since I'm trying to use both sort
and compute(from:)
before before all stored properties are initialized.
'self' used before all stored properties are initialized.
To fix the problem I could indeed move the logic within the the two method inside init(from:)
decoder. I would avoid it since the VideoResponse
could be used as a plain struct
.
extension VideoReponse {
init(videos: [Videos]) {
// same setup here...
}
}
Any idea on how to fix this in order to avoid duplicated code?
You can't call methods on self
before stored properties are all initialised because the methods could potentially access an uninitialised property (See also this answer of mine), and who knows what happens then? You can tell Swift that sort
and computeLastVideos
won't access self
at all, by putting the word static
:
static func sort(_ videos: [Video]) -> [Video] { ... }
static func computeLastVideos(from videos: [Video]) -> [Video] { ... }
You would also have to put the sorted videos into a temporary variable sortedVideos
first, because you can't access self.videos
:
let container = try decoder.container(keyedBy: CodingKeys.self)
let videos = try container.decode([Video].self, forKey: .videos)
let sortedVideos = VideoResponse.sort(videos)
self.lastVideos = VideoResponse.computeLastVideos(from: sortedVideos)
self.videos = sortedVideos
If sort
and computerLastVideos
does access self
though, you are out of luck, and have to make videos
a non-let
, and initialise it first, then change it later. You can't guarantee to Swift that sort
and computeLastVideos
will only access the initialised part of self
.