4

I am new with Objective-C so apologies for a dumb question.

I am opening an "options" view controller from my main view controller. Both are built in the storyboard. Before and after presenting the options controller I need to stop and start a timer on my main view controller. After the options controller is closed (a button calls dismiss) I need to send some info back to my main controller or at least let my main controller know that it needs to refresh some values.

MAIN QUESTION What's the best way of presenting a view controller and executing some presenter's methods before and after opening?

WHAT I'VE TRIED I found a few ways to do it, but they are all cumbersome and I assume that there must be some plausible way of doing it.

  1. Ideally I'd like to use the segue I set up in the storyboard between the two controllers.
  2. I managed to call the options controller programmatically by accessing the storyboard and calling instantiateViewControllerWithIdentifier. It worked but looks a bit complex.
  3. I was not able to find a delegate method on the UIViewController to handle the dismiss event
  4. When I was trying to access the main controller in the options controller via presentingViewController and downcasting it, I got a linkage error by including my .h file twice (not sure what are the Obj-C standards of using #define).

Appreciate your help...

Vlad Z
  • 383
  • 2
  • 12
  • You might want to figure out your main question, concisely state it, and post some related code – Dustin Jun 27 '12 at 17:56
  • ok, the main question is what's the best way of presenting a view controller and executing some presenter's methods before and after opening. – Vlad Z Jun 27 '12 at 18:01
  • Look at this http://stackoverflow.com/q/11229830/1439815 – Dustin Jun 27 '12 at 18:03

5 Answers5

2

For communication between ViewControllers that are weakly linked, you could use the NSNotificationCenter:

https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html

Here you can send a message to all ViewControllers listening, which need to process some changes (for example an option to change the font size).

It's really easy to implement and it keeps certain ViewControllers less dependent on each other.

Wim Haanstra
  • 5,918
  • 5
  • 41
  • 57
  • Understood, in my case it is a strong link though. The main controller executes pre-open method, opens new the controller (modal), executes post-close method. – Vlad Z Jun 27 '12 at 18:04
2

All of this can be done quite easily with storyboard and NSNotificationCenter, and NSCoding. In the viewDidLoad method of your main controller, put this code:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(receiveNotification:) 
                                             name:@"Update"
                                           object:nil];

Then create this method in the same controller:

(void)receiveNotification:(NSNotification*)notification
{
   //...
}

When you want to make the main controller update from the options controller:

[[NSNotificationCenter defaultCenter] postNotificationName:@"Update" object:self];

Also, I would suggest using NSArchiving for Basic Data Persistence. Just found this tutorial, looks pretty good. http://samsoff.es/posts/archiving-objective-c-objects-with-nscoding

Basically, create an object that can store information, code it using nscoding, and then uncode it whenever you need it. It has worked great for me.

Hope that helps!

Bot
  • 11,868
  • 11
  • 75
  • 131
Ahab
  • 311
  • 1
  • 2
  • 6
2

MAIN QUESTION What's the best way of presenting a view controller and executing some presenter's methods before and after opening?

Just in case the answers above are a bit more involved than you'd like, I'll suggest that the easiest way to execute a presenter's methods before opening is to do so in the presenter's prepareForSegue method. If you need to send data to the destination view controller, you can access its properties this way:

ViewController *destinationVC = [segue destinationViewController];

An easy way to execute the presenter's methods after opening would be:

ViewControllerSubclass *previousVC = [self presentingViewController];

And then use the class or instance to execute your class or instance methods. You could do this in the destination's viewWillAppear.

Sorry if you already knew all this; it's often difficult to surmise what level of complexity is needed.

Michael Mangold
  • 1,741
  • 3
  • 18
  • 32
1

I have run into this with almost every app I have on the market. Difference is I have never decided to go down the storyboard path.

The way I have always been able to accomplish this is to provide accessor functions between the controllers. You get past the linker issue by defining the cross defined controller as simply a UIViewController type within your options view header, then including the main view controller' header only in the .m file. Now when you call a main view controller routine from your options view, you will have to cast it to the type of your main view controller!

You will also have to provide a routine in your options view that will allow you to set the variable that will hold a pointer to your main view controller to self.

Example for your optionsView

@interface optionsViewController : UIViewController{
    UIViewController * myReactiveMainViewController;
}

-(void)setMyReactiveMainViewController:(UIViewController *)controller;

No in the .m file for the optionsView

#import "myMainViewController.h"

-(void)setMyReactiveMainViewController:(UIViewController *)controller{
    myReactiveMainViewController = controller;
}

In any other call back to the main view controller you will have to do this:

-(void)returnToMain{
    [(myMainViewController *)myReactiveMainViewController someCall:variable];
}

This example would of course assume that your myMainViewController implements a method called "someCall" that take on input parameter.

trumpetlicks
  • 7,033
  • 2
  • 19
  • 33
0

Thanks for replies.

I ended up with

  1. Calling prepareForSegue to execute pre-transition code

  2. Calling performSelector on presentingViewController when releasing presented view controller.

I am sure other suggestions would work too.

Vlad Z
  • 383
  • 2
  • 12