Rob*_*ler 5 ios swift widgetkit swiftui
我正在使用 SwiftUI 创建 iOS 14+ Widget,我面临着非常奇怪的情况。问题是我的小部件中只有一个“完整小部件”图像(也许值得注意的是,它是从互联网下载的,但在显示其已加载并注入时UIImage),该图像正确显示如下:
但过了一段时间,更多的 iPhone 解锁 BOOM 后,我得到了这个:
一些观察:
systemLarge- 图像宽度的相同百分比被裁剪为了方便起见,我创建了导致错误的最小示例:
所以,我有这个EntryView
struct EntryView: View {
var viewModel: EntryViewModel
var body: some View {
Image(uiImage: image)
.resizable()
.scaledToFill()
}
}
Run Code Online (Sandbox Code Playgroud)
用作Widget其自身的内容
struct SomeWidget: Widget {
var body: some WidgetConfiguration {
StaticConfiguration(
kind: xxx,
provider: SomeWidgetTimelineProvider(xxx)
) { item in
view(for: item)
}
.configurationDisplayName(xxx)
.description(xxx)
.supportedFamilies([.systemMedium, .systemLarge])
}
private func view(for item: Item) -> some View {
Group {
switch item {
case .aaa(let xxx):
EntryView(viewModel: xxx)
case .bbb(let xxx):
EntryView(viewModel: xxx)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这Widget是包裹在WidgetBundle
@main
struct SomeWidgets: WidgetBundle {
var body: some Widget {
SomeWidget()
SomeWidget()
}
}
Run Code Online (Sandbox Code Playgroud)
也许我还应该展示负责下载图像的逻辑。Data(contentsOf:)我只使用在后台队列上调用的简单同步方法,然后TimelineProvider在主队列上调用回调:
final class SomeWidgetTimelineProvider: TimelineProvider {
...
func getTimeline(in context: Context, completion: @escaping (Timeline<SomeEntry>) -> Void) {
getSomeModel { model in
prefetchImage(for: model) { result in
switch result {
case .success(let image):
completion(
Timeline(
entries: [.aaa(EntryViewModel(image: image)],
policy: .after(Date() + 30 * 60)
)
)
case .error(let error):
completion(
Timeline(
entries: [.bbb(xxx)],
policy: .after(Date() + 30 * 60)
)
)
}
}
}
}
private func prefetchImage(for model: SomeModel, completion: @escaping (Result<UIImage, Error>) -> Void) {
DispatchQueue.global(qos: .background).async {
guard
let imageURL = URL(string: model.imageUrl),
let data = try? Data(contentsOf: imageURL)
else {
DispatchQueue.main.async {
completion(.failure(xxx))
}
}
let image = UIImage(data: data)
DispatchQueue.main.async {
completion(.success(image))
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,我的布局或获取逻辑有问题吗?我缺少什么?
感谢您的任何帮助!
有几个问题是可能的。
问题通常源于您的小部件的图像分辨率。图像的分辨率(以像素为单位)必须与 Widget 的分辨率(以点为单位)相关。在下面的数据透视表中,您可以看到某些 iPhone 型号使用的分辨率(以点 (pts) 为单位)。点与像素不同,因为它们根据 PPI 改变大小。当分辨率为 时,1 点等于 1 像素163 PPI。Retina 时代之前的所有 iPhone 都是如此。然而今天,460 PPIiPhone 12 Pro 的 1 点等于横向 3 个像素、向下 3 个像素,即总共 9 个像素。
因此,对于 iPhone 13 Pro Max,中型小组件的图像大小不应超过 1092 x 510 像素(72 像素/英寸)。将 4K 源图像用于 iOS Widget 是非常不合适的。
| 模型 | 屏幕尺寸(磅) | 小部件(分) | 中等小部件(分) | 大部件(分) |
|---|---|---|---|---|
| iPhone 13 Pro 最大 | 428×926 | 170×170 | 364×170 | 364×382 |
| iPhone 11 | 414×896 | 169×169 | 360×169 | 360×379 |
| iPhone 8 Plus | 414×736 | 159×159 | 348×157 | 348×357 |
| iPhone 12 专业版 | 390×844 | 158×158 | 338×158 | 338×354 |
| iPhone X | 375×812 | 155×155 | 329×155 | 329×345 |
| iPhone 7 | 375×667 | 148×148 | 321×148 | 321×324 |
| iPhone SE | 320×568 | 141×141 | 292×141 | 292×311 |
小部件图像必须为 8 位.png格式。图像可以包含 Alpha 通道,但不应包含任何透明区域(即 Alpha 通道应为 100% 白色)。
使用最高优先级的服务质量,即.userInteractive情况:
DispatchQueue.global(qos: .userInteractive).async { ... }
Run Code Online (Sandbox Code Playgroud)
尝试使用不同的.png. 您从互联网下载的映像很可能已损坏或损坏。图像可能因传输中断、恶意软件/病毒感染、SSD 坏块等而损坏。
有时,如果您发现功能不正常、索引编制或速度缓慢,则必须删除/清理构建。如果是这样,请从文件夹中删除项目的构建~/Library/Developer/。接下来,在 Xcode 中,在导航器面板中选择项目的图标,然后按Command- Shift-K快捷键来清理构建。
然后,关闭 Xcode,进入~/Library/Developer/Xcode/DerivedData/ModuleCache目录并删除缓存。
在 Xcode 14 的发行版上运行您的项目。不要使用测试版。
| 归档时间: |
|
| 查看次数: |
1753 次 |
| 最近记录: |