【问题标题】:How do I use swift generic Decodable protocol in generic functions如何在泛型函数中使用 swift 泛型可解码协议
【发布时间】:2020-06-17 22:53:47
【问题描述】:

我想编写一个通用函数来解析结果并在闭包的成功块中返回或在失败块中发送回错误。

我遇到了这样的错误'无法推断通用参数'T''

这是我的示例代码。

let jsonString = """
{
"id": 1,
"msg": "Sample msg"
}
"""

struct Post: Codable {
    var id: String?
    var msg: String?
}

enum PostError: Error {
    case empty
}


func fetch<T:Decodable>(_ completion: @escaping (Result<T?, PostError>) -> Void)  {

        do {
            let data = Data(jsonString.utf8)
            let post = try JSONDecoder().decode(T.self, from: data)
            completion(.success(post))
        }
        catch {
            completion(.failure(.empty))
        }
    }


fetch { res in
        switch res {
        case .success( let p):
            print(p.description)

        case .failure(let error):
            print(error)
        }
    }

这是我遇到的错误。

【问题讨论】:

  • 我猜你希望res 成为Result&lt;Post?, PostError&gt;?但是Post? 没有description 属性。

标签: ios swift swift3


【解决方案1】:

您可以接受泛型类型作为参数,如下所示:

func fetchObject<T:Decodable>(ofType type: T.Type, _ completion: @escaping (Result<T, PostError>) -> Void)  {
   do {
      let data = Data(jsonString.utf8)
      let post = try JSONDecoder().decode(type, from: data)
      completion(.success(post))
   }
   catch {
      completion(.failure(.empty))
   }
}

用法:

fetchObject(ofType: Post.self) { res in
   switch res {
       case .success(let post):
          print(post.description)
       case .failure(let error):
          print(error)
   }
}

【讨论】:

    【解决方案2】:

    我了解您要做什么,但主要问题是您从不指定类型。编译器知道您要调用fetch,但它不知道您要获取什么或将其解析为什么。

    如果您查看您的 fetch 调用,编译器可能无法告诉您正在尝试做什么或您期望发生什么。

    您必须:

    1。将类型作为参数传递

    func fetch<T: Decodable>(_ type: T.Type, _ completion: @escaping (Result<T, PostError>) -> Void)  {
    
        do {
            let data = Data(jsonString.utf8)
            let post = try JSONDecoder().decode(T.self, from: data)
            completion(.success(post))
        }
        catch {
            completion(.failure(.empty))
        }
    }
    
    
    fetch(Post.self) { res in
            switch res {
            case .success(let p):
                print(p)
    
            case .failure(let error):
                print(error)
            }
        }
    

    或者...

    2。指定函数所属对象的实例化类型:

    struct Fetcher<T: Decodable> {
    
        func fetch(_ completion: @escaping (Result<T, PostError>) -> Void)  {
    
            do {
                let data = Data(jsonString.utf8)
                let post = try JSONDecoder().decode(T.self, from: data)
                completion(.success(post))
            }
            catch {
                completion(.failure(.empty))
            }
        }
    }
    
    let fetcher = Fetcher<Post>()
    fetcher.fetch { res in
        switch res {
        case .success(let p):
            print(p)
    
        case .failure(let error):
            print(error)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-10
      相关资源
      最近更新 更多