In this post I'm going to extend the previous post to show how to delegate a button press in a UIView to a UIViewController. The button will simply push another instance of my UIViewController onto stack and is a simple example of a custom delegate method in RubyMotion.
(Click on the link to read my last post about a basic app in RubyMotion)
To start with, my AppDelegate class is exactly the same as before:
class AppDelegate
def window
@window ||= UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
end
def navigation_controller
@navigation_controller ||= UINavigationController.alloc.initWithRootViewController(main_view_controller)
end
def main_view_controller
@main_view_controller ||= MainViewController.alloc.initWithNibName(nil, bundle: nil)
end
def application(application, didFinishLaunchingWithOptions:launchOptions)
window.rootViewController = navigation_controller
window.makeKeyAndVisible
true
end
end
Next I'll show the code for my UIView which I've changed a bit from the last post. There is no longer a UILabel and UIView added as subviews but instead a UIButton:
class MainView < UIView
attr_accessor :delegate
def initWithFrame(frame)
super.tap do
self.backgroundColor = UIColor.whiteColor
addSubview(button)
end
end
def button
@button ||= UIButton.new.tap do |button|
button.setTitle("Say Hello Again", forState: UIControlStateNormal)
button.setTitleColor(UIColor.blueColor, forState: UIControlStateNormal)
button.addTarget(self, action: :delegate_button_press, forControlEvents: UIControlEventTouchUpInside)
button_width = 280
screen_center = UIScreen.mainScreen.bounds.size.width/2
button.frame = [[screen_center - button_width/2, 100], [button_width, 30]]
end
end
def delegate_button_press
if self.delegate.respond_to?("say_hello_again")
self.delegate.say_hello_again
end
end
end
The first thing to notice is that I create getter and setter methods for delegate by using attr_accessor :delegate
. Within the button method I set the method for the action that happens when a button is pressed. delegate_button_press
will check to see if the view controller for this view responds to a method called say_hello_again
and if so then it calls the method. This will make sense when you see the code for the UIViewController:
class MainViewController < UIViewController
def loadView
@main_view = MainView.alloc.initWithFrame(CGRectZero).tap do |view|
view.delegate = self
end
self.view = @main_view
end
def viewDidLoad
self.title = 'Hello'
end
# delegate method
def say_hello_again
main_view_controller = MainViewController.alloc.initWithNibName(nil, bundle: nil)
self.navigationController.pushViewController(main_view_controller, animated: true)
end
end
You can see in the loadView
method that I have set the delegate of the view to be this UIViewController and then you can see where I have declared the say_hello_again
method that the button in the UIView calls.
This is a simple example of how to create a custom delegate method but this is a technique that will be used time and time again so it's really useful to understand how to implement it. Happy delegating!