Open Source UI framework based on SwiftUI syntax and features, adding backwards compatibility.
An overview of supported features can be seen here.
Add Package url: https://github.com/rakutentech/AltSwiftUI
Add the following to your Podfile:
pod 'AltSwiftUI'
The complete source documentation contains functionality covered by AltSwiftUI including its unique features.
AltSwiftUI has some small differences to SwiftUI, where it handles certain features slightly differently and adds some missing features as well.
You can use a AltSwiftUI view hierarchy the same as in SwiftUI with AppDelegate
or SceneDelegate
.
Create a UIHostingController
with a root View
, and add it to the Window
. Even though the names are similar, don't forget you should import AltSwiftUI instead of SwiftUI.
The structure of a View
is very similar to that of SwiftUI, with 2 key differences:
struct ExampleView: View {
var viewStore = ViewValues() // Difference 1
var body: View { // Difference 2
Text("Welcome")
}
}
In order for the library to internally store generic properties of a view, you need to provide a viewStore
property initialized with an empty ViewValues
for each view you create.
To target backwards compatibility, opaque return types (some View
) which is supported from iOS 13 are not used. Instead, explicity return types are used.
State management works the same way as in SwiftUI. When a view declares a property attributed with a property wrapper, it will update the view's body when that property's value changes.
@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
}
}
}
When using Text
without lineLimit
inside a HStack
, make sure that all other elements have their width specified. Failing to do so may introduce undesired layouts.
To work with previews, there are 2 steps that need to be done:
AltPreviewProvider
.#if DEBUG && canImport(SwiftUI)
import protocol SwiftUI.PreviewProvider
import protocol AltSwiftUI.View
struct MyTextPreview : AltPreviewProvider, PreviewProvider {
static var previewView: View {
MyText()
}
}
#endif
Editor > Canvas
is enabled and the current file contains this line: import SwiftUI
. Since AltSwiftUI files won't contain import SwiftUI
, you must go to a file that contains it in order to open the Canvas, and then pin it so that you can use it with AltSwiftUI previews. Adding import SwiftUI
to your file temporally to open the Canvas is also an option.If you end up importing Foundation, either directly or by an umbrella framework, and try to use ObservableObject
or Published
, Xcode will have a hard time solving the ambiguity as Foundation currently also defines these types as typealias.
To solve this, you can either specify the type like AltSwiftUI.ObservableObject
every time you use it, or you can explicitly import these 2 types, which will help resolve the ambiguity:
import Foundation
import protocol AltSwiftUI.ObservableObject
import class AltSwiftUI.Published
class MyClass: ObservableObject {
@Published var property: Bool
}
In AltSwiftUI, certain view modifiers can cause views to update with high performance. Modifiers in this category will indicate it in their function documentation. You can also refer to the list below:
List.contentOffset(_:)
: When the list updates the value of the bindingScrollView.contentOffset(_:)
: When the scroll view updates the value of the bindingDragGesture.onChanged()
.High performance updates won't update children views of List
or ScrollView
types. It's generally recommended for view subhierarchies that you want to modify by high performance updates to be moved to a separate View
while passing the state that causes the update as a Binding
.
There are also a couple of modifiers you can use to alter the default behavior of high performance updates and increase performance gains. For more information see List.ignoreHighPerformance()
, ScrollView.ignoreHighPerformance()
, View.strictHighPerformanceUpdate()
and View.skipHighPerformanceUpdate()
in the documentation.
Some of AltSwiftUI additional features are listed in this section.
In addition to the GeometryReader
view, AltSwiftUI also offers a View.geometryListener(_:)
property. This property records changes in a view's frame and stores it in a binding, which can then be referenced in any part of the hierarchy.
Unlike GeometryReader
, geometryListener
doesn't generate a new view.
@State private var geometryProxy: GeometryProxy = .default
VStack {
Text("Example")
.geometryListener($geometryProxy)
Color.red
.frame(width: geometryProxy.size.width)
}
Interactive pop gesture is also enabled by default for navigation views that have custom left bar button items and regardless if they show the navigation bar or not. To set this behavior to false in all cases, set UIHostingController.isInteractivePopGestureEnabled
to false
.
If you find any issues or ideas of new features/improvements, you can submit an issue in GitHub.
We also welcome you to contribute by submitting a pull request.
For more information, see CONTRIBUTING.
MIT license. You can read the LICENSE for more details.
link |
Stars: 296 |
Last commit: 1 year ago |
.onDisappear
coverage of dismiss flowskeyboardDismissMode
to List and ScrollViewtitle2
and title3
Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics