SwiftUI 结合 URLSession JSON 网络调用

SwiftUI Combine URLSession JSON Network Call

我正在尝试了解进行 JSON 网络调用的 Combine 方法。我是 显然缺少一些基本的东西。

我得到的最接近的失败,URLSession 被取消。

class NoteDataStore: ObservableObject {

    @Published var notes: [MyNote] = []

    init() {
        getWebserviceNotes()
    }

    func getWebserviceNotes() {

        let pub = Webservice().fetchNotes()
            .sink(receiveCompletion: {_ in}, receiveValue: { (notes) in
            self.notes = notes
            })
        }
    }
}//class

数据元素:

struct MyNote: Codable, Identifiable {
    let id = UUID()
    var title: String
    var url: String
    var thumbnailUrl: String

    static var placeholder: MyNote {
        return MyNote(title: "No Title", url: "", thumbnailUrl: "")
    }
}

网络设置:

class Webservice {
    func fetchNotes() -> AnyPublisher<[MyNote], Error> {
        let url = "https://jsonplaceholder.typicode.com/photos"
        guard let notesURL = URL(string: url) else { fatalError("The URL is broken")}

        return URLSession.shared.dataTaskPublisher(for: notesURL)
            .map { [=13=].data }
            .decode(type: [MyNote].self, decoder: JSONDecoder())
            .receive(on: RunLoop.main)
            .eraseToAnyPublisher()
    }
}

控制台输出为:

Task <85208F00-BC24-44AA-B644-E0398FE263A6>.<1> finished with error [-999] Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLStringKey=https://jsonplaceholder.typicode.com/photos, NSLocalizedDescription=cancelled, NSErrorFailingURLKey=https://jsonplaceholder.typicode.com/photos}

如有任何指导,我们将不胜感激。 Xcode11.4

let pub = Webservice().fetchNotes()

此发布者在范围退出时发布,因此使其成为成员,例如

private var publisher: AnyPublisher<[MyNote], Error>?

func getWebserviceNotes() {
    self.publisher = Webservice().fetchNotes()
    ...

根据 Asperi 的回答 - 您还需要添加:

var cancellable: AnyCancellable?

然后就可以下沉获取数据了:

func getWebserviceNotes() {

    self.publisher = Webservice().fetchNotes()
    guard let pub = self.publisher else { return }

    cancellable = pub
            .sink(receiveCompletion: {_ in },
                  receiveValue: { (notes) in
                    self.notes = notes
            })
}