SwiftUI实战-仿写掘金APP(二)

848 阅读2分钟

这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战

一、模拟数据加载

image.png

这里使用本地json文件加载的方式模拟搜索的数据

然后使用SwiftUIMVVM框架来共享加载的数据。

第一步,创建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.swiftMVVM中的最后一部分VM,全称ViewModel,代表ViewModel的管理和映射,数据和数据变更后的通知,都需要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

实例化

image.png

引用

image.png

二、自定义Card

image.png

先拆分布局

image.png

红色的部分拆分为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()
    }
    
}

最终效果

image.png

附录

代码地址