Correct pattern for refreshing data in UIViewController's - objective-c

I am trying to refresh my view data when the application becomes the active app again. I believe the correct pattern is to have the app delegate tell it's view to reload it's data when applicationDidBecomeActive is called.
However, I am having trouble finding the UIViewController from within the Delegate:
- (void)applicationDidBecomeActive:(UIApplication *)application {
MyFancyViewController* controller = //how do I get my view controller???
[controller refreshData];
}
Also, can I count on the view controller still being allocated, or is there a chance it would go away? I'm using iOS 5 Storyboard's if that makes any difference.
Update:
I think I got it:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
UIViewController* root = _window.rootViewController;
UINavigationController* navController = (UINavigationController*)root;
OctainViewController* mycontroller = (OctainViewController*)[[navController viewControllers] objectAtIndex:0];
[mycontroller refresh:nil];
}

Yeah, this does the trick:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
UIViewController* root = _window.rootViewController;
UINavigationController* navController = (UINavigationController*)root;
OctainViewController* mycontroller = (OctainViewController*)[[navController viewControllers] objectAtIndex:0];
[mycontroller refresh:nil];
}

Why not refresh your data in the respective view controller viewWillAppear method?

Related

UITableView isn't displaying data

AppDelegate
- (void)applicationDidFinishLaunching:(UIApplication *)application {
UIStoryboard *myStoryboard = [UIStoryboard storyboardWithName:#"MainSB" bundle:nil];
tCont = [myStoryboard instantiateViewControllerWithIdentifier:#"Table"];
}
- (void)serviceAdded:(NSNetService *)service moreComing:(BOOL)more {
tCont.server = _server;
[tCont addService:service moreComing:more];
}
TableController
- (void)addService:(NSNetService *)service moreComing:(BOOL)more {
[self.services addObject:service];
if(!more) {
[self.tableView reloadData];
}
}
server is correctly carried over, and service is added to services. But I don't see it in my table view. Is it because I'm trying to instantiate the view before it exists?
Update: I've done a little more debugging and found that TableController is initialized before my delegate calls for it. I've only seen one TableController thread, so my code is most likely the issue.
You need to create an UIWindow, set its rootViewController property to your table view controller and send it the makeKeyAndVisible message. You also have to implement the tableView:cellForRowAtIndexPath: method on your table view controller.

performing segue from appdelegate

I have the following code:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
//make sure that the user credentials are still ok
if (userLeftApplication){
BaseViewController * baseViewController = [[BaseViewController alloc]init];
BOOL detailsAreOK = [baseViewController credentialsValidated];
if (!detailsAreOK){
[self.window.rootViewController performSegueWithIdentifier: #"fromSplashToLogin" sender: self.window.rootViewController];
}
userLeftApplication = FALSE;
}
}
However, I get the following exception when trying to perform the segue:
Attempt to present <LoginViewController: 0x2012e180> on <FirstViewController: 0x1f59cef0> whose view is not in the window hierarchy!
and the user is not being directed there.
What is wrong?
rootViewController isn't currently defined. You can't 'perform a segue from the App Delegate', segues are transitions between view controllers. You need to launch the view controller rather than perform a segue.
self.window.rootViewController = baseViewController;

Attempt to present * on * whose view is not in the window hierarchy

I'm trying to make a modal view controller in my app delegate (I created a function called showLoginView). But whenever I try to call it I get a warning in XCode:
Warning: Attempt to present <PSLoginViewController: 0x1fda2b40> on <PSViewController: 0x1fda0720> whose view is not in the window hierarchy!
Here's the method code:
- (void)showLoginView
{
PSLoginViewController *loginViewController = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:NULL] instantiateViewControllerWithIdentifier:#"PSLoginViewController"];
[self.window.rootViewController presentViewController:loginViewController animated:NO completion:nil];
}
How can I add the view to the window hierarchy? Or maybe I'm doing something very wrong?
You can't display a modal view controller from the appDelegate. You need to display a modal ViewController from whichever viewController is currently displaying full-screen. In other words, you need to put that code into your root view controller, or whichever one you want to display the modal vc from...
Also, you'll want to use the method "presentModalViewController" to present the modal. You can set properties on the modal vc such as:
vC.modalPresentationStyle = UIModalPresentationFormSheet;
vC.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:vC animated:YES];
You can actually present a modal view Controller from the AppDelegate as long as you detect the current visible viewController and take care of the case where you current controller is a navigationController.
Here is what I do:
UIViewController *activeController = [UIApplication sharedApplication].keyWindow.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]]) {
activeController = [(UINavigationController*) activeController visibleViewController];
}
[activeController presentModalViewController:loginViewController animated:YES];
UIViewController *activeController = [UIApplication sharedApplication].keyWindow.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]])
{
activeController = [(UINavigationController*) activeController visibleViewController];
}
else if (activeController.modalViewController)
{
activeController = activeController.modalViewController;
}
[activeController presentModalViewController:vc animated:YES];
I ran into this problem on iOS 7 - the key to making any of the proposed solutions work was to call
[self.window makeKeyAndVisible];
in your AppDelegate.
After that call, presenting a modal view from the window's rootViewController worked.
Another reason for that warning can be that you want to present a view controller from an instance which is not the top most view controller.
So first you have to get the topmost UIViewController and using this instance to call presentViewController:
UIViewController *root = [UIApplication sharedApplication].keyWindow.rootViewController;
while (root.presentedViewController) {
root = root.presentedViewController;
}
You can NSLog(#"%#", self.window.rootViewController), and see what the rootViewController really is.
I came into this problem, when the rootViewController is a normal UIViewController.
Replace it with a UINavigationController, wish it will help.
Faced this issue while trying to present controller from the call of delegate of other controller . i.e : show search filter with delegate , once done back to my controller and receive data via the delegate then present controller , all I had to do is to dispatch the present code cause while in a delegate you're in another thread , that's why you're presenting on your view from main thread another controller from that other thread , so have to go back to main thread , just put the presenting code like this :
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:searchVC animated:true completion:nil];
});
Hope this helps !

Proper view controller not displayed when tapping push notification

I have implemented push notifications and am attempting to take the user to another view controller (opposed to just opening the app) when they tap the notification. I was going off of the apple website example but have not had any luck yet.
It seems that it never even enters my code as it should. I tried putting an NSLog to prove that and I was right.
Does anyone know why? The view controller I want implemented is called statsViewController.
Thanks
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSDictionary *remoteNotif = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotif) {
NSLog (#"We are here now");
[self handleRemoteNotification:application userInfo:remoteNotif]; //custom method where View controller will be implemented
return YES;
}
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
return YES;
}
-(void) handleRemoteNotification:(UIApplication *)application userInfo:(NSDictionary *)userInfo {
application.applicationIconBadgeNumber = 0;
statsViewController* viewController = [[statsViewController alloc] init];
[navController pushViewController:viewController animated:YES]; //Don't think this is right since I never use it in didFinishLaunching... I simply just declared it delegate.h
[viewController release];
}

Orientation problem

i have created and ipad application.
i started off with window based application and added 2 view controllers(loginviewcontroller , detailviewcontroler ) . both have their own XIB'S. the added the loginviewcontroller object in in the appdelegate applicationdidfinishlaunch method , i wrote code to move back and forth between 2 views. Here is the code.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
Login *mylogin = [[Loginviewcontroller alloc] init];
[window addSubview:mylogin.view];
//detailview *tv=[[detailviewcontroller alloc] init];
// [window addSubview:tv.view];
[self.window makeKeyAndVisible];
return YES;
}
The problem is that the willrotatetointerfaceorientation method runs only from the loginviewcontroller class even if i am in the detailviewcontroller.
if i add the tickets view to the appdelegate then it runs the willrotatetointerfaceorientation method from detailviewcontroller , so in summary it runs the willrotatetointerfaceorientation method from only the object which was added to appdelegate.
how do i make the 2 view controllers run their respective willrotatetointerfaceorientation methods?
UIViewController has the method
(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
override this method in your both viewcontroller classes(i.e. (loginviewcontroller , detailviewcontroler )
write this code
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
//write your code which you want to during rotation
return Yes;
}
The rotation messages are being sent only to the controller of topmost view. You should forward them manually in appropriate methods.