Keyword:SQLDelight,Native Driver
到24日,在iOS上呈现DB资料
KMMDay24
在昨天让Android可以享受到KMM底下的SQLDelight内容後,今天我们来让iOS也能使用SQLDelight.同样的,在iOS上使用需要比Android多一层的手续,才能让iOS也了解到Coroutine的使用方法.
我们现在来重写iOS(shared)内的NativeViewModel,之前是给网路api的Ktor使用,现在要在里面加入DB的使用,并且修改使用的方式.
//这是Kotlin 在iOSMain底下
class IOSNativeViewModel(
private val onDataState: (List<CAFE>) -> Unit//这个callback由iOS端执行
) : KoinComponent {
private val scope = IOSMainScope(Dispatchers.Main)
private val dataRepository: DataRepository by inject()
init {
observeCafeList()
}
private fun observeCafeList() {
scope.launch {
dataRepository.getCafeFromDb().collect { dataState ->
onDataState(dataState)//藉由callback让iOS也能接受Flow的数据
}
}
}
public fun fetchCafeListFromNewWork(cityName: String = "taipei") {
scope.launch {
val result = async { dataRepository.fetchCafesFromNetwork(cityName) }
dataRepository.insertCafeToDB(result.await())
}
}
fun onDestroy() {
scope.onDestroy()
}
}
然後我们修改原本的iOS专案内的ObserableViewModel,让这个物件的资料元从网路APi改为从DB上来的资料
这边我们是使用callback的方式,让flow在当数据改变时去执行特定的程序码,这边就很简单把的数据存入Published内,然後Published和ObservableObject就会去更新swiftUI的画面元件.记得加入onDestroy的函式,让画面在离开的时候销毁coroutine的scope,避免CoroutineLeak的情况发生
//这边是swift
import Foundation
import shared
class CafeEntityItemViewModel:ObservableObject{
private var viewModel: IOSNativeViewModel? = nil
@Published
var cafes:[CAFE]? = nil
func initData(){
viewModel = IOSNativeViewModel{ [weak self] data in
self?.cafes = data
}
}
func onDestroy(){
viewModel?.onDestroy()
viewModel = nil
}
}
最後在首页的ContentView修改为新的DB物件CAFE而不是原本的CafeResponseItem,并且让View再出现时开始拉取新网路资料,并且先显示DB资料,这样可以提高使用者体验.
//这是SwiftUI
import SwiftUI
import shared
struct ContentView: View {
@ObservedObject var cafeEntityViewModel = CafeEntityItemViewModel()
var cafes: [CAFE]?
var body: some View{
NavigationView {
CafeListContent(cafelist: cafeEntityViewModel.cafes)
.navigationBarTitle(Text("CafeList"), displayMode: .large)
.onAppear(perform: {
self.cafeEntityViewModel.initData()
})
.onDisappear(perform: {
self.cafeEntityViewModel.onDestroy()
})
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct CafeListContent: View{
var cafelist: [CAFE]?
var body : some View {
ZStack{
if let cafes = cafelist {
List(cafes, id: \.id) { cafe in
CafeItemView(cafeItem: cafe)
}
}else{
Text("Empty")
}
}
}
}
struct CafeItemView : View {
var cafeItem: CAFE
var body: some View {
HStack {
VStack(alignment: .leading) {
Text(cafeItem.name!).font(.headline)
Text(cafeItem.id).font(.subheadline)
}
}
}
}
明天开始会写KMM如何进行测试的
-政策框架 最高管理层要求加强资讯安全并通过政策表达他们的保护要求。有效的资讯安全涉及人员、流程和...
延续昨天的会员功能,预设会员资讯栏位只有 Email 和 Password,今天要加上一些栏位让会员...
经营自媒体网站最重要的就是要让文章被看见,有了流量才有信服力,而要曝光文章最快的方法除了购买付费广告...
本节是以 Golang 上游 4b654c0eeca65ffc6588ffd9c99387a7e4...
策略(Strategy) 自定义策略 class SmaCrossCons(ConsStrategy...