I want to give a share screen throughout my app. I am using UIActivityViewController for that purpose. The problem is, as per your location in the app, the current root view controller can be of kind UINavigationController(Case1) or UIViewController(Case2).
I can present UIActivityViewController using
[viewController presentViewController:viewController animated:YES completion:nil];
But I have to get currently visible UIViewController of UINavigationController in (Case1), and root view controller itself in (Case2).
But how to detect which kind of root view controller is present & code accordingly?
Thanks.
Try:
UIViewController *root = [[[[[UIApplication sharedApplication] keyWindow] subviews] objectAtIndex:0] nextResponder];
and then:
if ([root isKindOfClass:[UINavigationController class]]) {
// Navigation Controller
} else {
// The other one
}
that should tell you which one is presented.
Use the above method to detect for a UINavigationControler;
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
//If this will be called it is a navigation controller
}
use performselector to start and stop rorating activity indicater
Here AI is activity indicater variable name
[self performSelector:#selector(animateAI) withObject:self afterDelay:0.1];
[self performSelector:#selector(stopAI) withObject:self afterDelay:0.9];
-(void)animateAI
{
[AI startAnimating];
}
-(void)stopAI
{
[AI stopAnimating];
}
Related
In my model class i want to show alert when something bad happen (for example, server send an error). However, i dont want to bother with delegate or KVO.
Is there an easy way to show an alert for "main" window, to place a view above others?
Currently i use this code (not work, if placed out of viewController classes):
UIAlertController *vc = [UIAlertController alertControllerWithTitle:#"Произошла ошибка"
message:response
preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:vc animated:YES completion:^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[vc dismissViewControllerAnimated:YES completion:nil];
});
}];
Obviously, classes that don't have a view cant use:
[self presentViewController:vc animated:YES completion:^{
as per solution of #Ashley Mills You can find top view controller with this method
- (UIViewController *)currentTopViewController
{
UIViewController *topVC = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
while (topVC.presentedViewController)
{
topVC = topVC.presentedViewController;
}
if ([topVC isKindOfClass:[UINavigationController class]]) {
return [(UINavigationController *)topVC topViewController];
}
return topVC;
}
show you alert in return object of currentTopViewController method
You need to present the UIAlertController from a UIViewController. If you want the main view controller, you'll need to do this from your application delegate's window's rootViewController.
A nasty way to do this is to refer to UIApplication.sharedApplication().delegate.window.rootViewController
A better way would be to post a notification from your model method and listen for it in the App Delegate
Ideally though you should be looking at passing back an error from your model method to the calling view controller.
Or perhaps you could pass in your current view controller as a parameter to the model method
There are 3 view controllers View1,View2 and View3.
From view3 I have to navigate to view1.
I have tried the following code but it doesn't work.
//in View3.m
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;
{
appDelegate.isComingFromCountries = YES;
[self dismissViewControllerAnimated:YES completion:nil];
}
//in View2.m
-(void)viewWillAppear:(BOOL)animated
{
if (appDelegate.isComingFromCountries == YES)
{
appDelegate.isComingFromCountries = NO;
[self dismissViewControllerAnimated:YES completion:nil];
}
}
But this code doesn't work. How do I handle this?
You can use use presentingViewController for dismissing it,
try this -
[self.presentingViewController.presentingViewController dismissModalViewControllerAnimated:YES];
A -> B -> C
Running the above code in modal C will take you back to A.
You have to use delay method to perform animation so that main thread should start performing in B viewController
[self performSelector:#selector(methodForDissmiss) withObject:nil afterDelay:0.5];
then write dismiss code in selector method to work by your logic.
If you are returning to the root view controller from a series of modally presented view controllers then the following code will work in iOS6
[self.window.rootViewController dismissViewControllerAnimated:NO completion:nil];
I think, It may help you. According to your code( in comments area), You second view controller push from first view controller, then present third from second. So you have to set delegate as second in third. And do your code as below in third VC.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;
{
appDelegate.isComingFromCountries = YES;
[self dismissViewControllerAnimated:YES completion:^{
[self.delegate dismissModal];
};
}
In SecondVC.m
-(void)dismissModal
{
[self.navigationController popViewControllerAnimated:NO];
}
Also you can pop to view 1 from view 3 on like this:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
[self.navigationController dismissViewControllerAnimated:NO completion:nil];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
You can try this one :
if you are pushing one viewController to another and want to move back then use this one
[self.navigationController popViewControllerAnimated:YES];
if you are presenting viewController use modelly and want to move back then use this one
[picker dismissViewControllerAnimated:YES completion:nil];
also you can try this because first you need to dismiss third viewController then second one.
UIViewController *viewController = [self parentViewController];
[self dismissModalViewControllerAnimated:NO];
[viewController dismissModalViewControllerAnimated:YES];
The situation is :
App is on background
The user click on icon app
App open and show the view controller where we were before apps entered background last time.
I'd like to know which view controller is about to be presented. I'm looking for something like :
- (void)applicationDidBecomeActive:(UIApplication *)application {
if ([self.window.viewControllerOnScreen isKindOfClass:[HomeViewController class]]) {
//do sthg
}
}
Because in case, it's the home view controller (embed in a navigation controller and i use storyboards) i would perform some reload method.
[[self.navigationController viewControllers] lastObject];
The first part will give you an array of all of the viewControllers on the stack, with the last object being the one that is currently display. Check its class type to see is it the homeViewController
As per this link Each object receive a UIApplicationDidEnterBackgroundNotification notification when the app goes in background. Similarly UIApplicationWillEnterForegroundNotification gets fired when app comes in foreground.
so you can use it to keep track of which view controller is opened when app enters foreground
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(appEnteredForeground:)
name:UIApplicationDidEnterForegroundNotification
object:nil];
Try this
- (UIViewController *)topViewController{
return [self topViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController *)topViewController:(UIViewController *)rootViewController
{
if (rootViewController.presentedViewController == nil) {
return rootViewController;
}
if ([rootViewController.presentedViewController isMemberOfClass:[UINavigationController class]]) {
UINavigationController *navigationController = (UINavigationController *)rootViewController.presentedViewController;
UIViewController *lastViewController = [[navigationController viewControllers] lastObject];
return [self topViewController:lastViewController];
}
UIViewController *presentedViewController = (UIViewController *)rootViewController.presentedViewController;
return [self topViewController:presentedViewController];
}
I have done this for getting the current viewController
if (![[appDelegate.rootNavController topViewController] isMemberOfClass:NSClassFromString(#"LGChatViewController")]) {}
self.tabBarController.viewControllers = [NSArray arrayWithObjects: [self LoadAccount], [self LoadContacts], [self LoadPhoneLine], [self LoadSettings], nil];
if you use tab bar then you set like this and show first account and go on......
I have an two class, in first class
- (IBAction)Login:(id)sender {
SampleViewController2 *sampleView = [[[SampleViewController2 alloc] init];
[self presentModalViewController:sampleView animated:YES];
}
in second class..
- (IBAction)Logout:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
it says warning Attempt to dismiss from view controller.. what is the problem here..
Add this:
if (![[self modalViewController] isBeingDismissed])
[self dismissModalViewControllerAnimated:YES];
Do a simple google search, the problem that you stated is common...
You might check it before dismissing if your current view's modal view is being dismissed or not
if (![[self modalViewController] isBeingDismissed]){
[self dismissModalViewControllerAnimated:YES];
}
I have a tab bar controller with a view inside a navigation controller. One of the buttons on this pops up a modal view. I set my starting view as the delegate for the modal, and call the following:
- (void)dischargeSaveComplete:(dischargeView *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
[self.navigationController popViewControllerAnimated:YES];
}
It correctly dismisses the modal view, but it doesn't call the back button. Do I need to do something else since it's inside a tab bar controller?
I tried set both to animation no as seen below, and it doesn't work either.
- (void)dischargeSaveComplete:(ehrxEncounterDischargeView *)controller
{
[self dismissViewControllerAnimated:NO completion:nil];
[self.navigationController popViewControllerAnimated:NO];
}
Found the solution based on one of the answers, because I was in a tab bar controller, I had to call the popviewcontroller from the first view as seen below:
- (void)dischargeSaveComplete:(ehrxEncounterDischargeView *)controller
{
[self dismissViewControllerAnimated:YES completion:^(void)
{
demoView *e = [self.parentViewController.tabBarController.viewControllers objectAtIndex:0];
[e.navigationController popViewControllerAnimated:YES];
}];
}
You want 2 animations to follow one another, which is not allowed as you did it. You either have to cancel one of the animation or place popViewController inside the completion block for your first animation.
[self dismissViewControllerAnimated:YES completion:^(void) {
[self.navigationController popViewControllerAnimated:YES];
}
];
u can try delay in performing second action
[self.navigationController performSelector:#selector(popViewControllerAnimated:) withObject:#"YES" afterDelay:1];
hope it works.. happy coding :)