面向Swift协议的网络代码崩溃Xcode

时间:2017-06-15 07:40:58

标签: ios swift xcode

在面向协议的网络代码的游乐场玩耍,在我把所有东西放在一起的最后一行,Xcode崩溃说

  

LLDB RPC服务器已崩溃......依此类推

我的代码中肯定存在一些严重错误,我确信这是在最后几行,但我无法弄明白。

import UIKit
import PlaygroundSupport

struct Repo {
    let id: Int
    let name: String
}

extension Repo {
    init?(dict: JSONDict) {
        guard let id = dict["id"] as? Int, let name = dict["name"] as? String else { return nil }
        self.id = id
        self.name = name
    }
}

typealias JSONDict = [String:Any]

protocol Resource {
    associatedtype Content
    var url: URL { get }
    func parse(data: Data) -> Content?
}

extension Resource {
    func parseJSON(data: Data) -> Any? {
        let json = try? JSONSerialization.jsonObject(with: data)
        return json
    }
}

struct RepoService: Resource {
    let url = URL(string: "https://api.github.com/users/mkchoi212/repos")!

    func parse(data: Data) -> [Repo]? {
        guard let dictArray = self.parseJSON(data: data) as? [JSONDict] else { return nil }
        return dictArray.flatMap(Repo.init)
    }
}

final class WebService<Content> {
    func load<R: Resource>(resource: R, completion: @escaping (R.Content?) -> ()) {
        URLSession.shared.dataTask(with: resource.url) { data, _, _ in
            let res = data.flatMap(resource.parse)
            completion(res)
        }.resume()
    }
}

WebService().load(resource: RepoService) { res in
    for elem in res {
        print(elem)
    }
}

PlaygroundPage.current.needsIndefiniteExecution = true

2 个答案:

答案 0 :(得分:4)

崩溃的编译器是一个错误,应该报告。 Xcode 9(beta)没有 使用您的代码崩溃,但会提供有用的错误消息,从而产生解决方案:

error: generic parameter 'Content' could not be inferred
WebService().load(resource: RepoService) { res in
             ^

Content中的通用占位符class WebService<Content>是 根本不使用,删除它并使该类非通用。然后:

error: generic parameter 'R' could not be inferred
WebService().load(resource: RepoService) { res in
             ^

您必须将RepoService实例传递给load方法, 闭包内的res是可选的。

随着这些变化

final class WebService {
    func load<R: Resource>(resource: R, completion: @escaping (R.Content?) -> ()) {
        URLSession.shared.dataTask(with: resource.url) { data, _, _ in
            let res = data.flatMap(resource.parse)
            completion(res)
            }.resume()
    }
}

WebService().load(resource: RepoService()) { res in
    guard let res = res else { return }
    for elem in res {
        print(elem)
    }
}

您的代码在Xcode 8.3.3和9中编译并按预期运行。

答案 1 :(得分:0)

工作示例

import Foundation

import PlaygroundSupport

struct Repo {
    let id: Int
    let name: String
}

extension Repo {
    init?(dict: JSONDict) {
        guard let id = dict["id"] as? Int, let name = dict["name"] as? String else { return nil }
        self.id = id
        self.name = name
    }
}

typealias JSONDict = [String:Any]

protocol Resource {
    associatedtype Content
    var url: URL { get }
    func parse(data: Data) -> Content?
}

extension Resource {
    func parseJSON(data: Data) -> Any? {
        let json = try? JSONSerialization.jsonObject(with: data)
        return json
    }
}

struct RepoService: Resource {
    let url = URL(string: "https://api.github.com/users/mkchoi212/repos")!

    func parse(data: Data) -> [Repo]? {
        guard let dictArray = self.parseJSON(data: data) as? [JSONDict] else { return nil }
        return dictArray.flatMap(Repo.init)
    }
}

final class WebService {
    func load<R: Resource>(resource: R, completion: @escaping (R.Content) -> ()) {
        URLSession.shared.dataTask(with: resource.url) { data, _, _ in
            if let res = data.flatMap(resource.parse) {
                completion(res)
            }
            }.resume()
    }
}

WebService().load(resource: RepoService()) { res in
    for elem in res {
        print(elem)
    }
}

PlaygroundPage.current.needsIndefiniteExecution = true

给了我这个结果

Repo(id: 93473150, name: "bitbuf")
Repo(id: 28517340, name: "DIJKASTRAS")
Repo(id: 71310619, name: "git-strbuf")
Repo(id: 30558002, name: "Habitats-master")
Repo(id: 28517464, name: "Home-Automation-Project")
Repo(id: 33394787, name: "hw.")
Repo(id: 39911528, name: "JPSThumbnailAnnotation")
Repo(id: 37162894, name: "M3")
Repo(id: 39709018, name: "Maroon")
Repo(id: 41267183, name: "mkchoi212.github.io")
Repo(id: 28519262, name: "Money-Saving-Meals")
Repo(id: 39857111, name: "MRCircularProgressView")
Repo(id: 81773538, name: "papers-we-love")
Repo(id: 37074317, name: "socket.io-client-swift")
Repo(id: 28519322, name: "Wordsneak")