在SwiftData使用过程中,通过使用测试数据快速预览视图。下面将讲述如何使用静态数据预览SwiftData数据。
下面是一个SwiftData文件代码:
import SwiftUI
import SwiftData
import MapKit
@Model
class Place {
@Attribute(.unique) var name: String
var latitude: Double
var longitude: Double
var interested: Bool
var location: CLLocationCoordinate2D {
CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}
var image: Image {
Image(name.lowercased().replacingOccurrences(of: " ", with: ""))
}
init(name: String, latitude: Double, longitude: Double, interested: Bool) {
self.name = name
self.latitude = latitude
self.longitude = longitude
self.interested = interested
}
}
静态数据
创建两个静态变量,一个管理实例的数组,另一个则提供一个预览的ModelContainer,利用数组的轮训将实例插入到该ModelContainer中。
在视图文件中,绑定该ModelContainer,从而实现对于测试数据的预览。
1、previewPlaces
在SwiftData文件中新增静态数据previewPlaces变量:
static var previewPlaces: [Place] {
[
Place(name: "Bellagio", latitude: 36.1129, longitude: -115.1765, interested: true),
Place(name: "Paris", latitude: 36.1125, longitude: -115.1707, interested: true),
Place(name: "Treasure Island", latitude: 36.1247, longitude: -115.1721, interested: true)
]
}
作用: 提供一个数组,包含一些示例 Place 数据,用于在开发和预览时使用。
内容: 包含多个 Place 实例,每个实例具有特定的名称、经纬度、以及是否感兴趣 (interested) 的属性值。
用途: 开发者可以在 UI 预览中使用这些静态数据来快速测试和查看视图的布局和功能,而无需连接到实际的数据源。
2、preview
创建一个临时的ModelContainer容器:
@MainActor
static var preview: ModelContainer {
let container = try! ModelContainer(for: Place.self, configurations: ModelConfiguration(isStoredInMemoryOnly: true))
for place in previewPlaces {
container.mainContext.insert(place)
}
return container
}
作用: 提供一个 ModelContainer 实例,并将 previewPlaces 数据插入其中,用于 SwiftUI 的预览功能。
内容:
创建一个只存储在内存中的 ModelContainer。
将 previewPlaces 数据插入到容器的 mainContext 中。
用途: 让开发者可以在视图预览中使用 SwiftData 的功能,模拟真实的数据存储和查询。
两者的关系
1、previewPlaces 是一个简单的静态数据数组,用来模拟实际的 Place 数据。
2、priview 利用 previewPlaces 数据,创建了一个完整的 ModelContainer,以支持更复杂的预览场景(如使用 SwiftData 的查询和存储功能)。
实际应用
在View中,通过给#Preview的View绑定modelContainer,实现通过静态数据预览视图。
import SwiftUI
import SwiftData
struct PlaceList: View {
@Query(sort:\Place.name) private var places: [Place]
var body: some View {
List(places) { place in
place.image
.resizable()
}
}
}
#Preview {
PlaceList()
.modelContainer(Place.preview)
}
注意,这里的modelContainer后面直接使用Place.preview,而不是使用modelContainer(for:)绑定容器。
最后,实际的预览效果为:
相关文章
1、iOS 18, SwiftUI 6, & Swift 6: 从零开始构建iOS应用程序, 涵盖visionOS, macOS, watchOS:https://www.bilibili.com/video/BV1b6421f7Px?spm_id_from=333.788.player.switch&vd_source=f21219cb93118beac6a36b0ef961df6a&p=7
2、SwiftData预览报错问题:https://fangjunyu.com/2024/11/04/swiftdata-%e9%a2%84%e8%a7%88%e6%8a%a5%e9%94%99%e9%97%ae%e9%a2%98/
完整代码
PlaceList视图
import SwiftUI
import SwiftData
struct PlaceList: View {
@Query(sort:\Place.name) private var places: [Place]
var body: some View {
List(places) { place in
place.image
.resizable()
}
}
}
#Preview {
PlaceList()
.modelContainer(Place.preview)
}
Place文件
import SwiftUI
import SwiftData
import MapKit
@Model
class Place {
@Attribute(.unique) var name: String
var latitude: Double
var longitude: Double
var interested: Bool
var location: CLLocationCoordinate2D {
CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}
var image: Image {
Image(name.lowercased().replacingOccurrences(of: " ", with: ""))
}
init(name: String, latitude: Double, longitude: Double, interested: Bool) {
self.name = name
self.latitude = latitude
self.longitude = longitude
self.interested = interested
}
@MainActor
static var preview: ModelContainer {
let container = try! ModelContainer(for: Place.self, configurations: ModelConfiguration(isStoredInMemoryOnly: true))
for place in previewPlaces {
container.mainContext.insert(place)
}
return container
}
static var previewPlaces: [Place] {
[
Place(name: "Bellagio", latitude: 36.1129, longitude: -115.1765, interested: true),
Place(name: "Paris", latitude: 36.1125, longitude: -115.1707, interested: true),
Place(name: "Treasure Island", latitude: 36.1247, longitude: -115.1721, interested: true),
Place(name: "Stratosphere", latitude: 36.1475, longitude: -115.1566, interested: true),
Place(name: "Luxor", latitude: 36.0955, longitude: -115.1761, interested: true),
Place(name: "Excalibur", latitude: 36.0988, longitude: -115.1754, interested: true)
]
}
}