sách gpt4 ăn đã đi

ios - 协议(protocol)类型不能符合协议(protocol),因为只有具体类型才能符合协议(protocol)

In lại 作者:搜寻专家 更新时间:2023-11-01 06:51:02 28 4
mua khóa gpt4 giày nike

在应用程序中,我们有两种类型的贴纸,字符串和位图。每个贴纸包都可以包含两种类型。这就是我声明模型的方式:

// Mark: - Models

protocol Sticker: Codable {
}

public struct StickerString: Sticker, Codable, Equatable {
let fontName: String
let character: String
}

public struct StickerBitmap: Sticker, Codable, Equatable {
let imageName: String
}

在用户选择了一些贴纸并使用它们之后,我们希望将贴纸保存到 UserDefaults 中,这样我们就可以向他显示“最近使用过的”贴纸选项卡。我正在尝试解码保存的 [Sticker] 数组:

let recentStickers = try? JSONDecoder().decode([Sticker].self, from: data)

但是我得到以下编译错误:

Protocol type 'Sticker' cannot conform to 'Decodable' because only concrete types can conform to protocols

我不明白为什么我将 Sticker 声明为 Codable 而它也实现了 Decodable。任何帮助将不胜感激!

câu trả lời hay nhất

而不是协议(protocol)使用泛型。

声明一个简单的函数

func decodeStickers(from data : Data) throws -> T
{
return try JSONDecoder().decode(T.self, from: data)
}

T 可以是单个对象,也可以是数组。


在您的结构中删除 Sticker 协议(protocol)。您还可以删除 Equatable,因为它正在结构中合成。

public struct StickerString : Codable {
let fontName: String
let character: String
}

public struct StickerBitmap : Codable {
let imageName: String
}

要解码其中一种贴纸类型,请注释该类型

let imageStickers = """
[{"imageName":"Foo"},{"imageName":"Bar"}]
"""
let stickerData = Data(imageStickers.utf8)

let recentStickers : [StickerBitmap] = try! decodeStickers(from: stickerData)
print(recentStickers.first?.imageName)

let stringSticker = """
{"fontName":"Times","character":""}
"""
let stickerData = Data(stringSticker.utf8)

let sticker : StickerString = try! decodeStickers(from: stickerData)
print(sticker.character)

要解码 StickerStringStickerBitmap 类型的数组,请声明一个具有关联值的包装器枚举

enum Sticker: Codable {

case string(StickerString)
case image(StickerBitmap)

init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
LÀM {
let stringData = try container.decode(StickerString.self)
self = .string(stringData)
} catch DecodingError.keyNotFound {
let imageData = try container.decode(StickerBitmap.self)
self = .image(imageData)
}
}

func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .string(let string) : try container.encode(string)
case .image(let image) : try container.encode(image)
}
}
}

然后就可以解码了

let stickers = """
[{"imageName":"Foo"},{"imageName":"Bar"}, {"fontName":"Times","character":""}]
"""

let stickerData = Data(stickers.utf8)
let recentStickers = try! JSONDecoder().decode([Sticker].self, from: stickerData)
print(recentStickers)

在 TableView 中只需切换枚举

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let sticker = stickers[indexPath.row]
switch sticker {
case .string(let stringSticker):
let cell = tableView.dequeueReusableCell(withCellIdentifier: "StringStickerCell", for: indexPath) as! StringStickerCell
// update UI
return cell
case .image(let imageSticker):
let cell = tableView.dequeueReusableCell(withCellIdentifier: "ImageStickerCell", for: indexPath) as! ImageStickerCell
// update UI
return cell
}
}

关于ios - 协议(protocol)类型不能符合协议(protocol),因为只有具体类型才能符合协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57026463/

28 4 0
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress