Rubymotion: Chain of Modal segues

While building my iOS application, I had a user registration process to be implemented. This included the user entering his mobile number, his language details and a few other ( say, miscellaneous ) details. Once he has registered himself he is presented with a table view where a few movies in the language he chose are shown.

The way I went about implementing is that I had a masterviewcontroller which is the initial view controller. The other controllers are

  • mobilenumberview_controller
  • languageviewcontroller
  • miscellaneousviewcontroller
  • moviesviewcontroller

I have segues, all of type modal, from the master controller to all other controllers I mentioned above. The segues are of modal type because once the user has submitted each of his details, he doesnt have to care about the particluar detail and is given no option to go back to his previous screen. Its not a like a dig deep type of chain where we could implement the navigation controller. The segues are the follows.

On the left we have the contoller and on the right we have the segue identifier to that controller from the master controller.

master_view_controller:
  mobile_number_view_controller -> msisdnSegue
  language_view_controller -> languageSegue
  miscellaneous_view_controller -> miscellaneousSegue
  movies_view_controller -> moviesSegue

Also, we have this chain of modal segues.

master_view_controller -> mobile_number_view_controller -> language_view_controller -> miscellaneous_view_controller

Now in the viewDidAppear delegate of the master controller, we have this check to present the appropriate controller. The details entered by the user in the registration process are saved( we use motion model to store the details of the user ). Ofcourse, we dont want a user who has entered his mobile number once to enter it again even if he has opted to quit the app after entering the mobile number. Similarly we dont want him to select his language for the second time during the registration process. We consider all this in the viewDidAppear delegate and decide which contoller to load.

master_view_controller.rb ( This obviously can be implemented better :) )

def viewDidAppear(animated)
  super
  perform_criteria_based_segue
end

def perform_criteria_based_segue
  @user = User.first

  if (not @user) or (not @user.verified_mobile_number)
    performSegueWithIdentifier('msisdnSegue', sender: self)
  end

  elsif not @user.language
    performSegueWithIdentifier('languageSegue', sender: self)
  end

  elsif not @user.miscellaneous_details
    performSegueWithIdentifier('miscellaneousSegue', sender: self)
  end

  else
    performSegueWithIdentifier('moviesSegue', sender: self)
  end
end

Now, suppose the user reached the view where he has to enter his misellaneous details. Once he entered them all he now has to be be shown the table view which list the movies in his language. We have implemented this segue to the moviesviewcontroller in viewDidAppear delegate in the masterviewcontroller. Hence for this to work, the masterviewcontroller's view will have to appear. For this to happen, the current controller( the i.e, miscellaneousviewcontroller ) along with all controllers in between the current controller and the master view controller will have to be dismissed ( in our case, its only the languageviewcontroller ).

For this to be done, we have the dismissViewControllerAnimated(flag, completion:completion_block) method.

We implement this method in the presented view controller. Here, miscellaneousviewcontroller is the current presented view controller.

miscellaneous_view_controller.rb

outlet :submitButton, UIButton
ib_action :submit_miscellanous_details

def submit_miscellanous_details
  # Do something here...

  self.view.window.rootViewController.dismissViewControllerAnimated(true, completion:nil)
end

So in the miscellaneousviewcontroller controller we have a submitButton which is tied to an ibaction *submitmiscellanousdetails*. On submitting the button, the ibaction is invoked. We do whatever necessary steps is required in the ibaction and then invoke dismissViewControllerAnimated on the rootViewController( i.e, the masterviewcontroller ). When this is done, the presented controllers and all other controllers in the chain of controllers until the presenting controller on whom the dismissViewControllerAnimated method is called ( here, the rootViewController) is also dismissed. The rootViewController or the masterview_controller view appears on screen and the viewDiDAppear delegate will process the rest.