我正在创建我的第一个 kotlin 多平台项目,我在快速使用 kotlin 流程时遇到了一些困难。我使用 kotlin flow 和 ktor 创建了模型、服务器数据请求作为通用文件、视图模型和我创建为本机的 ui 层。所以,我没有快速开发的经验,除此之外,我在快速视图模型上使用流程时遇到了很多麻烦。在寻找我的问题的答案时,我发现了一个描述为 CommonFlow 的类,它的目的是用作两种语言的通用代码(kotlin、swift,但我遇到了一个错误,让我很少或根本不知道为什么会这样发生了,或者,可能只是我缺乏对 xcode 和 swift 编程的控制:
所以这是 xcode 指出错误的代码部分: Obs: sorry about the image 我想这次可能更具描述性
这就是我从错误中得到的全部
Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffee5928ff8)
我的 iOS 视图模型:
class ProfileViewModel: ObservableObject {
private let repository: ProfileRepository
init(repository: ProfileRepository) {
self.repository = repository
}
@Published var authentication: Authetication = Authetication.unauthenticated(false)
@Published var TokenResponse: ResponseDTO<Token>? = nil
@Published var loading: Bool = false
func authenticate(email: String, password: String) {
DispatchQueue.main.async {
if(self.isValidForm(email: email, password: password)){
self.repository.getTokenCFlow(email: email, password: password).watch{ response in
switch response?.status {
case StatusDTO.success:
self.loading = false
let token: String = response!.data!.accessToken!
SecretStorage().saveToken(token: token)
self.authentication = Authetication.authenticated
break;
case StatusDTO.loading:
self.loading = true
break;
case StatusDTO.error:
print("Ninja request error \(String(describing: response!.error!))}")
break;
default:
break
}
}
}
}
}
private func isValidForm(email: String, password: String) -> Bool {
var invalidFields = [Pair]()
if(!isValidEmail(email)){
invalidFields.append(Pair(first:"email invalido",second: "email invalido"))
}
if(password.isEmpty) {
invalidFields.append(Pair(first:"senha invalida",second: "senha invalida"))
}
if(!invalidFields.isEmpty){
self.authentication = Authetication.invalidAuthentication(invalidFields)
return false
}
return true
}
private func isValidEmail(_ email: String) -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailPred = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
return emailPred.evaluate(with: email)
}
}
class Pair {
let first: String
let second: String
init(first:String, second: String) {
self.first = first
self.second = second
}
}
enum Authetication {
case invalidAuthentication([Pair])
case authenticated
case persistentAuthentication
case unauthenticated(Bool)
case authenticationFailed(String)
}
存储库方法:
override fun getToken(email: String, password: String): Flow<ResponseDTO<Token>> = flow {
emit(ResponseDTO.loading<Token>())
try {
val result = api.getToken(GetTokenBody(email, password))
emit(ResponseDTO.success(result))
} catch (e: Exception) {
emit(ResponseDTO.error<Token>(e))
}
}
@InternalCoroutinesApi
override fun getTokenCFlow(email: String, password: String): CFlow<ResponseDTO<Token>> {
return wrapSwift(getToken(email, password))
}
类 CFLOW:
@InternalCoroutinesApi
class CFlow<T>(private val origin: Flow<T>): Flow<T> by origin {
fun watch(block: (T) -> Unit): Closeable {
val job = Job()
onEach {
block(it)
}.launchIn(CoroutineScope(Dispatchers.Main + job))
return object: Closeable {
override fun close() {
job.cancel()
}
}
}
}
@FlowPreview
@ExperimentalCoroutinesApi
@InternalCoroutinesApi
fun <T> ConflatedBroadcastChannel<T>.wrap(): CFlow<T> = CFlow(asFlow())
@InternalCoroutinesApi
fun <T> Flow<T>.wrap(): CFlow<T> = CFlow(this)
@InternalCoroutinesApi
fun <T> wrapSwift(flow: Flow<T>): CFlow<T> = CFlow(flow)