基于 SwiftUI 语法和功能的开源 UI 框架,增加了向下兼容性。
兼容性
- 最低 iOS 版本:iOS 11.0
- SwiftUI:不可互换,但由于语法高度相似,易于相互分享知识和迁移代码。
- UIKit:兼容
- Xcode:从 Xcode 12 开始
- 平台:iOS,iPadOS
特性
支持特性的概述请见此处 Features.md。
安装
Swift 包管理器
添加包 URL: https://github.com/rakutentech/AltSwiftUI
Cocoapods
在您的 Podfile 中添加以下内容
pod 'AltSwiftUI'
文档
完整的源文档包含 AltSwiftUI 所包含的功能,包括其独特的功能。
用法
AltSwiftUI 与 SwiftUI 有一些小的不同,它在处理某些功能时略有不同,并添加了一些缺失的功能。
入门
您可以使用与 SwiftUI 相同的 AltSwiftUI 视图层结构与 AppDelegate
或 SceneDelegate
。
使用根 View
创建一个 UIHostingController
,并将其添加到 Window
。尽管名称相似,但不要忘记您应该导入 AltSwiftUI 而不是 SwiftUI。
视图结构
View
的结构与 SwiftUI 非常相似,有 2 个主要区别。
struct ExampleView: View {
var viewStore = ViewValues() // Difference 1
var body: View { // Difference 2
Text("Welcome")
}
}
-
为了使库能够内部存储视图的泛型属性,对于您创建的每个视图,您需要提供一个初始化为空
ViewValues
的viewStore
属性。 -
为了向后兼容,不使用支持从 iOS 13 开始的不可见返回类型(
some View
)。取而代之的是,显式使用返回类型。
状态和渲染
状态管理在 SwiftUI 中的工作方式相同。当一个视图声明一个使用了属性包装器的属性时,当该属性的值发生变化时,它将更新视图的主体。
@State private var exampleText = "Original text"
@ObservedObject var myModel = MyModel()
var body: View {
VStack {
Text(exampleText)
Text(myModel.value)
Divider()
.padding(.vertical, 10)
MyView($myModel.value) // Will update the view when 'MyView' updates the value
Button("Update text") {
exampleText = "Updated text" // Will update the view on button action
}
}
}
HStack 与多行文本
当在 HStack
内使用没有 lineLimit
的 Text
时,请确保所有其他元素都指定了宽度。否则可能会导致预料之外的布局效果。
预览
要使用预览功能,需要完成以下两个步骤
- 在包含要预览的视图的文件末尾编写预览代码。这与 SwiftUI 类似,但预览还必须遵从
AltPreviewProvider
。
#if DEBUG && canImport(SwiftUI)
import protocol SwiftUI.PreviewProvider
import protocol AltSwiftUI.View
struct MyTextPreview : AltPreviewProvider, PreviewProvider {
static var previewView: View {
MyText()
}
}
#endif
- 加载画布:截至现在(Xcode 12 测试版),为了显示预览画布,Xcode 需要启用
编辑 > 画布
,并且当前文件包含此行:import SwiftUI
。由于 AltSwiftUI 文件不会包含import SwiftUI
,您必须转到包含它的文件以打开画布,然后将其固定以用于 AltSwiftUI 预览。在打开画布时临时将import SwiftUI
添加到您的文件中也是一个选项。
ObservableObject
和 Published
的命名冲突
如果您最终直接或通过聚合框架导入了 Foundation,并尝试使用 ObservableObject
或 Published
,由于 Foundation 目前也将这些类型定义为 typealias,Xcode 将很难解决这种歧义。
为了解决这个问题,每次使用时可以指定类型如 AltSwiftUI.ObservableObject
,或者您可以显式导入这两个类型,这有助于消除歧义。
import Foundation
import protocol AltSwiftUI.ObservableObject
import class AltSwiftUI.Published
class MyClass: ObservableObject {
@Published var property: Bool
}
高性能
在AltSwiftUI中,某些视图修饰符可以使视图以高性能更新。此类修饰符将在其功能文档中表明。您还可以参考以下列表
List.contentOffset(_:)
:当列表更新绑定值时ScrollView.contentOffset(_:)
:当滚动视图更新绑定值时- 发生在
DragGesture.onChanged()
闭包内的状态变化。
高性能更新不会更新List
或ScrollView
类型的子视图。通常建议,如果需要使用高性能更新来修改视图子层次结构,则将其移动到另一个View
中,同时传递造成更新的状态作为绑定
。
还有一些修饰符可以用来改变高性能更新的默认行为并增加性能提升。有关更多信息,请参阅文档中的List.ignoreHighPerformance()
、ScrollView.ignoreHighPerformance()
、View.strictHighPerformanceUpdate()
和View.skipHighPerformanceUpdate()
。
附加功能
本节介绍了AltSwiftUI的一些附加功能。
几何监听器
除了GeometryReader
视图外,AltSwiftUI还提供View.geometryListener(_:)
属性。此属性记录视图的帧变化并将其存储在绑定中,然后可以在层次结构的任何部分引用该绑定。
与GeometryReader
不同,geometryListener
不会生成新的视图。
@State private var geometryProxy: GeometryProxy = .default
VStack {
Text("Example")
.geometryListener($geometryProxy)
Color.red
.frame(width: geometryProxy.size.width)
}
交互式弹出手势
默认情况下,交互式弹出手势也适用于具有自定义左栏按钮项的导航视图,无论它们是否显示导航栏。要将此行为设置为所有情况下的false
,请将UIHostingController.isInteractivePopGestureEnabled
设置为false
。
参与进来
如果您发现任何问题或关于新功能/改进的创意,您可以在GitHub上提交一个问题。
我们也欢迎您通过提交拉取请求来贡献。
了解更多信息,请见 CONTRIBUTING。
许可证
MIT许可证。您可以阅读LICENSE获取更多详细信息。