Create a SwiftUI user interface through a JSON file. The JSON file will contain the structure of the user interface, and the program will create the user interface based on the JSON file.
Warning
This is a work in progress and not yet ready for production use.
Please feel free to contribute, report issues, or request features.
- Swift 5.9+ (Xcode 15+)
- iOS 15+, macOS 12+, tvOS 14+, watchOS 7+, macCatalyst 15+, visionOS 1.0+
Install using Swift Package Manager
dependencies: [
.package(url: "https://github.com/0xWDG/DynamicUI.git", branch: "main"),
],
targets: [
.target(name: "MyTarget", dependencies: [
.product(name: "DynamicUI", package: "DynamicUI"),
]),
]
And import it:
import DynamicUI
import SwiftUI
import DynamicUI
struct ContentView: View {
let json = """
[
{
"type": "Text",
"title": "Wait, am i generating views from JSON?",
"modifiers": {"foregroundStyle":"red","opacity":0.6}
},
{
"type": "Button",
"title": "Click me",
"eventHandler": "customHandler"
},
{
"type": "Toggle",
"title": "Toggle me",
"identifier": "my.toggle.1"
}
]
""".data(using: .utf8)
var body: some View {
DynamicUI(
json: json,
callback: { component in
// This contains everything passed as a component (type, title, identifier, ...)
print(component)
}
)
}
}
In the directory Playground
is a Xcode project to build the Playground Application
Please note: Items prefixed with ⚠ may ignore passed parameters.
Items with a strikethrough are not yet supported.
VStack
{
"type": "VStack",
"children": [ ]
}
HStack
{
"type": "HStack",
"children": [ ]
}
ZStack
{
"type": "ZStack",
"children": [ ]
}
List
{
"type": "List",
"children": [ ]
}
ScrollView
{
"type": "ScrollView",
"children": [ ]
}
NavigationView
{
"type": "NavigationView",
"children": [ ]
}
Form
{
"type": "Form",
"children": [ ]
}
Button
{
"type": "Button",
"title": "Click me!"
}
Text
{
"type": "Text",
"title": "..."
}
Image
{
"type": "Image",
"imageURL": "systemName"
}
Divider
{
"type": "Divider"
}
Spacer
{
"type": "Spacer"
}
Label
{
"type": "Label",
"title": "..."
}
TextField
{
"type": "TextField",
"title": "...",
"defaultValue": "..."
}
SecureField
{
"type": "SecureField",
"title": "...",
"defaultValue": "..."
}
TextEditor
{
"type": "TextEditor",
"title": "...",
"defaultValue": "..."
}
Toggle
{
"type": "Toggle",
"title": "Turn me on!",
"defaultValue": true
}
⚠ Gauge
{
"type": "Gauge",
"title": "...",
"defaultValue": 0.5
}
⚠ ProgressView
{
"type": "ProgressView",
"title": "...",
"value": 50,
"total": 100
}
Slider
{
"type": "Slider",
"title": "...",
"minLabel": "min",
"maxLabel": "max"
}
GroupBox
{
"type": "GroupBox",
"children": [ ]
}
DisclosureGroup
{
"type": "DisclosureGroup",
"children": [ ]
}
HSplitView
{
"type": "HSplitView",
"children": [ ]
}
VSplitView
{
"type": "VSplitView",
"children": [ ]
}
⚠ Picker
{
"type": "Picker",
"title": "...",
"values": ["...", "..."]
}
⚠ NavigationSplitView
{
"type": "NavigationSplitView",
"children": [ ]
}
⚠ TabView
{
"type": "TabView",
"children": [ ]
}
![image](https://private-user-images.githubusercontent.com/1290461/350126255-cfd7ba02-88b1-410d-a6ba-54c9ebee06e0.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzkzNTI5NjMsIm5iZiI6MTczOTM1MjY2MywicGF0aCI6Ii8xMjkwNDYxLzM1MDEyNjI1NS1jZmQ3YmEwMi04OGIxLTQxMGQtYTZiYS01NGM5ZWJlZTA2ZTAucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxMiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTJUMDkzMTAzWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MWEwMTc5MjJhNWI3NzI4NjQ5NTZhYmJlNjkxMmE4ZjAxNTM4M2YxYTQ2YmQ2MzA3NjBkNTQ5ODNkZjcyYTkxYSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.NRZI62E7zKgkfmBEEN-U5mEpJeR16lhqlv8Sjl7OGrE)
![image](https://private-user-images.githubusercontent.com/1290461/322620426-02e2d735-5496-4b68-a428-9e03815bf4d6.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzkzNTI5NjMsIm5iZiI6MTczOTM1MjY2MywicGF0aCI6Ii8xMjkwNDYxLzMyMjYyMDQyNi0wMmUyZDczNS01NDk2LTRiNjgtYTQyOC05ZTAzODE1YmY0ZDYucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxMiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTJUMDkzMTAzWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ODMwMDFhZjY2NWU0OTIwOTY0MzkyOWUwYzRmYWU3YjU4OTAyNTUzMTk0ZTQ5OTc0MzY1Y2QxNGNmMTc1NjY2NSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.k5M4ys3S7XUxPT-iPNvajxwl9uYaS4GpIVhUewruAxo)
- Aurora Editor for custom views in extensions.
We can get in touch via Twitter/X, Discord, Mastodon, Email, Website.