Respond to LocalNotification in viewController - ios5

I need to respond to a LocalNotification on my app on the main viewController. My problem is that the system seems to be the catch it in didRecieveLocalNotification which I am but I then need to take some action in the main view.
My problem is that that action differs depending on a global class variable (Boolean) and from what I can tell the only way to access the viewController from the didRecieveLocalNotification is to recreate the view class as a new init alloc which would destroy the current value of said variable.
How do I call a viewController method from the appdelegate's didRecieveLocalNotification without destroying the variable or any content on the view.

Assuming the main viewController which you are referring to is the root view controller of your UIWindow which you should have in your app delegate, you can do the following.
[(viewController*)[self.window rootViewController] themethodyouwanttocall];
From the phrasing of your question, that should call a method on the root view controller from the app delegate.

Related

Swift: Determine Active View Controller when applicationDidEnterBackground is called

Is there a way for me to determine the ViewController that was active when a user hits the Home button and the app delegate function applicationDidEnterBackground function is called?
So this line:
let vc: UIViewController = self.window!.rootViewController!
will give you the root view controller in Swift (assuming that you use that line in some method inside AppDelegate), but if you have containers (such as UITabBarController) -- you may need to go on that hierarchy for additional checks/inspections...

On iOS, if a view controller has no view yet, why does NSLog(#"self.view is %p", self.view) crash?

If a new iOS project is created with an Empty App template in Xcode 4.3.2, and in AppDelegate.m:
self.window.rootViewController = [[FooViewController alloc] init];
and in FooViewController's viewDidLoad, the following:
NSLog(#"self.view is %p", self.view);
NSLog(#"self.view is %#", self.view);
will print out the view, so it looks like the default loadView will instantiate a view and assign it to self.view.
So if I override loadView with an all empty method, and comment out the second NSLog statement above, I expect the first NSLog statement to print out 0x0, but instead the app crashed due to bad memory access right at that NSLog line. Why would that be?
Okay, after a knee-jerk and obviously wrong answer, I tried this. The Empty App template would not have a rootViewController, so I used a single screen template. After running, I see that you are getting a stack overflow. In trying to access self.view, you are calling the view property on the superclass, which is then trying to load the view in order to return it, which is calling viewDidLoad, etc., as far as I can see. The other NSLog statement does the same.
The documentation for the view property in UIViewController states:
Because accessing this property can cause the view to be loaded automatically, you can use the isViewLoaded method to determine if the view is currently in memory.
It also has a link to The View Controller Life Cycle, which states:
The steps that occur during the load cycle are as follows:
The load cycle is triggered when the view controller's view property is accessed and the view is not currently in memory.
The view controller calls its loadView method. The default implementation of the loadView method does one of two things:
If the view controller is associated with a storyboard, it loads the views from the storyboard.
If the view controller is not associated with a storyboard, an empty UIView object is created and assigned to the view property.
The view controller calls its viewDidLoad method to allow your subclass to perform any additional load-time tasks.
So when you say:
So if I override loadView with an all empty method
You're deliberately breaking the life cycle, because when your overridden version of loadView finishes, it should have loaded a view. Because it didn't, you get a crash.

How to pass NSManagedObjectContext via Interface Builder's XIBs

I have a simple iOS application with one UIViewController beneath a UINavigationController. The UIViewController has an IBOutlet for an NSManagedObjectContext.
The AppDelegate has an IBOutlet for the nav controller - but not the view controller. The view controller is automatically instantiated ala the XIB process (as a child of the nav controller).
With this setup, how does one cleanly assign or pass the app delegate's NSManagedObjectContext to the view controller's IBOutlet property. There is a nav controller in the way :) and the app delegate doesn't have a direct property for the UIViewController.
It is a weird problem in that, I want to link a property from one XIB component to another component's property. Most of the XIB work I've done takes a property and points it to an object in the XIB which in turn - gets instantiated ala the normal process but in this case, the context is being created correctly in the app delegate, I just want to pass it on to the view controller when it instantiates it.
You don't need to pass it, just grab it from the app delegate as required:
#import "MyAppDleegate.h"
NSManagedObjectContext* moc = [(MyAppDelegate*)[UIApplication sharedApplication].delegate managedObjectContext];
Apple's docs recommend that you pass references to your managed object context to the classes the require them instead of referencing it from your app delegate.
Here's what the application:didFinishLaunchingWithOptions: looks like in one of my Core Data projects.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
LocationsViewController *lvc = (LocationsViewController *)self.navigationController.topViewController;
lvc.managedObjectContext = self.managedObjectContext;
assert(lvc.managedObjectContext != nil);
[self.window addSubview:self.navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}
You'll see that I also start with a UINavigationController with a single root view controller.
You've got the right idea, but the problem you're wrestling with seems to be entirely of your own creation. You say that your app delegate has an outlet for the navigation controller, but not for the nav controller's root view controller, because you've set up your nib such that the view controller is created when the nib is loaded. There's nothing wrong with that, but there's also no reason that the app delegate shouldn't have an outlet for that controller. Indeed, the entire reason for outlets is to get references to things that are loaded from a nib.
Add an outlet to your app delegate for your root view controller, and connect it. The app delegate can then give the controller a reference to the managed object context.
With respect to your question about multiple view controllers, I wonder what sort of real-world app might have view controller (A), which needs data, load another view controller (B) which doesn't need any data, followed by a third (C) which again needs data? A realistic example might help, if you have one.
Remember that you don't have to pass the entire managed object context to each successive view controller. You can instead pass just the part of the model that the controller will need to do its work by passing a managed object.

How to access one UIViewControllers properties from another UIViewController?

I have one single MainViewController which has of course it's one main UIView. I have this main view comprised of many different subviews.
Some of these subviews have their very own ViewController.
Lets say the MAIN view (whose delegate is primarily MainViewController) has a container which loads another UIView that uses a separate UIViewController- SecondaryViewController as the delegate for most it's actions.
This container view is of course loaded in MainViewController via
MyContainerViewController *myContainerController =
[[MyContainerViewController alloc] ...];
[self addSubView: myContainerController.view];
the controller for myContainerController.view though is MyContainerViewController. How inside this controller do I access MainViewController properties? Specifically I need to access MainViewController's - self.navigationController property to push a new ViewController? :)
Does this make any sense? I assume there's going to be casting of some sort involved since it seems I need to somehow retain a reference to MainViewController inside SecondaryViewController?
It doesn't make sense to push a new ViewController from the SecondaryViewController in the MainViewController.
This screws up the design of the code. A child object will access its parents method to call a method. By other words: bad code.
Make a delegate call from the SecondaryViewController to the MainViewController that it state has changed. Then the MainViewController can decide to do with the call and the SecondaryViewController will not know anything about the implementation of the MainViewController.
So:
Make a protocol in SecondaryViewController.
Let the MainViewController be SecondaryViewController's delegate.
Implement the delegate method in MainViewController which pushes the new ViewController.
Expose the desired sub-view controllers as properties of the view controller that contains them.
Expose your root view controller(s) as properties of your app delegate, and synthesize them also.
When you want to access a different UIViewController, first obtain a reference to your appDelegate:
MyAppDelegate* myAppDelegate = [[UIApplication sharedApplication] delegate];
Then just use your chain of properties to get access to your desired view controller.
SubSubViewController* ssvc = myAppDelegate.rootViewController.subViewController.subSubViewController;
Some folks frown upon the use of the sharedApplication class method to obtain the reference to a delegate, but I've used it in multiple apps and not suffered for it (yet). The alternative is to pipe your appDelegate through your hierarchy of viewControllers.

Do something if view loads

I shift to my view by
[[self navigationController] popToViewController:controller animated:YES];
In that ViewController, I'm not able to get a notice, that it comes back to front (e.g. by viewWillAppear). I want to reload a table, as soon as the view is visible again.
How do I get a notice, that the view comes back on the screen?
----> solved: See my last comment on Corey's answer
viewWillAppear should be called if you are using a UINavigationController.
Are you sure you have added it correctly to the view hierarchy?
Did you check if viewWillDisappear gets called when it goes offscreen?
Did you try viewDidAppear just to make sure?
Did you spell the method name correctly?
To add:
Is the instance of UINavigationController added directly to the UIWindow instance?
The delegate methods like viewWillappear are sent from UIApplication (I believe). UIApplication only "knows" about viewControllers whose views are either:
Added Directly to UIWindow.
Added to a
UINavigationController/UITabBarCOntroller
that is added directly to UIWindow
(or a chain of these that leads to UIWindow).