我正在为 iOS 10+ 构建一个 iOS 应用程序。该应用程序在 Debug 配置中构建良好,但在 Release 中无法编译引用WidgetCenter.
Cannot find WidgetCenter in scope即使我正在导入WidgetKit并可选择嵌入框架,它也会输出错误。
import Foundation
import WidgetKit
class MyWidgetCenter: NSObject {
@available(iOS 14, *)
func reloadTimelines(_ kind: String) {
// this line causes error: cannot find 'WidgetCenter' in scope
WidgetCenter.shared.reloadTimelines(ofKind: kind)
}
@available(iOS 14, *)
func reloadAllTimelines() {
// this line causes error: cannot find 'WidgetCenter' in scope
WidgetCenter.shared.reloadAllTimelines()
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:当我设置Build Active Architecture Only标志时,它在发布配置中为模拟器和我连接的设备(iPhone XR)构建良好。只有在为多个架构构建时,它才无法编译。是否存在WidgetKit我没有考虑的架构限制?
更新:我尝试将时间线上的策略设置为.atEnd,因为只有一个条目。这没有任何区别。我已经尝试在 RSS 解析器文件和 AppDelegate 中运行 WidgetCenterreloadAllTimeLines方法,但它也没有做任何事情。这让我发疯了,我将不得不使用开发人员支持票来解决这个问题。
我正在慢慢为 iOS 14 的某些功能准备好我的应用程序,但不断遇到一个又一个错误,或者(更有可能)我没有正确地做事。我正在尽我所能让小部件更新,但它不会。小部件本身很简单;它显示来自 RSS 提要的最新条目的标题和一些文本。我构建了一个 XMLParser,此代码针对时间线运行:
struct Provider: TimelineProvider {
@State private var rssItems:[RSSItem]?
let feedParser = FeedParser()
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), title:"News", description: "News article here", link: "Http://link", pubDate: "The day it posted")
}
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date(), title:"News", description: "News Article Here", link: "Http://link", pubDate: "The day it posted")
completion(entry)
} …Run Code Online (Sandbox Code Playgroud) 只是想知道是否有一种方法可以在 SwiftUI 的 Text UI 中为 DateStyle comp 应用自定义格式。例如,就像使用 DateFormatter 时一样,只是分钟或秒。我想显示小部件的动态日期,但它只提供有限数量的选项。这是为什么?有人找到解决方法吗?
Apple 在此处详细介绍了显示动态日期:https ://developer.apple.com/documentation/widgetkit/keeping-a-widget-up-to-date
我玩过新的 iOS 14 小部件,除了自动刷新外,似乎工作得几乎很好。我的目标是让我的小部件每午夜刷新一次(因此,每天只刷新一次,当然,如果我的应用程序中发生某些事情,则偶尔刷新一次)。在 XCode 中,我将它设置为每分钟刷新一次,并且似乎工作得相当随机 - 所以它可能在我测试的 10 分钟内刷新一次,但我想,没关系,因为我读到刷新是由 iOS 处理的,所以它可能迟早会出现,但终将到来。
现在,我已经发布了我的应用程序的这个版本,今天早上(早上 8 点左右,午夜过后很长时间)我检查了我的小部件,但今天没有更新。
我的问题,我做错了什么吗?或者它只是还没有那么稳定?
我的时间线只包含一个项目,date: now并且刷新策略设置为.after(nextMidnight)。我也尝试过使用 refresh policy .atEnd,但是由于我在时间轴中只有一项设置为现在,它不会尝试不断刷新吗?我想,.after是更好的方法。
如果它是相关的,它是StaticConfiguration和不是IntentConfiguration(老实说,我仍然需要深入研究这里的区别是什么......)。
代码片段:
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
let now = Date()
let calendar = Calendar.current
var dateComponents = DateComponents()
dateComponents.year = calendar.component(.year, from: now)
dateComponents.month = calendar.component(.month, from: now)
dateComponents.day = calendar.component(.day, from: now) + 1
dateComponents.hour = 0
dateComponents.minute = 0
dateComponents.second …Run Code Online (Sandbox Code Playgroud) 我试图让 SwiftUI 小部件在 @AppStorage 的值发生变化时根据命令进行更新。当我加载模拟器时,小部件会从@AppStorage更新为正确的值,但无论我尝试什么,都不会再次更新。要在小部件中显示新值,需要关闭并重新打开模拟器。
在应用程序中查看:
import SwiftUI
import WidgetKit
struct MessageView: View {
@AppStorage("message", store: UserDefaults(suiteName: "group.com.suiteName"))
var widgetMessage: String = ""
var body: some View {
VStack {
Button(action: {
self.widgetMessage = "new message"
WidgetCenter.shared.reloadAllTimelines()
}, label: { Text("button") })
}
}
}
Run Code Online (Sandbox Code Playgroud)
小部件文件:
import WidgetKit
import SwiftUI
import Intents
struct Provider: IntentTimelineProvider {
@AppStorage("message", store: UserDefaults(suiteName: "group.com.suiteName"))
var widgetMessage: String = ""
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), message: "Have a great day!", configuration: …Run Code Online (Sandbox Code Playgroud) 所以我熟悉测试 SwiftUI 视图,但是当应用程序启动后应用程序中不存在用于小部件的视图时(因为它们仅在小部件中使用),如何测试它们?
此外,小部件功能本身(getTimeline 等)的正确方法是什么?
我对 iOS 编程还很陌生,想了解测试不同 iOS 功能的基础知识。任何指导将不胜感激。
我的基本项目设置:
我正在开发一个带有小部件的新 iOS 应用程序。用 SwiftUI 编写。
我的大部分代码在 Widget 目标和 App 目标之间共享,但我想在两个目标之间进行一些小的样式更改。
有没有办法检查代码是在小部件中还是在应用程序中执行?
我想使用自定义颜色为我的小部件创建渐变颜色。而且我只使用两种颜色时出现问题,结果没有应用一种颜色,而是背景变成绿色!
struct WeatherWidgetMediumView: View {
var gradient: LinearGradient {
LinearGradient(
gradient: Gradient(
colors:
[
Color(red: 96.0/255.0, green: 171.0/255.0, blue: 239.0/255.0),
Color(red: 163.0/255.0, green: 230.0/255.0, blue: 244.0/255.0)
]),
startPoint: .top,
endPoint: .bottom)
}
var body: some View {
GeometryReader { geo in
HStack(alignment: .center) {
Divider().background(Color.black).padding(.vertical, 16.0).opacity(0.1)
}
}
.background(gradient)
}
}
Run Code Online (Sandbox Code Playgroud)
但是如果我再添加一种颜色,它看起来很棒。
struct WeatherWidgetMediumView: View {
let weather: Weather
var gradient: LinearGradient {
LinearGradient(
gradient: Gradient(
colors:
[
Color(red: 96.0/255.0, green: 171.0/255.0, blue: 239.0/255.0),
Color(red: 96.0/255.0, green: 171.0/255.0, blue: 239.0/255.0), …Run Code Online (Sandbox Code Playgroud) 我正在编写一个 HomeKit 应用程序,它可以成功显示应用程序内支持的配件的实时数据。我可以读取单个值 ( HMCharacteristic.readValue) 或使用通知来保持更新 ( HMCharacteristic.enableNotification)。
现在我想实现在用户主屏幕上显示这些数据的小部件。这包括四个步骤:
HMHomeManager并使用户能够选择其中一个以显示在小部件上。IntentTimelineProvider的getTimeline函数内部,我可以再次使用HMHomeManager来检索我想要在小部件上显示的附件(基于存储在 的参数 - 意图中的附件的 UUID getTimeline)configuration。getTimeline功能内,我可以选择显示附件小部件所需的服务和特征HMHomeManager。到目前为止,一切正常。
HMCharacteristic.readValue,回调包含一个错误,说明错误域=HMErrorDomain 代码=80“缺少 API 权利。”
Widget 的 Info.plist 包含“隐私 - HomeKit 使用说明”字段,并且 Target 具有 HomeKit 功能。
经过一番研究,我得出了以下理论:显然整个 WidgetKit API 在后台运行我的代码。而且 HomeKit 似乎不允许从后台上下文进行访问。好吧,它确实允许访问 Homes/Services/Characteristics,但它不允许读取或写入 Characteristics(我想确保应用程序开发人员使用 HomeKit 自动化,并且不要尝试实现由某些后台进程控制的自定义自动化他们的应用程序在 iPhone 上运行)。
我的(简化的)getTimeline代码:
func getTimeline(for configuration: SelectAccessoryIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> …Run Code Online (Sandbox Code Playgroud) 我正在HealthKit我的小部件中使用数据。如果手机被锁定,则无法获取HealthKit数据,除非手机解锁。但是,即使手机被锁定,我的小部件时间线也会尝试更新。
是否有可能以某种方式返回空完成,因此它将保持当前小部件数据不变?
这是我的代码:
struct Provider: IntentTimelineProvider {
private let healthKitService = HealthKitService()
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
let currentDate = Date()
let refreshDate = Calendar.current.date(byAdding: .minute, value: 5, to: currentDate)!
healthKitService.getHeartRate() { data, error in
//Create an empty entry
var entry = SimpleEntry(date: currentDate, configuration: ConfigurationIntent(), data: nil)
//If no errors, set data
if(error == nil) {
entry.data = data
} else {
print(error) //this runs when a …Run Code Online (Sandbox Code Playgroud)