{"id":1845,"url":"https://github.com/alexdrone/Render","last_synced_at":"2025-08-02T04:32:39.704Z","repository":{"id":52241540,"uuid":"56135227","full_name":"alexdrone/Render","owner":"alexdrone","description":"UIKit a-là SwiftUI.framework [min deployment target iOS10]","archived":false,"fork":false,"pushed_at":"2019-12-13T14:45:11.000Z","size":913699,"stargazers_count":2164,"open_issues_count":3,"forks_count":96,"subscribers_count":36,"default_branch":"master","last_synced_at":"2025-07-27T22:50:36.901Z","etag":null,"topics":["elm-architecture","ios","layout-engine","reconciliation","swift","swiftui","uikit","uiview","unidirectional-data-flow","virtual-dom"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexdrone.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-04-13T08:39:19.000Z","updated_at":"2025-06-24T09:49:51.000Z","dependencies_parsed_at":"2022-08-30T18:11:45.363Z","dependency_job_id":null,"html_url":"https://github.com/alexdrone/Render","commit_stats":null,"previous_names":[],"tags_count":60,"template":false,"template_full_name":null,"purl":"pkg:github/alexdrone/Render","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexdrone%2FRender","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexdrone%2FRender/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexdrone%2FRender/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexdrone%2FRender/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexdrone","download_url":"https://codeload.github.com/alexdrone/Render/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexdrone%2FRender/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268126092,"owners_count":24200286,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-31T02:00:08.723Z","response_time":66,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elm-architecture","ios","layout-engine","reconciliation","swift","swiftui","uikit","uiview","unidirectional-data-flow","virtual-dom"],"created_at":"2024-01-05T20:15:57.157Z","updated_at":"2025-08-02T04:32:39.375Z","avatar_url":"https://github.com/alexdrone.png","language":"Swift","funding_links":[],"categories":["Reactive Programming","Swift","Uncategorized","virtual-dom"],"sub_categories":["React-Like","Other free courses","Uncategorized"],"readme":"# Render [![Swift](https://img.shields.io/badge/swift-5.1-orange.svg?style=flat)](#) [![ObjC++](https://img.shields.io/badge/ObjC++-blue.svg?style=flat)](#) [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://opensource.org/licenses/MIT)\n\n\u003cimg src=\"docs/assets/logo.png\" width=150 alt=\"Render\" align=right /\u003e\n\nCoreRender is a SwiftUI inspired API for UIKit (that is compatible with iOS 10+ and ObjC).\n\n\n### Introduction\n\n* **Declarative:** CoreRender uses a declarative API to define UI components. You simply describe the layout for your UI based on a set of inputs and the framework takes care of the rest (*diff* and *reconciliation* from virtual view hierarchy to the actual one under the hood).\n* **Flexbox layout:** CoreRender includes the robust and battle-tested Facebook's [Yoga](https://facebook.github.io/yoga/) as default layout engine.\n* **Fine-grained recycling:** Any component such as a text or image can be recycled and reused anywhere in the UI.\n\n### TL;DR\n\nLet's build the classic *Counter-Example*.\n\nThe DSL to define the vdom representation is similiar to SwiftUI.\n\n```swift\nfunc makeCounterBodyFragment(context: Context, coordinator: CounterCoordinator) -\u003e OpaqueNodeBuilder {\n  Component\u003cCounterCoordinator\u003e(context: context) { context, coordinator in\n    VStackNode {\n      LabelNode(text: \"\\(coordinator.count)\")\n        .textColor(.darkText)\n        .background(.secondarySystemBackground)\n        .width(Const.size + 8 * CGFloat(coordinator.count))\n        .height(Const.size)\n        .margin(Const.margin)\n        .cornerRadius(Const.cornerRadius)\n      HStackNode {\n        ButtonNode()\n          .text(\"TAP HERE TO INCREASE COUNT\")\n          .setTarget(coordinator, action: #selector(CounterCoordinator.increase), for: .touchUpInside)\n          .background(.systemTeal)\n          .padding(Const.margin * 2)\n          .cornerRadius(Const.cornerRadius)\n      }\n    }\n    .alignItems(.center)\n    .matchHostingViewWidth(withMargin: 0)\n  }\n}\n```\n\n\u003cimg src=\"docs/assets/screen_2.png\" width=320 alt=\"screen\" /\u003e\n\n`Label` and `Button` are just specialized versions of the `Node\u003cV: UIView\u003e` pure function.\nThat means you could wrap any UIView subclass in a vdom node. e.g.\n```swift\n\nNode(UIScrollView.self) {\n  Node(UILabel.self).withLayoutSpec { spec in \n    // This is where you can have all sort of custom view configuration.\n  }\n  Node(UISwitch.self)\n}\n\n```\nThe `withLayoutSpec` modifier allows to specify a custom configuration closure for your view.\n\n `Coordinators`  are the only non-transient objects in CoreRender. They yeld the view internal state and \n they are able to manually access to the concrete view hierarchy (if one desires to do so).\n \n By calling  `setNeedsReconcile`  the vdom is being recomputed and reconciled against the concrete view hiearchy.\n\n```swift\nclass CounterCoordinator: Coordinator{\n  var count: UInt = 0\n\n  func incrementCounter() {\n    self.count += 1                      // Update the state.\n    setNeedsReconcile()                  // Trigger the reconciliation algorithm on the view hiearchy associated to this coordinator.\n  }\n}\n```\n\nFinally,  `Components` are yet again transient value types that bind together a body fragment with a\ngiven coordinator.\n\n```swift\nclass CounterViewCoordinator: UIViewController {\n  var hostingView: HostingView!\n  let context = Context()\n\n  override func loadView() {\n    hostingView = HostingView(context: context, with: [.useSafeAreaInsets]) { context in\n      makeCounterBodyFragment(context: context, coordinator: coordinator)\n    }\n    self.view = hostingView\n  }\n    \n  override func viewDidLayoutSubviews() {\n    hostingView.setNeedsLayout()\n  }\n}\n```\n\nComponents can be nested in the node hierarchy.\n\n```swift\n\nfunc makeFragment(context: Context) {\n  Component\u003cFooCoordinator\u003e(context: context) { context, coordinator in\n    VStackNode {\n      LabelNode(text: \"Foo\")\n      Component\u003cBarCoordinator\u003e(context: context) { context, coordinator in\n        HStackNode {\n          LabelNode(text: \"Bar\")\n          LabelNode(text: \"Baz\")\n        }\n      }\n    }\n  }\n}\n\n```\n\n### Use it with SwiftUI\n\nRender nodes can be nested inside SwiftUI bodies by using `CoreRenderBridgeView`:\n```swift\n\nstruct ContentView: View {\n  var body: some View {\n    VStack {\n      Text(\"Hello From SwiftUI\")\n      CoreRenderBridgeView { context in\n        VStackNode {\n          LabelNode(text: \"Hello\")\n          LabelNode(text: \"From\")\n          LabelNode(text: \"CoreRender\")\n        }\n          .alignItems(.center)\n          .background(UIColor.systemGroupedBackground)\n          .matchHostingViewWidth(withMargin: 0)\n      }\n      Text(\"Back to SwiftUI\")\n    }\n  }\n}\n\nstruct ContentView_Previews: PreviewProvider {\n  static var previews: some View {\n    ContentView()\n  }\n}\n\n```\n\n# Credits:\nLayout engine:\n\n* [facebook/yoga](https://github.com/facebook/yoga)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexdrone%2FRender","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexdrone%2FRender","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexdrone%2FRender/lists"}