swift - 为什么不在 Swift Widget 中使用 URLSession
问题描述
我从我的站点创建带有温度的小部件。在标准程序中所有工作,但在结果小部件中我看到“0”(来自var的信息)
这里有错误的代码(DataProvider.swift)
import Foundation
class DataProvider {
struct CurrencyJSON: Codable {
var temp : String
}
static func getTemp() -> String {
var dig : String = "0"
print ("1")
//on url this data: {temp:3.5}, this is my site, i can do anything format, may be make format: 3.5 (no json)?
URLSession.shared.dataTask(with: URL(string: "http://example.com/weather.php")! ) {(data, response, error) in
guard let data = data else { return }
do {
let res = try JSONDecoder().decode(CurrencyJSON.self, from: data)
dig=res.temp
print ("\(dig)")
} catch let error {
print("\(error)")
}
}.resume()
return dig
}
}
在小部件上我看到“0”(来自:var dig:String =“0”),为什么?我在哪里犯错?
这是我的 struct Provider:TimelineProvider:
struct Provider: TimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), myString: "...")
}
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date(), myString: "...")
completion(entry)
}
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
var entries: [SimpleEntry] = []
print ("1")
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .second, value: hourOffset * 10, to: currentDate)!
let entry = SimpleEntry(date: entryDate, myString: DataProvider.getTemp())
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
解决方案
URLSession.shared.dataTask
是异步的,这意味着您需要另一种方式来返回数据。
为此,您可以在getTemp
函数中提供完成处理程序:
static func getTemp(completion: @escaping (String) -> Void) { // add completion, don't return anything
var dig: String = "0"
URLSession.shared.dataTask(with: URL(string: "http://example.com/weather.php")!) { data, response, error in
guard let data = data else { return }
do {
let res = try JSONDecoder().decode(CurrencyJSON.self, from: data)
dig = res.temp
print("\(dig)")
} catch {
print("\(error)")
}
completion(dig) // pass the value to the completion handler
}.resume()
// return dig // don't return here
}
如您所见,该getTimeline
函数还有一个完成处理程序 - 这允许您在那里执行异步函数:
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
DataProvider.getTemp { myString in
var entries: [SimpleEntry] = []
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .second, value: hourOffset * 10, to: currentDate)!
let entry = SimpleEntry(date: entryDate, myString: myString)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
推荐阅读
- .net - .Net Framework 3.5 和 .Net Framework 3.5 SP1 有相同的版本号吗?
- vue.js - 按下浏览器后退按钮时如何防止Vuejs滚动到页面顶部
- sql-server - 如何通过 Internet 将数据从 SQL Server 数据库迁移到另一个数据库
- c++ - Qt MainWindow 深色主题
- ios - 由于 Google 移动广告而崩溃:集合在被枚举时发生了变异
- wordpress - Wordpress - 新发布的通知计数
- python - 为数字列表编写自定义求和函数
- javascript - 当我将画布转换为 png 时,有时图像充满黑色
- python - While循环仍在循环
- android - 获取方法返回 No_Value 可选