I used to initialize my UIViewController in - (void) viewDidLoad.
Since the update to iOS 7 the viewDidLoad method is either not called or after executing setItemAndParents.
Example:
I have a UITableViewController if you click on a cell the desired view is loaded:
- (void)tableView: (UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath {
// some more code
[cpvc setItemAndParents:items[selectedIndex] orderIndex:indexOrder];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
cpvc = segue.destinationViewController;
}
Where am I supposed to initialize the ViewController.
Remember with iOS 6 everything worked find.
Had similar problem.
I inserted this right after allocation of viewController (or in some case after pushViewController):
viewController.view.hidden = NO;
and it calls viewDidLoad.
Hope I helped.
Yup it happens to me also... You can initialized view controller in - (void)awakeFromNib{} method. This method help me in the same scenario as you have.
Related
my application has a UIViewController that isn't wrapped in a UINavigationController from it I call different UINavigationControllers each representing a state in a state machine.
calling these UINavigationControllers from code is done like this:
-(void) callState1
{
[popover dismissPopoverAnimated:YES];
UINavigationController *state1NavigationController = [self.storyboard instantiateViewControllerWithIdentifier:#"state1Navigation"];
[self presentViewController:state1NavigationController animated:NO completion:nil];
}
in state1 there is a custom UIBarButtonItem representing the back control.
self.navigationItem.leftBarButtonItem = self.backBtn;
Is there a native code that returns to the calling UIViewController?
or should I implement the same code from callState1 in the back button calling the UIViewController, and if so how can I synchronize the data between them?
Since you are presenting the view controller (state1NavigationController) modally, you need to use the method dismissViewControllerAnimated:completion: to dismiss the state1NavigationController and go back.
In our App we have a log-in ViewController A. On user log-in, a request navigate is automatically called to navigate to the next ViewController B. However when this is done we want to remove the log-in ViewController A from the stack so the user cannot "go back" to the log-in view but goes back the previous ViewController before the log-in instead.
We thought about removing the ViewController A from the stack when ViewController B is loaded, but is there a better way?
In the Android version of the App we've set history=no (if I recall correctly) and then it works.
Is there an similar way to achieve this in MonoTouch and MvvmCross?
I ended up with removing the unwanted viewcontroller from the navigation controller. In ViewDidDisappear() of my login ViewController I did the following:
public override void ViewDidDisappear (bool animated)
{
if (this.NavigationController != null) {
var controllers = this.NavigationController.ViewControllers;
var newcontrollers = new UIViewController[controllers.Length - 1];
int index = 0;
foreach (var item in controllers) {
if (item != this) {
newcontrollers [index] = item;
index++;
}
}
this.NavigationController.ViewControllers = newcontrollers;
}
base.ViewDidDisappear(animated);
}
This way I way remove the unwanted ViewController when it is removed from the view. I am not fully convinced if it is the right way, but it is working rather good.
This is quite a common scenario... so much so that we've included two mechanisms inside MvvmCross to allow this....
a ClearTop parameter available in all ViewModel navigations.
a RequestRemoveBackStep() call in all ViewModels - although this is currently NOT IMPLEMENTED IN iOS - sorry.
If this isn't enough, then a third technique might be to use a custom presenter to help with your display logic.
To use : 1. a ClearTop parameter available in all ViewModel navigations.
To use this, simply include the ClearTop flag when navigating.
This is a boolean flag - so to use it just change:
this.RequestNavigate<ChildViewModel>(new {arg1 = val1});
to
this.RequestNavigate<ChildViewModel>(new {arg1 = val1}, true);
For a standard simple navigation controller presenter, this will end up calling ClearBackStack before your new view is shown:
public override void ClearBackStack()
{
if (_masterNavigationController == null)
return;
_masterNavigationController.PopToRootViewController (true);
_masterNavigationController = null;
}
from https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.Touch/Views/Presenters/MvxTouchViewPresenter.cs
If you are not using a standard navigation controller - e.g. if you had a tabbed, modal, popup or split view display then you will need to implement your own presentation logic to handle this.
You can't: 2. RequestRemoveBackStep().
Sadly it proved a bit awkward to implement this at a generic level for iOS - so currently that method is:
public bool RequestRemoveBackStep()
{
#warning What to do with ios back stack?
// not supported on iOS really
return false;
}
from https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.Touch/Views/MvxTouchViewDispatcher.cs
Sorry! I've raised a bug against this - https://github.com/slodge/MvvmCross/issues/80
3. You can always... Custom ideas
If you need to implement something custom for your iOS app, the best way is to do this through some sort of custom Presenter logic.
There are many ways you could do this.
One example is:
for any View or ViewModel which needs to clear the previous view, you could decorate the View or ViewModel with a [Special] attribute
in Show in your custom Presenter in your app, you could watch for that attribute and do the special behaviour at that time
public override void Show(MvxShowViewModelRequest request)
{
if (request.ViewModelType.GetCustomAttributes(typeof(SpecialAttribute), true).Any())
{
// do custom behaviour here - e.g. pop current view controller
}
base.Show(request);
}
Obviously other mechanisms might be available - it's just C# and UIKit code at this stage
I don't know about mvvm but you can simply Pop the viewcontroller (AC A) without animation and then push the new viewcontoller (AC B) with animation
From within AC A:
NavigationController.PopViewControllerAnimated(false);
NavigationController.PushViewController(new ACb(), true);
My scenario is a UIView Controller displays different subview programmatically... Like a game board. Now I'm in a incredible situation:
I can't find a way to reload application after the game is finish!? What I would like to do is after terminate scenario clic on IBAction for star new game. My doubt is about ViewDidLoad or call Main.
try moving your code from viewDidLoad into a new function like -(void)startGame or -(void)refreshViews: and call that function whenever you want to reload your view. even in viewDidLoad you can load your view using this function.
-(void)viewDidLoad
{
[super viewDidLoad];
[self startGame];
}
remember if you are creating allocating and add some of your subviews outside this function then they will remain visible untill and unless yu remove them from superView before calling startGame.
I solved it with this code:
(IBAction)newGame:(id)sender{
UIView *parent = self.view.superview;
[self.view removeFromSuperview];
self.view = nil; // unloads the view
[parent addSubview:self.view];
}
I am trying to add a View Controller to the Appdelegate Class. My code goes this way..
[self.view addsubView:viewcontroller.view];
But unfortunately i am not able to view the controller view. Please suggest if i am going wrong somewhere.Thanks for ur time.
The method in AppdidFinishLaunching is:-
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
// [self.window addSubview:videoController.view];
self.window.rootViewController = videoController;
[self.window makeKeyAndVisible];
return YES;
}
and in the Load view of ViewController i have written as
UIButton *playMovie = [UIButton buttonWithType:UIButtonTypeRoundedRect];
playMovie.frame = CGRectMake(70,30,100,50);
[playMovie setTitle:#"Play Movie" forState:UIControlStateHighlighted];
[playMovie addTarget:self action:#selector(playMovie:) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:playMovie];
The problem here is i am not able to view the button and the view.Please help.
Under no circumstances should you ever add a view controller's view manually to the interface like this. The app delegate is not, itself, a view controller; so viewcontroller is not its child. So the view is not yours to add. Use view controllers correctly: a view controller is either your app window's rootViewController, or it is some other view controller's child - and in either case, its view is placed into the interface for you automatically.
If this view is intended to be the root view of the app, then do what the Xcode 4.2 project templates do (e.g. the Single View Application): instantiate the view controller and assign it as self.window.rootViewController. If not, you must not use a view controller to add it as a subview as you are trying to do; just obtain the view and add it, without the intervening view controller.
It might help you to read my chapter on view controllers: http://www.apeth.com/iOSBook/ch19.html
Try below it works for me,
SFRmbrVC *viewController=[[SFRmbrVC alloc]initWithNibName:#"SFRmbrVC" bundle:nil];
[self.window.rootViewController addChildViewController:viewController];
viewController.parentController = self.window.rootViewController;
viewController.view.frame = self.window.rootViewController.view.frame;
[self.window.rootViewController.view addSubview:viewController.view];
viewController.view.alpha = 0;
[viewController didMoveToParentViewController:self.window.rootViewController];
[UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^
{
viewController.view.alpha = 1;
}
completion:nil];
The best steps to work out with this are
Create your own delegate and make an instance in the AppDelegate
eg.
#protocol MyAppDelegate <NSObject>
#optional
- (void)myApplicationWillResignActive:(UIApplication *)application;
#end
Make a call's of your delegate in the MyAppdelegate
eg.
- (void)applicationWillResignActive:(UIApplication *)application {
[myDelegate myApplicationWillResignActive:application]
}
Implement it in your viewController class (ViewController).
4.assign you viewController class instance to myAppdelegate instance in AppDelegate
eg.
MyAppDelegate*myDelegate=(MyAppDelegate*)[[UIApplication sharedApplication] delegate];
myDelegate=self; //self=viewController class
I have a UIViewController which contains a new UIViewController like below,
#implementation ParentViewController
- (id)init
{
// some stuff
}
- (BOOL)CreateChildViewController
{
UIViewController *childVC = [[UIViewController alloc] init];
}
#end
Now i need to stop interfaceOrientation of childVC.
Is it possible, if so how??
Try using:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
to any view controller to determine auto rotate behaviour.
From the documentation:
By default, this method returns YES for the UIInterfaceOrientationPortrait orientation only. If your view controller supports additional orientations, override this method and return YES for all orientations it supports.
In short, if you subclass UIViewController and only want to support portrait, you don't need to do anything. Otherwise you will need to add this method and decide whether to allow rotation to another orientation.
Read the section titled "Handling View Rotations".