Last active
March 6, 2018 15:38
-
-
Save LinusU/a733c27de2a9df1db898e44f8e1b45da to your computer and use it in GitHub Desktop.
React like renderer concept for Swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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