SwiftUI合并零数据



我创建了一个类来执行网络请求并使用Combine解析数据。我不完全确定代码是正确的,但到目前为止它还在运行(仍在学习Swift的基础知识和基本的网络任务(。我的小部件有正确的数据,并且一直工作到数据变为零。不知道如何检查SwiftUIView中第一个publisher的数据是否为零,即使没有游戏显示,数据似乎也是有效的。

我的SwiftUI视图

struct SimpleEntry: TimelineEntry {
let date: Date
public var model: CombineData?
let configuration: ConfigurationIntent
}
struct Some_WidgetEntryView : View {
var entry: Provider.Entry
@Environment(.widgetFamily) var widgetFamily

var body: some View {
VStack (spacing: 0){
if entry.model?.schedule?.dates.first?.games == nil {
Text("No games Scheduled")
} else {
Text("Game is scheduled")
}
}
}
}

联合

import Foundation
import WidgetKit
import Combine
// MARK: - Combine Attempt
class CombineData {
var schedule: Schedule?
var live: Live?

private var cancellables = Set<AnyCancellable>()

func fetchSchedule(_ teamID: Int, _ completion: @escaping (Live) -> Void) {
let url = URL(string: "https://statsapi.web.nhl.com/api/v1/schedule?teamId=(teamID)")!
let publisher = URLSession.shared.dataTaskPublisher(for: url)
.map(.data)
.decode(type: Schedule.self, decoder: JSONDecoder())
//.catch { _ in Empty<Schedule, Error>() }
//.replaceError(with: Schedule(dates: []))
let publisher2 = publisher
.flatMap {
return self.fetchLiveFeed($0.dates.first?.games.first?.link ?? "")
}
Publishers.Zip(publisher, publisher2)
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: {_ in
}, receiveValue: { schedule, live in
self.schedule = schedule
self.live = live
completion(self.live!)
WidgetCenter.shared.reloadTimelines(ofKind: "NHL_Widget")
}).store(in: &cancellables)
}
func fetchLiveFeed(_ link: String) -> AnyPublisher<Live, Error /*Never if .catch error */> {
let url = URL(string: "https://statsapi.web.nhl.com(link)")!
return URLSession.shared.dataTaskPublisher(for: url)
.map(.data)
.decode(type: Live.self, decoder: JSONDecoder())
//.catch { _ in Empty<Live, Never>() }
.eraseToAnyPublisher()
}
}

正如我在评论中所说,decode(type: Live.self, decoder: JSONDecoder())很可能会返回一个错误,因为当linknil时,您从中获取的URL不会返回任何可以解码为Live.self的内容。

所以你需要以某种方式处理这个案子。例如,可以通过将Live变量设为可选变量,并在link为空(或为零(时返回nil来处理此问题。

这只是为了让你朝着正确的方向前进——你需要自己计算出确切的代码。

let publisher2 = publisher1
.flatMap {
self.fetchLiveFeed($0.dates.first?.games.first?.link ?? "")
.map { $0 as Live? } // convert to an optional
.replaceError(with: nil)
}

然后在sink中,处理nil:

.sink(receiveCompletion: {_ in }, receiveValue: 
{ schedule, live in
if let live = live {
// normal treatment
self.schedule = schedule 
self.live = live
//.. etc
} else {
// set a placeholder
}
})

SwiftUIWidgetKit的工作方式不同。我需要在getTimeline中为IntentTimelineProvider获取数据,然后为TimelineEntry添加一个completion处理程序。严重修改了我的Combine数据模型。所有的荣誉都归功于@EmilioPelaez为我指明了正确的方向,请在这里回答。

相关内容

  • 没有找到相关文章

最新更新