我正在尝试将 SwiftData 集成到我的网络模型中以合并本地持久性。为了实现这一目标,我需要确保我的 Codable 模型符合 SwiftData。但是,我在构建过程中遇到了错误。有其他人遇到类似问题并找到解决方案吗?
以下是我的模型:我省略了某些模型属性以启用帖子的发布。
import SwiftData
import SwiftUI
// MARK: - Game
@Model
class Game: Codable, Identifiable, Hashable {
let id: Int?
let name: String?
let cover: Cover?
let firstReleaseDate: Int?
let summary: String?
let totalRating: Double?
let ratingCount: Int?
let genres: [Genre]?
let platforms: [Platform]?
let releaseDates: [ReleaseDate]?
let screenshots: [Cover]?
let gameModes: [GameMode]?
let videos: [Video]?
let websites: [Website]?
let similarGames: [Int]?
let artworks: [Artwork]?
enum CodingKeys: String, CodingKey {
case id, name, cover, artworks, genres, platforms, screenshots, summary, videos, websites
case firstReleaseDate = "first_release_date"
case releaseDates = "release_dates"
case totalRating = "total_rating"
case ratingCount = "rating_count"
case gameModes = "game_modes"
case similarGames = "similar_games"
}
init(
id: Int? = nil,
name: String? = nil,
cover: Cover? = nil,
firstReleaseDate: Int? = nil,
summary: String? = nil,
totalRating: Double? = nil,
versionTitle: String? = nil,
ratingCount: Int? = nil,
genres: [Genre]? = nil,
platforms: [Platform]? = nil,
releaseDates: [ReleaseDate]? = nil,
screenshots: [Cover]? = nil,
gameModes: [GameMode]? = nil,
videos: [Video]? = nil,
websites: [Website]? = nil,
similarGames: [Int]? = nil,
artworks: [Artwork]? = nil
) {
self.id = id
self.name = name
self.cover = cover
self.firstReleaseDate = firstReleaseDate
self.summary = summary
self.totalRating = totalRating
self.ratingCount = ratingCount
self.genres = genres
self.platforms = platforms
self.releaseDates = releaseDates
self.screenshots = screenshots
self.gameModes = gameModes
self.videos = videos
self.websites = websites
self.similarGames = similarGames
self.artworks = artworks
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(Int?.self, forKey: .id)
self.name = try container.decode(String?.self, forKey: .name)
self.firstReleaseDate = try container.decode(Int?.self, forKey: .firstReleaseDate)
self.summary = try container.decode(String?.self, forKey: .summary)
self.totalRating = try container.decode(Double?.self, forKey: .totalRating)
self.genres = try container.decode([Genre]?.self, forKey: .genres)
self.platforms = try container.decode([Platform]?.self, forKey: .platforms)
self.releaseDates = try container.decode([ReleaseDate]?.self, forKey: .releaseDates)
self.screenshots = try container.decode([Cover]?.self, forKey: .screenshots)
self.gameModes = try container.decode([GameMode]?.self, forKey: .gameModes)
self.videos = try container.decode([Video]?.self, forKey: .videos)
self.websites = try container.decode([Website]?.self, forKey: .websites)
self.similarGames = try container.decode([Int]?.self, forKey: .similarGames)
self.artworks = try container.decode([Artwork]?.self, forKey: .artworks)
self.cover = try container.decode(Cover?.self, forKey: .cover)
self.ratingCount = try container.decode(Int?.self, forKey: .ratingCount)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(cover, forKey: .cover)
try container.encode(artworks, forKey: .artworks)
try container.encode(firstReleaseDate, forKey: .firstReleaseDate)
try container.encode(genres, forKey: .genres)
try container.encode(name, forKey: .name)
try container.encode(platforms, forKey: .platforms)
try container.encode(releaseDates, forKey: .releaseDates)
try container.encode(screenshots, forKey: .screenshots)
try container.encode(summary, forKey: .summary)
try container.encode(totalRating, forKey: .totalRating)
try container.encode(ratingCount, forKey: .ratingCount)
try container.encode(gameModes, forKey: .gameModes)
try container.encode(videos, forKey: .videos)
try container.encode(websites, forKey: .websites)
try container.encode(similarGames, forKey: .similarGames)
}
}
// MARK: - Artwork
@Model
class Artwork: Codable, Hashable {
let id: Int?
let url: String?
enum CodingKeys: CodingKey {
case id
case url
}
init(id: Int?, url: String?) {
self.id = id
self.url = url
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(Int?.self, forKey: .id)
self.url = try container.decode(String?.self, forKey: .url)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(url, forKey: .url)
}
}
// MARK: - Cover
@Model
class Cover: Codable, Hashable {
let id: Int?
let url: String?
enum CodingKeys: CodingKey {
case id
case url
}
init(id: Int?, url: String?) {
self.id = id
self.url = url
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(Int?.self, forKey: .id)
self.url = try container.decode(String?.self, forKey: .url)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(url, forKey: .url)
}
}
// MARK: - Genre
@Model
class Genre: Codable, Hashable {
let id: Int?
let name: String?
enum CodingKeys: CodingKey {
case id
case name
}
init(id: Int?, name: String?) {
self.id = id
self.name = name
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(Int?.self, forKey: .id)
self.name = try container.decode(String?.self, forKey: .name)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(name, forKey: .name)
}
}
// MARK: - GameMode
@Model
class GameMode: Codable, Hashable {
////
}
// MARK: - Platform
@Model
class Platform: Codable, Hashable {
////
}
// MARK: - ReleaseDate
@Model
class ReleaseDate: Codable, Hashable, Comparable {
////
}
// MARK: - Video
@Model
class Video: Codable, Hashable {
////
}
// MARK: - Website
@Model
class Website: Codable, Hashable {
////
}
尝试转换 Codable 模型以符合 Swift Data @Model Macro
SwiftData(或任何新宏)似乎与
Codable
不兼容。
它们本身符合
Codable
,并且生成的 JSON 看起来不像基于开发人员创建的属性的标准 JSON。
没有任何文档支持或反对这一点,但苹果使用 SwiftData 复制服务器数据的一个例子是,他们创建了一个辅助
struct
并使用 convenience init
进行初始化。
convenience init(from feature: GeoFeatureCollection.Feature) {
self.init(
code: feature.properties.code,
magnitude: feature.properties.mag,
time: feature.properties.time,
name: feature.properties.place,
longitude: feature.geometry.coordinates[0],
latitude: feature.geometry.coordinates[1]
)
}
https://developer.apple.com/documentation/swiftdata/maintaining-a-local-copy-of-server-data