Skip to content

Instantly share code, notes, and snippets.

@scizo
Created June 30, 2012 17:27
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save scizo/3024727 to your computer and use it in GitHub Desktop.
Save scizo/3024727 to your computer and use it in GitHub Desktop.
class AppDelegate
def application(application, didFinishLaunchingWithOptions:launchOptions)
@window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
@window.rootViewController = ExampleViewController.alloc.init
@window.makeKeyAndVisible
true
end
end
class ExampleViewController < UIViewController
def init
return self if self.initWithNibName(nil, bundle: nil)
end
def loadView
self.view = ExampleView.alloc.init
end
end
class View < UIView
INITIALIZERS = {
UIView => 'initWithFrame:',
UIImageView => 'initWithImage:',
UISegmentedControl => 'initWithItems:',
}
class << self
def current_views
@current_views ||= []
end
def attributes
@attributes ||= []
end
def view_builders
@view_builders ||= []
end
def subview(klass, *args, &attributes_builder)
options = args.pop if args.last.is_a?(Hash)
options = {} unless options
if current_views.empty?
view_builders << [klass, args, attributes_builder, options]
return
end
build(klass, args, attributes_builder, options)
end
def method_missing(name, *args)
method = "set#{camelize(name)}:"
if current_views.empty?
attributes.push [method, args.first]
return
end
view = current_views.last
super unless view.respond_to?(method)
puts "::: Performing #{method} with #{args.first.inspect} on #{view.inspect}"
# I would rather use send, but it crashes
view.performSelectorOnMainThread(method, withObject: args.first, waitUntilDone: true)
end
private
def build(klass, args, attributes_builder, options)
args = args.map{ |arg| arg.respond_to?(:call) ? arg.call : arg }
view = klass.alloc.send(INITIALIZERS[klass], *args)
current_views << view
attributes_builder.call if attributes_builder
current_views.pop
root_view, last_view = current_views.first, current_views.last
root_view.views[options[:name]] = view if options[:name]
last_view.addSubview view
view
end
def camelize(term)
string = term.to_s
string = string.sub(/^[a-z\d]*/) { $&.capitalize }
#string = string.sub(/^(?:(?=a)b(?=\b|[A-Z_])|\w)/) { $&.downcase }
string.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" }
end
end
attr_reader :views
def init
if self.initWithFrame(CGRectZero)
@views = {}
self.class.attributes.each do |(method, arg)|
self.performSelectorOnMainThread(method, withObject: arg, waitUntilDone: true)
end
self.class.current_views << self
self.class.view_builders.each do |builder|
view = self.class.build(*builder)
end
self.class.current_views.pop
end
self
end
end
class ExampleView < View
frame [[0, 0], [320, 460]]
background_color UIColor.redColor
subview UIView, [[10, 10], [300, 440]] do
background_color UIColor.greenColor
subview UIView, [[10, 10], [280, 420]] do
background_color UIColor.blueColor
subview UISegmentedControl, ["Example", "Test"] do
frame [[40, 20], [200, 40]]
tint_color UIColor.blackColor
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment