Skip to content

Instantly share code, notes, and snippets.

@LinusU
Last active March 6, 2018 15:38
Show Gist options
  • Save LinusU/a733c27de2a9df1db898e44f8e1b45da to your computer and use it in GitHub Desktop.
Save LinusU/a733c27de2a9df1db898e44f8e1b45da to your computer and use it in GitHub Desktop.
React like renderer concept for Swift
import UIKit
import PlaygroundSupport
/**********************************************
* Library Types *
**********************************************/
typealias REProps = [String: Any]
class REComponent {
var children: [REComponent]
var props: REProps
var state: Any?
required init(_ props: REProps, _ children: [REComponent] = []) {
self.props = props
self.children = children
self.state = nil
}
func render() -> REComponent? { return nil }
func toNativeView() -> UIView? { return nil }
}
/**********************************************
* Built-in components *
**********************************************/
class RELabel: REComponent {
override func toNativeView() -> UIView? {
let view = UILabel()
if props["backgroundColor"] != nil {
view.backgroundColor = (props["backgroundColor"] as! UIColor)
}
if props["text"] != nil {
view.text = (props["text"] as! String)
}
if props["textColor"] != nil {
view.textColor = (props["textColor"] as! UIColor)
}
return view
}
}
class REStack: REComponent {
override func toNativeView() -> UIView? {
let view = UIStackView()
view.frame = CGRect(x: 0, y: 0, width: 200, height: 200)
if props["alignment"] != nil {
view.alignment = (props["alignment"] as! UIStackViewAlignment)
}
if props["axis"] != nil {
view.axis = (props["axis"] as! UILayoutConstraintAxis)
}
if props["distribution"] != nil {
view.distribution = (props["distribution"] as! UIStackViewDistribution)
}
for child in children {
RE_render(node: child, toTargetView: view)
}
return view
}
}
/**********************************************
* Rendering function *
**********************************************/
func RE_render(node: REComponent, toTargetView targetView: UIView) {
if let view = node.toNativeView() {
if let stackedView = targetView as? UIStackView {
stackedView.addArrangedSubview(view)
} else {
targetView.addSubview(view)
}
return
}
if let child = node.render() {
RE_render(node: child, toTargetView: targetView)
return
}
}
/**********************************************
* User code *
**********************************************/
class MyViewController : UIViewController {
override func loadView() {
let view = UIView()
view.backgroundColor = .white
let tree = REStack(["alignment": UIStackViewAlignment.center], [
RELabel(["backgroundColor": UIColor.cyan, "text": "Hello:"]),
RELabel(["textColor": UIColor.blue, "text": "World!"])
])
RE_render(node: tree, toTargetView: view)
self.view = view
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment