Skip to content

Instantly share code, notes, and snippets.

@hurshagrawal
Last active August 29, 2015 14:02
Show Gist options
  • Save hurshagrawal/8bfb5c4a80b17fa1de9d to your computer and use it in GitHub Desktop.
Save hurshagrawal/8bfb5c4a80b17fa1de9d to your computer and use it in GitHub Desktop.
This is a super v0.1 of what I think a new UI API may look like.
// Benefits:
// - UI is nested, making it easy to tell what contains what UI elements
// - All UI is *one file* - no need to hunt down other files/locations (UITableViewCells, for example).
// This is a huge boon to productivity. Going back to edit this means I only have to look in one place.
// - All event handling info is inline with the UI, making it easy to tell what is interacting how.
// (Not very different from current target:action: methods, tbh)
// - Styling and layout is separated out, and styling allows for inheritence to keep it DRY
// - All UI and styling is declarative (as much as possible), so there's no "order" of doing things, reducing complexity.
// Cons:
// - Kind of lose out on the type system by using these strings to refer to everything.
// There must be some way to make the compiler smarter about this stuff (obviously outside the scope of a library),
// or some better solution that still allows you to typecheck everything.
let alert = UIView.addView(UIView, name: "alertView", events: nil) { alertView in
alertView.addView(UIView, name: "titleBar", events: nil) { titleBar in
// Events are inline with view declarations somehow
titleBar.addButtonWithName("doneButton", text: "Done", events: [
UIControlEventTouchUpInside: { button in // Not sure if you can add blocks to dictionaries in swift
alertView.hidden = true
}])
titleBar.addLabelWithName("titleLabel", text: "Welcome")
}
alertView.addTableViewWithName("tableView", numberOfRows:{ section in section == 0 ? 5 : 2 }) { tableView, indexPath in
if indexPath.row == 0 {
// The tableView looks for cells named "personCell" that may have already been initialized and can be reused.
// If so, reuses them, skips the initialize block, and only runs the configure.
// Note: this means we don't need a separate class at all, and avoid having to write + maintain a lot of boilerplate
tableView.addCellWithName("personCell", initialize: {
return UITableViewCell().addView(UIView, name: "cellView", events: nil) { cellView in
cellView.addLabelWithName("nameLabel", text: nil)
cellView.addLabelWithName("profileLabel", text: nil)
}
}, configure: { cell in
cell.get("nameLabel").text = self.users[indexPath.row].name
cell.get("profileLabel").text = self.users[indexPath.row].profileText
}
}
}
}
// Styling and UI look and feel code is compartmentalized and allows you to inherit
alertView.styleButton("button") { button in
button.backgroundColor = UIColor.blackColor
button.textColor = UIColor.whiteColor
button.layer.cornerRadius = 5.0
}
alertView.styleButton("doneButton", inheritsFrom: "button") { button in
button.backgroundColor = UIColor.blueColor
}
// Since we already named all views, getting a dictionary of named subviews is easy
alertView.addConstraintsForName("titleBar", visualConstraints: [
"H:|-[titleLabel]-[doneButton]-|"
"V:|-[titleLabel]-|",
"V:|-[doneButton]-|",
], metrics:0 views: alertView.subviewsDictionary())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment