这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战
一、模拟数据加载
这里使用本地json文件加载的方式模拟搜索的数据
然后使用SwiftUI的MVVM框架来共享加载的数据。
第一步,创建SearchResult.swift即为MVVM的第一部分M,全称Model,代表数据层。
import Foundation
struct SearchResult: Codable,Identifiable {
var id: Int
var title: String
var author: String
var date: String
var content: String
var like: Int
var comments: Int
}
SearchResult必须实现Codable协议(Protocol),才能再后面进行json字符串和Model的转换。实现Identifiable协议,以便后续遍历数据。
第二步,创建类(class)SearchResultModel.swift,MVVM中的最后一部分VM,全称ViewModel,代表View和Model的管理和映射,数据和数据变更后的通知,都需要ViewModel来做。
class SearchResultModel: ObservableObject {
@Published var results: [SearchResult] = []
}
实现
ObservableObject协议;然后将数据results用@Published注解来修饰。
第三部,加载json文件,转换成Model数据。
class SearchResultModel: ObservableObject {
@Published var results: [SearchResult] = []
init() {
let pathString = Bundle.main.path(forResource: "SearchResult", ofType: "json")
if let path = pathString {
let url = URL(fileURLWithPath: path)
do{
let data = try Data(contentsOf: url)
let decoder = JSONDecoder()
DispatchQueue.main.async {
do {
self.results = try decoder.decode([SearchResult].self, from: data)
} catch {
print("Decode Json Error")
}
}
}catch{
print("Parse Data Error")
}
}
}
}
DispatchQueue.main.async来使加载数据为非主线程的异步操作,避免加载数据时阻断主线程的加载,现象就是加载数据时,页面为白屏。
具体的实现描述可以参考SwiftUI之解析JSON
第四步,实例化ViewModel和在View中使用ViewModel。
实例化
引用
二、自定义Card
先拆分布局
红色的部分拆分为VStack嵌套4个HStack。
VStack{
HStack{} //标题
HStack{} //作者和时间
HStack{} //文章内容
HStack{} //点赞和评论
}
创建一个SearchResultCard.swift实现这个布局逻辑。
自定义Divider
Rectangle().foregroundColor(Color(red: 241/255, green: 241/255, blue: 245/255)).frame(height: 10)
最后遍历
ScrollView{
SearchSortView(sortViewIsExpanded: false)
SearchResultDivider()
ForEach(searchResultModel.results){result in
SearchResultCard(searchResult: result)
SearchResultDivider()
}
}