I have been figuring out this since yesterday but have not got that correct yet.
I have added the modalviewcontroller for my loading view controller on top of my tab bar controller and it works fine.
Added the code in app Delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions {
[navController.navigationBar setTintColor:[UIColor blackColor]];
[window addSubview:rootController.view];
[window makeKeyAndVisible];
LoadingViewController *lvc = [[LoadingViewController alloc] initWithNibName:#"LoadingView" bundle:nil];
// Delegate added here
lvc.loadingDelegate = self;
[rootController presentModalViewController:lvc animated:YES];
[self URL];
[lvc release];
return TRUE;
}
Now I do my parsing and when its done I call the following code in different view name XMLParsingView.m where the parsing got over.
- (void)handleLoadedApps
{
LoadingViewController *loading = [[[LoadingViewController alloc] init] autorelease];
//delegating to let the load view controller know to dimiss itself by defining disappear method in protocol
[loading.loadingDelegate disappear];
}
and in loading view controller I have method which calls dismissModalViewControlAnimated:
-(void)disappear{
[activity stopAnimating];
[activity removeFromSuperview];
[self removeFromSuperview];
[self dismissModalViewControllerAnimated:YES];
}
But for some reason it will never remove the view and not load it back to my tab bar controller.
Really need help here if any one have come across such issues.
Sagos
In your code you seem to create, without a nib, a new LoadingViewController and immediately go and dismiss it. In your app delegate you create your first loadingViewController with a nib, present it modally on rootController and then release it. Since you want to dismiss it outside your app delegate you have
3 choices, (hardest to fastest and most sane)
a) Key-Value-Observing on a property of XMLParsingView from LoadingViewController to remove itself when the task finishes.
b) Use delegation to inform the LoadingViewController when the task finishes to dismiss itself.
c) Fetch your rootController from your [[UIApplication sharedApplication] delegate], which means you must expose rootController as a property or through a method, and make rootController dismiss your modal.
You need to call dismissModalViewControllerAnimated on the rootViewController, not the loading view controller.
Related
Background: I would like to dismiss a modalView that I have presented earlier and right away present the same viewController that I just dismissed with new information.
Problem: I have not been very successful in doing so without an explicit pointer to the parent ViewController that presented the first ViewController modally. I am trying to write this class that works without messing around with the previous viewController's code.
Possible lead: There are couple of things I have been experimenting with:
1.) Trying to get access to the parent ViewController, which at this time I don't know how to.
2.) Once access to the parent is gained, I can simply apply the following code:
UIViewController* toPresentViewController = [[UIViewController alloc] init];
[self dismissViewControllerAnimated:YES completion:^{
[parentViewControllerAccessor presentModalViewController:toPresentViewController animated:YES];
}];
In theory this should work given the access to parent viewController. I am open to other ways of doing this.
Assumption: You do not have permission to change any code in the parent ViewController.
Your code looks like it should work. If you are using iOS 5 there is a UIViewController property called presentingViewController.
#property(nonatomic, readonly) UIViewController *presentingViewController;
So you can use this property to get the view controller that presented your modal controller.
Note: In iOS 4 parentViewController would be set to the presenting controller, so if you are supporting both iOS 4 and 5 you will have to check the OS version first to decide which property to access. In iOS 5 Apple have fixed this so that parentViewController is now exclusively used for the parent of contained view controllers (see the section on Implementing a Container View Controller in the UIViewController documentation).
Edit: Regarding accessing self.presentingViewController from within the block: By the time the block is called (after the modal view controller is dismissed) the presentingViewController property may get set to nil. Remember that self.presentingViewController inside the block gives the value of the property when the block is executed, not when it was created. To protect against this do the following:
UIViewController* toPresentViewController = [[UIViewController alloc] init];
UIViewController* presentingViewController = self.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^
{
[presentingViewController presentModalViewController:toPresentViewController animated:YES];
}];
This is necessary not because self is gone/dismissed (it is safely retained by the block), but because it is no longer presented, therefore its presentingViewController is now nil. It is not necessary to store the presentingViewController anywhere else, the local variable is fine because it will be retained by the block.
You could accomplish this using notifications.
For example, fire this notification from outside the modal view when you want it to be dismissed:
[[NSNotificationCenter defaultCenter] postNotificationName:#"dismissModalView"
object:nil
userInfo:nil];
And then handle that notification inside your modal view:
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(dismissMe:)
name:#"dismissModalView"
object:nil];
}
- (void)dismissMe:(NSNotification)notification {
// dismiss it here.
}
the solution for ios5:
-(void)didDismissModalView:(id)sender {
// Dismiss the modal view controller
int sold=0;
if(sold==0){
//Cash_sold.delegate = self;
// Cash_sold.user_amount.text=[NSString stringWithFormat:#"%d",somme];
Cash_sold = [[CashSoldview alloc] initWithNibName:#"CashSoldview" bundle:nil];
CGRect fram1 = CGRectMake(200,20,400,400);
Cash_sold.view.superview.frame = fram1;
Cash_sold.view.frame=fram1;
Cash_sold.modalTransitionStyle= UIModalTransitionStyleCoverVertical;
Cash_sold.modalPresentationStyle=UIModalPresentationFormSheet;
UIViewController* presentingViewController = self.parentViewController;
[self dismissViewControllerAnimated:YES completion:^
{
[presentingViewController presentModalViewController:Cash_sold animated:YES];
}];
}
}
Try the following code:
[self dismissViewControllerAnimated:NO
completion:^{
// instantiate and initialize the new controller
MyViewController *newViewController = [[MyViewController alloc] init];
[[self presentingViewController] presentViewController:newViewController
animated:NO
completion:nil];
}];
I have two views - view1 and view2.
View1 is my default viewcontroller loaded from mainwindow.xib.
Depending on some condition checking, i want to load either View1 or View2, say if user registration is not done, load sign up screen for user, else go to default view controller.
How and where do I check this condition?
Please help.
Thanks in advance.
In your app delegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if(needToLogin) {
[self setViewController:[[[ViewController2 alloc] initWithNib:#"Login View"] autorelease]];
}
[window setRootViewController:viewController];
}
This will switch your view controller to the view2 view controller if needToLogin returns true. Otherwise, it will go to the default controller specified in mainwindow.xib
Another method (since you probably need the main view controller anyway) would be to present the login view controller if its needed.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if(needToLogin) {
ViewController2 *loginVC = [[[ViewController2 alloc] initWithNib:#"LoginViewController"] autorelease];
[[self viewController] presentViewController:loginVC animated:NO];
}
[window setRootViewController:viewController];
}
Note, you will have to call [self dismissViewControllerAnimated:YES] to get rid of the login view.
Edit: Respones from OP:
I tried first one,
if(loginflag){
[self setViewController:[[[SignUpViewController alloc] initWithNibName:#"SignUpViewController" bundle:nil] autorelease]];
}
[self.window setRootViewController:self.signUpView];
Try this instead:
if(loginFlag) {
[self setViewController:[[[SignUpViewController alloc] initWithNibName:#"SignUpViewController" bundle:nil] autorelease]];
}
[[self window] setRootViewController:[self viewController]];
If you are just planning on bringing up a sign-up screen if the user registration is needed, why not stick with the default view controller, but at -applicationDidBecomeActive: present a modal view controller for the sign up view?
With the information given, you could just create a flag in the AppDelegate that can be persisted based on the user registration is complete or not. Then in the "didFinishLaunching..." method you could check this flag and load the the proper view based on this.
I'm using the following code to display the previous view when a user is clicking on a button
[self.navigationController popViewControllerAnimated:YES];
In the previous view, I overwrite viewWillAppear to initialized few things. However, it seems like viewWillAppear is not being called. I put NSLog in viewDidload, viewWillAppear, viewDidAppear and only viewDidAppear is being called. Is this normal behavior? If yes, what event should I override so I can do my initialization? Thank you.
As requested -viewWillAppear for the previous view
- (void)viewWillAppear:(BOOL)animated{
NSLog(#"ViewWillAppear");
//[[GameStore defaultStore] resetGame];
[self setHangmanImage];
NSLog([[[GameStore defaultStore] selectedList] label]);
[labelListName setText:[NSString stringWithFormat:#"List Name: %#", [[[GameStore defaultStore] selectedList] label]]];
[labelCurrentIndex setHidden:YES];
[labelCurrentWord setHidden:YES];
[[self navigationController] setNavigationBarHidden:NO];
[FlurryAnalytics logEvent:#"GameViewController - viewWillAppear"];
[self getNewQuestion];
NSLog(#"ViewWillAppear finish");
[super viewWillAppear:YES];
}
I setup the UINavigationalController in the app delegate using the following code
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
HomeViewController *hv = [[HomeViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:hv];
// You can now release the itemsViewController here,
// UINavigationController will retain it
[hv release];
// Place navigation controller's view in the window hierarchy
[[self window] setRootViewController:navController];
[navController release];
// Override point for customization after application launch.
[self.window makeKeyAndVisible];
return YES;
}
UPDATE
I don't know what happened but last night after trying to run the app one more time in the simulator and its still having this issue, I decided to save everything and shut my computer down since it was getting late.
This morning I turned my computer back on opened up xcode, clean the project and build and run it and I the problem is fixed and -viewWillAppear is called. I didn't change anything and its working. I added NSLog in -willShowView and its not getting called. I don't know why all of a sudden viewWillAppear is being called.
Make sure your navigation controller's delegate is set and then use this function to call viewWillAppear in the class whose viewWillAppear you want to call:
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[self viewWillAppear:animated];
}
I've just hit a problem very much the same and after some testing discovered that calling popViewControllerAnimated: in a block (from a network response in AFNetworking) viewDidAppear isn't called in the parent view.
The solution that worked for me here was to call it in the main thread instead.
dispatch_async(dispatch_get_main_queue(), ^{
// If not called on the main thread then the UI doesn't invoke the parent view's viewDidAppear
[self.navigationController popViewControllerAnimated:YES];
});
I have just hit this problem as well the root cause of this problem is because I put self.navigationController.delegate = self on viewDidLoad. My solution is to put the delegation on viewWillAppear :
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.navigationController.delegate = self;
}
After that popViewController will hit viewWillAppear.
I'm trying to display an "About Page" in my application when pressing a button, but when I press the UIButton, the NSLog(#"Button pressed") is called, but the view won't load. Here is my code:
- (IBAction)pushAbout {
NSLog(#"Button pressed");
AboutView * aboutView = [[AboutView alloc] initWithNibName:#"AboutView" bundle:nil];
[self.navigationController pushViewController:aboutView animated:YES];
[aboutView release];
}
I've seen this code in an example, but it was called in a UITableViewController instead of an ordianry UIView controller.
The class files "AboutView" were created as UIViewController subclass. They were created and left untouched
A guess: Your view is not in a UINavigationController, hence
self.navigationController
is actually nil, and nothing happens.
The solution would be to place the main view in a nav controller, and adding the nav controller's view to your application's main window.
A simple way of doing this:
In your app delegate, change
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
to
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions
(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UINavigationController* navController = [[UINavigationController alloc]
initWithRootViewController:self.viewController];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
Or similar. Note that this is just to get you started, and maybe not the nicest way of doing it. (I assumed you've just created a view-based application in xcode.)
Yes you don't have a UINavigationController set.
Add
NSLog(#"nav? %#", self.navigationController);
to your action and you'll see that it dumps (null).
However, the AboutView.xib works fine if you enter this code:
[self presentModalViewController:aboutView animated:YES];
instead of
[self.navigationController pushViewController:aboutView animated:YES];
The view will show up. In you zipped example the AboutView.xib didn't contain a label, so don't wonder if it turns out to be a white page.
You can dismiss the presented modal view by using
[self dismissModalViewControllerAnimated:YES];
in your AboutViewController.
To get your hands on a UINavigationController I suggest creating an app with the Navigation-Based Application template.
I have the following code where I display a view controller within a navigation controller.
Just for the test I display it for 3 seconds and then dismiss it.
What is happening is that it disappearing - and then reappearing after a second or so.
What am I doign wrong?
- (void) test
{
[myNavCtrl dismissModalViewControllerAnimated:YES];
}
- (void) viewDidAppear:(BOOL)animated
{
MyViewController *ctrl = [[MyViewController alloc] init];
[ctrl setDelegate:self];
myNavCtrl = [[UINavigationController alloc] initWithRootViewController:ctrl];
[myNavCtrl setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentModalViewController:myNavCtrl animated:NO];
[ctrl release];
[myNavCtrl release];
[self performSelector:#selector(test) withObject:nil afterDelay:3];
}
The viewWillAppear method is called every time the controller's view appears so you've created a loop. The view appears, it calls the modal view which covers the calling view. When the modal view disappears, the calling view controller's viewWillAppear gets called again. Lather, rinse, repeat.