ios - 如何将 Kotlin 中的抽象片段复制到 Swift 中的视图控制器
问题描述
我正在实现现有 Kotlin Android 应用的 iOS 版本。我正在重现的特定功能是分步向导工作流程。
我是如何在 Android 中做到的
在 Android 中,我使用的库有以下过程:
- 向根活动添加“步进器”视图,并
StepAdapter
为此视图提供 - 控制步骤的
StepAdapter
数量,并根据索引的请求返回每个步骤。 - 每个步骤都是一个
Fragment
实现Step
接口,该接口为验证和步骤之间的转换提供挂钩。
我最终创建了一个Fragment
为方法提供默认实现的抽象类型Step
:
abstract class StepFragment(private val index: Int) : Fragment(), Step {
...overriding some methods from Fragment
...implementing methods from Step
}
每一步都Fragment
继承这个类,将硬编码传递给index
'StepFragment
的构造函数。这些步骤可能会覆盖 中的一些方法StepFragment
,其中一些也调用超类的实现(我使用@CallSuper
注释来促进这一点)。实例化并返回这些片段中的StepAdapter
每一个。
我如何尝试在 iOS 中做到这一点
回到 iOS/Swift 世界,我发现了一个类似的库,但它提供的只是进度条的视图。它不像 Android 那样处理实例化和显示每个步骤的内容。我需要自己处理。
但是,您可以为步进器提供一个委托,允许您连接到转换(willSelectIndex、didSelectIndex、canSelectIndex 等)。我将根ViewController
设置为步进器的代表。这ViewController
在顶部有进度条视图,在进度条下方有一个用于每个步骤的容器。每个步骤ViewController
都嵌入到相应的容器中。为了控制步骤之间的转换,我简单地显示和隐藏这些容器视图。我已经弄清楚了那部分。
我没有想到的是如何将StepFragment
类从 Android复制Fragment
到 SwiftViewController
中。我有以下问题:
- Swift 没有抽象类(出于某种原因)。
- 我没有实例化步骤
ViewController
s;由情节提要在内部处理。这意味着我不能像在 Android 中那样在构造函数中提供步骤索引。抽象属性是解决这个问题的典型方法,但是(见上文)Swift 没有抽象类。
我可以通过以下几种方式解决这些问题:
- 我可以使用协议而不是抽象类。我可以指定所有符合协议的类都必须是
ViewController
s 的要求,但我不能覆盖ViewController
协议中的方法(据我所知)。我可以向协议添加一个扩展,以提供具有默认实现的函数,然后实现者可以覆盖这些函数,他们甚至可以调用原始函数(使用(self as Protocol).func()
)。但是,这感觉非常笨拙。 - 我可以使用常规类代替抽象类。我可以在这里实现我想要的一切,除了我不能强制子类在编译时实现抽象成员。我需要
fatalError()
在基类中使用类似的东西,它只在运行时抛出。这也让人感觉很笨拙。 - 我不断听到“委托”模式,我认为这是一种以“Swifty”方式解决许多问题的优雅方式,但我不知道如何在这里使用它。我想我更愿意以这种方式而不是上述两种方式来做到这一点。
TL;博士
总结一下我的问题,我正在寻找一种方法让多个“步骤” childViewController
连接到由 parent 控制的向导工作流程中ViewController
。他们应该能够在步骤选择、转换之前甚至块转换上执行一些(可能是异步的)逻辑。我必须能够选择性地忽略其中一些钩子,然后它们应该使用默认实现。
解决方案
我发现您实际上可以为协议功能提供默认实现,所以这是我的解决方案:
protocol StepViewController: UIViewController {
var stepIndex: Int { get }
func onBackClicked(_ goToPreviousStep: () -> Void)
...
}
extension StepViewController {
// this is a default implementation, so implementors don't have to provide it
func onBackClicked(_ goToPreviousStep: () -> Void) {
goToPreviousStep()
}
...
}
class StepOneViewController: UIViewController, StepViewController {
let stepIndex: Int = 0
func onBackClicked(_ goToPreviousStep: () -> Void) {
// if I want to call the default implementation I can do this:
(self as StepViewController).onBackClicked(goToPreviousStep)
}
}
推荐阅读
- r - id被分配给多个类别如何删除行所以id在r中只有一个类别
- laravel - 筛选选择字段中的值
- database - CodeIgniter - 基于数据库中的变量显示视图
- java - Spring Boot 和 Thymeleaf 在字段错误时返回 400 错误
- docker - 在 Docker-Compose 上运行的应用程序在 k8s 上无法运行
- typescript - 带有 TypeScript 数组 .push 的 VueX 不是函数
- git - 存储库的 Git Push 可访问性错误
- javascript - React Infinite Scroll - Intersection Observer API 总是跳回顶部
- python - Boost.python 空指针函数
- xcode - 升级到 Cordova ios6 会导致项目的 xcode 出现错误