首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我们不能使用协议‘`Encodable`’作为func中的一个类型?

为什么我们不能使用协议‘`Encodable`’作为func中的一个类型?
EN

Stack Overflow用户
提问于 2018-06-27 08:42:20
回答 6查看 14.4K关注 0票数 17

我试图通过符合Encodable协议的编码模型来获取数据。但是它没有像下面的代码那样调用func encode

代码语言:javascript
复制
// MARK: - Demo2

class TestClass2: NSObject, Encodable {
    var x = 1
    var y = 2
}


var dataSource2: Encodable?

dataSource2 = TestClass2()

// error: `Cannot invoke 'encode' with an argument list of type '(Encodable)'`
let _ = try JSONEncoder().encode(dataSource2!)
//func encode<T>(_ value: T) throws -> Data where T : Encodable

但在另一个演示中,它工作得很好,为什么?

代码语言:javascript
复制
// MARK: - Demo1

protocol TestProtocol {
    func test()
}

class TestClass1: NSObject, TestProtocol {
    func test() {
        print("1")
    }

    var x = 1
    var y = 2
}


var dataSource1: TestProtocol?

dataSource1 = TestClass1()


func logItem(_ value: TestProtocol) {
    value.test()
}

logItem(dataSource1!)
EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2018-06-27 08:52:01

解决方案1.

试试下面的代码,它扩展了可编码的

代码语言:javascript
复制
extension Encodable {
    func toJSONData() -> Data? { try? JSONEncoder().encode(self) }
}

解决方案2.

避免通过扩展来污染苹果提供的协议

代码语言:javascript
复制
protocol MyEncodable: Encodable {
    func toJSONData() -> Data?
}

extension MyEncodable {
    func toJSONData() -> Data?{ try? JSONEncoder().encode(self) }
}

使用

代码语言:javascript
复制
var dataSource2: Encodable?
dataSource2 = TestClass2()
let data = dataSource2?.toJSONData()
票数 38
EN

Stack Overflow用户

发布于 2019-10-31 11:00:02

您不能传递协议,但可以使用泛型来要求一个符合该类的类:

代码语言:javascript
复制
func printJSON<T: Encodable>(_ data: T) {
    if let json = try? JSONEncoder().encode(data) {
        if let str = String(data: json, encoding: .utf8) {
            print(str)
        }
    }
}

// Now this should work
var dataSource2 = TestClass2()
printJSON(dataSource2!)
票数 9
EN

Stack Overflow用户

发布于 2019-06-28 23:18:46

解决这个问题有许多方法。

扩展Encodable的@SPatel解决方案是一种可能。然而,我个人试图避免通过扩展来污染苹果提供的协议。

如果我在行之间阅读,那么您想要的似乎是传递符合的任何符合Encodable的构造结构(Encodable),该构造符合中的函数/方法--其他一些结构/类。

让我们举一个例子,说明我认为你正在努力实现的目标:

代码语言:javascript
复制
struct Transform {
    static func toJson(encodable: Encodable) throws -> Data {
        return try JSONEncoder().encode(encodable)
    }
}

但是,Xcode会抱怨:

代码语言:javascript
复制
Protocol type 'Encodable' cannot conform to 'Encodable' because only concrete types can conform to protocols

Swift-ier解决方案是在函数上使用受限的泛型:

代码语言:javascript
复制
struct Transform {
    static func toJson<EncodableType: Encodable>(encodable: EncodableType) throws -> Data {
        return try JSONEncoder().encode(encodable)
    }
}

现在编译器可以推断符合Encodable的类型,我们可以按预期调用函数:

代码语言:javascript
复制
let dataSource = TestClass2()
let jsonData = try? Transform.toJson(encodable: dataSource)
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51058292

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档