Keyword: Koin,AppDelegate
今天完成的内容,在iOS上使用Koin 放在这边
KMMDay21
有个好消息,原来KMM编译过程中有用到一个物件,在新版本的Xcode後也换成另外版本了,因此KMM的编译过程中找不到.不过在Kotlin的新版本中已经改用另外一版本了,只是目前这个版本的Kotlin还没到Stable版本,所以需要使用early-access版本的.(官方表示在1.5.31版本修正了这个问题)
如何更换Kotlin成为early-access版本呢?就在上方的Tools ⇒ Kotlin ⇒Configure Kotlin Plugin Updates
在里面可以选择使用的Kotlin版本,这边我们换成1.5版本的Early Access Preview 1.5.x 版本的Kotlin
然後让他下载新版本的Kotlin就可以啦
此外官方讨论区也有人提到必须要升级Gradle版本到7.2版之後,我也有遇到同样的情况.那调整Gradle版本的位置就在工具列中,
其中的
点开後把下面的gradle版本调整成7.2 之後同步即可.
虽然标题这麽说,但是Koin是给Kotlin专用的,实际上是不能运行在swift或是Object-C版本的.好在我们前几天已经把ViewModel的部分下放到了iosMain之中,也就是说,现在iOS专案内除了负责显示的swiftUI,其他部分都是由KMM的Kotlin部分代劳,而这部分,就能使用Koin注入所需要的物件.
所以:虽然Koin不能运行在显示层,但是其他部分,商业逻辑与资料层都能够进行依赖注入.画面层则是直接呼叫这些Koin所管理的物件,也能进行一定程度的解耦.
首先,我们会用到一个为KMM特制的第三方库进行资料的储存库,会根据平台不同而使用不同的实作方式,来源是:
同样的,我们在BuildSrc的依赖管理区域,加入这个第三方库.来管理他的版本
object Version{
...
val multiplatformSettings = "0.7.7"
}
object Develop{
val multiplatformSettings = "com.russhwolf:multiplatform-settings:${Versions.multiplatformSettings}"
val multiplatformSettingsTest = "com.russhwolf:multiplatform-settings-test:${Versions.multiplatformSettings}"
}
然後在gradle(shared)中加入使用,记得同步Gradle让其加入专案之中.
sourceSets["commonMain"].dependencies {
implementation(Develop.multiplatformSettings)
}
sourceSets["commonTest"].dependencies {
implementation(Develop.multiplatformSettingsTest)
}
在shared内的iosMain建立起一个档案KoinForIOS.kt,这个档案会给iOS的App呼叫,里面写一个Koin启动时所必要的Function,前几天Android的版本可以直接呼叫我们放在commonMain内的Koin.kt,但是iOS需要过经过一层处理
//这边是Kotlin
fun initKoinIos(
userDefaults: NSUserDefaults,//iOS独有的使用者资讯档案,
doOnStartup: () ->Unit): KoinApplication //初始化结束时会呼叫
= initKoin(//藉由这行,呼叫Koin.kt内的Koin初始化流程
module{//同样建立iOS使用的Module
single<Settings>{AppleSettings(userDefaults)}
single { doOnStartup }
}
)
这样,只要iOS呼叫了这个Function,就能初始化Koin.那这个物件会由KMM包装成iOS也能够看懂的物件以供使用.
(之後都是在Xcode内撰写swift)
那我们接下来写呼叫initKoinIos的swift方法.
建立一个swift档案在iOS专案中,我的叫做iOSKoinFunctions,在里面写下Koin初始化的流程
//这是swift
import Foundation
import shared
func startKoin(){
let _userDefaults = UserDefaults(suiteName: "KMMItExample")!
let _doONStartup = {NSLog("Hello from iOS/Swift")}
let koinApplication = KoinForIOSKt.doInitKoinIos(userDefaults: _userDefaults,doOnStartup: _doONStartup)
_koin = koinApplication.koin
}
private var _koin: Koin_coreKoin? = nil
var koin: Koin_coreKoin {
return _koin!
}
这边我们UserDefaults放入了专案的名称,这边可以存放各种资料,如果有其他想放的使用者资讯也能放在这边.
然後让传入一个doOnStartUp让iOS在完成时执行作为Log用途,这边就简单呼叫NSLog印出来吧.
最後就是重点,koinApplication 就是初始化的流程.可以注意到KMM把刚刚的KoinForIOS.kt变成了KoinForIOSKT物件(这个其实是Kotlin里面在档案里撰写方法时的特性),然後initKoinIos变成了doInitKoinIos,经过这层转换,就能够在swift之中使用Kotlin的方法.当然swift还是认swift语法,只是这个swift语法是从Kotlin转换过来的.
接下来我们要在iOS App启动的时候一并启动Koin,而KMM预设范例中的swiftUI目前没有办法做到开始时顺带启动Koin,所以我们要写一个AppDelegate,告诉iOS系统,在App启动时要帮我做这些事.
首先,跟之前建立新的swift档案一样,我们建立一个名为AppDelegate的swift档案,然後照iOS的开发流程,让这个档案继承UIResponder, UIApplicationDelegate,就会变成iOS的入口.
//这边是swift
import Foundation
import UIKit
import SwiftUI
@UIApplicationMain //这个注解代表这是App入口
class AppDelegate: UIResponder, UIApplicationDelegate{
}
建立了之後就能够把原本的iosAPP这个档案砍掉了,我们有了新的入口.
然後我们这边有一个application初始化的流程,我们在其中加入初始化Koin的流程
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate{
func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
startKoin()//刚刚写的startKoin()方法
return true
}
}
最後指定一开始时要显示的画面,完整如下
import Foundation
import UIKit
import SwiftUI
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate{
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
startKoin()
let viewController = UIHostingController(rootView: ContentView())
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()
return true
}
}
按下执行,发现....什麽都没变,跟原本一样.但是其实商业逻辑与资料层已经成为了Koin管理的物件
明天,会进入使用SqlDelight DB来储存资料.
>>: [Day 11]在你顺利的时候来一拳才是标配(前端篇)
1.前言 今天本来要进入函示Part2的,但後来想想这次系列文章面对的是全龄层(普遍级),前面好像也...
可信恢复是“在系统故障後确保恢复而不受影响的能力”。( NIST Glossary )通用标准中指定...
我们来看到C#要如何计算程序码的执行时间呢 ~ 有两种方法分别是 Stopwatch DateTim...
互殴之前当然要先有场地才行,让我们建立 Phaser 场景吧! 建立场景 首先建立 src\comp...