I am having a small problem.I have a view which should be set to hidden when the view loads is tried to add
[self.view setHidden:YES];
in viewWillAppear and the view is hiding but the Hiding of view is visible(it takes a split second to hide after the app is loaded).I need to hide the view without it visible.Help me ?
My full code in viewDidAppear
-(void)viewDidAppear:(BOOL)animated
{
#try {
NSLog(#"\n\n--------------Mainview Controller------------\n");
// Guided access mode call mainview in iOS7. It making issue in UI
[getStartBox setHidden:NO];
appDel.deviceModel=[self platformString];
if([MainView checkRegistrationStatus])
{
NSLog(#"Already registered....");
[main setGlobalValues];
if ([appDel.configArray count]==0)
{
NSLog(#"Load app sync page...");
[self.view setHidden :YES];
// [_mainView setHidden:YES];
AppSync *sync=[[AppSync alloc]initWithNibName:#"AppSync" bundle:nil];
sync.appSyncData = configureData;
[self presentViewController:sync animated:NO completion:nil];
}
else
{
NSLog(#"%#",appDel.logInStatus);
if([appDel.logInStatus isEqualToString:#"false"])
{
[self.view setHidden :YES];
// [_mainView setHidden:YES];
NSLog(#"Load login view controller...");
appDel.isEmergencyAlertOn=NO;
appDel.isRespondingToAlert=NO;
LogInViewController *loginView=[[LogInViewController alloc]initWithNibName:#"LogInViewController" bundle:nil];
[self presentViewController:loginView animated:NO completion:nil];
}
else if([appDel.logInStatus isEqualToString:#"true"])
{
NSLog(#"Load alert screen");
[self.view setHidden :YES];
// [_mainView setHidden:YES];
AlertScreen *alert=[[AlertScreen alloc]initWithNibName:#"AlertScreen" bundle:nil];
alert.alertData=notificationData;
[self presentViewController:alert animated:NO completion:nil];
}
}
}
else
{
appDel.domainName=nil;
// Version number reffered in settings page. The log enabled one should be in same format (Ex Version 1.0.53(log enabled))
versionLabel.text=#"Version 1.3(log enabled)";//(log enabled)
appDel.appVersion=versionLabel.text;
//self.view.layer.contents=(id)[[UIImage imageNamed:#"background.png"]CGImage];
[self.view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"background.png"]]];
ConfigureButton.hidden=NO;
}
}
#catch (NSException *exception) {
[[WriteLogger getWriteLogger] writeLog:moduleName sourceClass:self.nibName methodName:#"viewDidAppear" errorMsg:exception];
}
Related
I have a view with following configuration. by clicking a button the respective container view should move to the main screen with animation. If I am in portrait or landscape mode(only one of those) this works well but if I try to rotate iphone this does not work.
- (IBAction)button2Pressed:(UIButton *)button {
if(previousButton != button){
if([previousButton.titleLabel.text isEqualToString:#"1"])
[self viewLoadedIntoContainer:-self.container1.frame.size.width];
else if([previousButton.titleLabel.text isEqualToString:#"3"])
[self viewLoadedIntoContainer:self.container1.frame.size.width];
else
[self viewLoadedIntoContainer:self.container1.frame.size.width*2];
previousButton = button;
[self animateLabel:self.button2Outlet.frame.origin.x];
indexCount=1;
}}
- (IBAction)button1Pressed:(UIButton *)button {
if(previousButton != button){
if([previousButton.titleLabel.text isEqualToString:#"2"])
[self viewLoadedIntoContainer:self.container1.frame.size.width];
else if([previousButton.titleLabel.text isEqualToString:#"3"])
[self viewLoadedIntoContainer:self.container1.frame.size.width*2];
else
[self viewLoadedIntoContainer:self.container1.frame.size.width*3];
previousButton = button;
[self animateLabel:self.button1Outlet.frame.origin.x];
indexCount=0;
}}
- (IBAction)button3Pressed:(UIButton *)button {
if(previousButton != button){
if([previousButton.titleLabel.text isEqualToString:#"1"])
[self viewLoadedIntoContainer:-self.container1.frame.size.width*2];
else if([previousButton.titleLabel.text isEqualToString:#"2"])
[self viewLoadedIntoContainer:-self.container1.frame.size.width];
else
[self viewLoadedIntoContainer:self.container1.frame.size.width];
previousButton = button;
[self animateLabel:self.button3Outlet.frame.origin.x];
indexCount=2;
}}
- (IBAction)button4Pressed:(UIButton *)button {
if(previousButton != button){
if([previousButton.titleLabel.text isEqualToString:#"3"])
[self viewLoadedIntoContainer:-self.container1.frame.size.width];
else if([previousButton.titleLabel.text isEqualToString:#"2"])
[self viewLoadedIntoContainer:-self.container1.frame.size.width*2];
else
[self viewLoadedIntoContainer:-self.container1.frame.size.width*3];
previousButton = button;
[self animateLabel:self.button4Outlet.frame.origin.x];
indexCount=3;
}}
-(void)viewLoadedIntoContainer:(CGFloat)x{
__weak __typeof(self) weakSelf = self;
[UIView animateWithDuration:0.3f animations:^{
weakSelf.container1.layer.position = CGPointMake(weakSelf.container1.layer.position.x+(x), weakSelf.container1.layer.position.y);
weakSelf.container2.layer.position = CGPointMake(weakSelf.container2.layer.position.x+(x), weakSelf.container2.layer.position.y);
weakSelf.container3.layer.position = CGPointMake(weakSelf.container3.layer.position.x+(x), weakSelf.container3.layer.position.y);
weakSelf.container4.layer.position = CGPointMake(weakSelf.container4.layer.position.x+(x), weakSelf.container4.layer.position.y);
//[weakSelf.container1 setFrame:CGRectMake(weakSelf.container1.frame.origin.x+(x), weakSelf.container1.frame.origin.y, weakSelf.container1.frame.size.width, weakSelf.container1.frame.size.height)];
//[weakSelf.container2 setFrame:CGRectMake(weakSelf.container2.frame.origin.x+(x), weakSelf.container2.frame.origin.y, weakSelf.container2.frame.size.width, weakSelf.container2.frame.size.height)];
//[weakSelf.container3 setFrame:CGRectMake(weakSelf.container3.frame.origin.x+(x), weakSelf.container3.frame.origin.y, weakSelf.container3.frame.size.width, weakSelf.container3.frame.size.height)];
//[weakSelf.container4 setFrame:CGRectMake(weakSelf.container4.frame.origin.x+(x), weakSelf.container4.frame.origin.y, weakSelf.container4.frame.size.width, weakSelf.container4.frame.size.height)];
}completion:^(BOOL finished) {
//[weakSelf.container1 layoutIfNeeded];
}];
}
I am using 4 container views. Should I use 4 container views which are of same height and width and lies on top of each other. Or should I use 4 view controller which are linked to single container view using custom segue?
It really depends on exactly on the specifics of what each view/view controller does.
But generally speaking; I usually make each "screen" (full frame view) its own UIViewController. I usually make subviews of a screen UIViews.
I have a UIViewController on an iPad that I am displaying modally.
However after dismissing it, the view controller that displayed it does not change in orientation and acts as if the underlying view controller did not change, unless the device is rotated back and forth.
I'm using these methods in the modal view controller:
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation {
[self updateUI];
return YES;
}
- (BOOL)shouldAutorotate {
[self updateUI];
return YES;
}
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAll;
}
-(void) updateUI{
}
The underlying UINavigationController code (the one that doesn't change itself properly once the modal view controller is dismissed):
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation {
[self adjustUIForOrientation:interfaceOrientation];
return YES;
}
- (BOOL)shouldAutorotate {
[self adjustUIForOrientation:[self preferredInterfaceOrientationForPresentation]];
return YES;
}
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAll;
}
- (void) adjustUIForOrientation: (UIInterfaceOrientation)interfaceOrientation {
if(UIDeviceOrientationIsPortrait(interfaceOrientation)) {
[_landscapeTemplate hide];
[_portraitTemplate show];
_activeTemplate = _portraitTemplate;
} else {
[_portraitTemplate hide];
[_landscapeTemplate show];
_activeTemplate = _landscapeTemplate;
}
}
-(IBAction) signInButtonTouched: (id) sender{
if (![Session shared].loggedInUser){
UserProfileLoginViewController *userProfileLoginVC = [[[UserProfileLoginViewController alloc] initWithNibName:#"UserProfileLoginViewController" bundle:nil] autorelease];
userProfileLoginVC.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
self.modalPresentationStyle = UIModalPresentationCurrentContext;
//self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:userProfileLoginVC animated:YES completion:nil];
// [self pushViewController:userProfileLoginVC animated:YES];
[userProfileLoginVC.emailTextField becomeFirstResponder];
}
else [[Session shared] explicitEnd];
}
Is there a way to make this work? Basically it appears that the view controller that presented the modal view controller is not getting the rotation calls forwarded to itself.
I'm using GKAchievementViewController to display achievements. It works fine on most devices, but on some (iPod Touch 3rd Gen and iPad 1 running iOS 5.1.1) taping the Done button does nothing.
I have no idea how to debug this...
Here is the code I'm using to display the achievements:
viewController = [[GKAchievementViewController alloc] init];
if (viewController)
{
viewController.achievementDelegate = self;
[self presentModalViewController:viewController animated:YES];
}
and then:
- (void)achievementViewControllerDidFinish:(GKAchievementViewController *)aViewController
{
[self dismissModalViewControllerAnimated:YES];
}
Should work when implementing achievementViewControllerDidFinish:
- (void) achievementViewControllerDidFinish:(GKAchievementViewController *)viewController
{
[viewController.delegate dismissModalViewControllerAnimated:YES];
}
Answering my own question in case anyone has the same problem.
This seems to have solved the issue:
- (void)achievementViewControllerDidFinish:(GKAchievementViewController *)aViewController
{
if ([self respondsToSelector:#selector(dismissViewControllerAnimated:completion:)])
{
[self dismissViewControllerAnimated:YES completion:^{
aViewController.achievementDelegate = nil;
[aViewController release];
}];
}
else
{
[self dismissModalViewControllerAnimated:YES];
aViewController.achievementDelegate = nil;
[aViewController release];
}
}
I'm trying to have something similar to a UINavigationController so I can customize the animations. To start, I'm just using Apple stock animations. Here's my containerViewController:
- (void)loadView {
// Set up content view
CGRect frame = [[UIScreen mainScreen] bounds];
_containerView = [[UIView alloc] initWithFrame:frame];
_containerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.view = _containerView;
}
- (id)initWithInitialViewController:(UIViewController *)vc {
self = [super init];
if (self) {
_currentViewController = vc;
[self addChildViewController:_currentViewController];
[self.view addSubview:_currentViewController.view];
[self didMoveToParentViewController:self];
_subViewControllers = [[NSMutableArray alloc] initWithObjects:_currentViewController, nil];
}
return self;
}
- (void)pushChildViewController:(UIViewController *)vc animation:(UIViewAnimationOptions)animation {
vc.view.frame = _containerView.frame;
[self addChildViewController:vc];
[self transitionFromViewController:_currentViewController toViewController:vc duration:0.3 options:animation animations:^{
}completion:^(BOOL finished) {
[self.view addSubview:vc.view];
[vc didMoveToParentViewController:self];
[self.subViewControllers addObject:vc];
}];
}
- (void)popChildViewController:(UIViewController *)vc WithAnimation:(UIViewAnimationOptions)animation {
// Check that there is a view controller to pop to
if ([self.subViewControllers count] <= 0) {
return;
}
NSInteger idx = [self.subViewControllers count] - 1;
UIViewController *toViewController = [_subViewControllers objectAtIndex:idx];
[vc willMoveToParentViewController:nil];
[self transitionFromViewController:vc toViewController:toViewController duration:0.3 options:animation animations:^{
}completion:^(BOOL finished) {
[vc.view removeFromSuperview];
[vc removeFromParentViewController];
[self didMoveToParentViewController:toViewController];
[self.subViewControllers removeObjectAtIndex:idx];
}];
}
I have this ContainerViewcontroller as my rootViewController of the window. I can add my initial viewController and push a view controller. When I try to pop though, I get
ContainerViewController[65240:c07] Unbalanced calls to begin/end appearance transitions for <SecondViewController: 0x8072130>.
I'm wondering what I am doing wrong. I figured my initialViewController is still underneath the secondViewController. Any thoughts? Thanks!
I don't know if this is what's causing your problem, but shouldn't this:
[self didMoveToParentViewController:toViewController];
be:
[toViewController didMoveToParentViewController:self];
Also, I'm not sure what you're doing with the subViewControllers array. It seems to be a duplication of the childViewControllers array that is already a property of a UIViewController.
One other thing I'm not sure is right. In your pop method your toViewController is the last controller in the _subViewControllers array. Don't you want it to be the second to last? Shouldn't the last be the one you're popping? You're popping vc, which is a controller you're passing in to the method, I don't understand that.
This is the way I've made a navigation like controller. In its containment behavior, it acts like a navigation controller, but without a navigation bar, and allows for different transition animations:
#implementation ViewController
-(id)initWithRootViewController:(UIViewController *) rootVC {
if (self = [super init]) {
[self addChildViewController:rootVC];
rootVC.view.frame = self.view.bounds;
[self.view addSubview:rootVC.view];
}
return self;
}
-(void)pushViewController:(UIViewController *) vc animation:(UIViewAnimationOptions)animation {
vc.view.frame = self.view.bounds;
[self addChildViewController:vc];
[self transitionFromViewController:self.childViewControllers[self.childViewControllers.count -2] toViewController:vc duration:1 options:animation animations:nil
completion:^(BOOL finished) {
[vc didMoveToParentViewController:self];
NSLog(#"%#",self.childViewControllers);
}];
}
-(void)popViewControllerAnimation:(UIViewAnimationOptions)animation {
[self transitionFromViewController:self.childViewControllers.lastObject toViewController:self.childViewControllers[self.childViewControllers.count -2] duration:1 options:animation animations:nil
completion:^(BOOL finished) {
[self.childViewControllers.lastObject removeFromParentViewController];
NSLog(#"%#",self.childViewControllers);
}];
}
-(void)popToRootControllerAnimation:(UIViewAnimationOptions)animation {
[self transitionFromViewController:self.childViewControllers.lastObject toViewController:self.childViewControllers[0] duration:1 options:animation animations:nil
completion:^(BOOL finished) {
for (int i = self.childViewControllers.count -1; i>0; i--) {
[self.childViewControllers[i] removeFromParentViewController];
}
NSLog(#"%#",self.childViewControllers);
}];
}
After Edit: I was able to duplicate the back button function with this controller by adding a navigation bar to all my controllers in IB (including in the one that is the custom container controller). I added a bar button to any controllers that will be pushed, and set their titles to nil (I got some glitches if I left the title as "item"). Deleting that title makes the button disappear (in IB) but you can still make connections to it in the scene list. I added an IBOutlet to it, and added this code to get the function I wanted:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (self.isMovingToParentViewController) {
self.backButton.title = [self.parentViewController.childViewControllers[self.parentViewController.childViewControllers.count -2] navigationItem].title;
}else{
self.backButton.title = [self.parentViewController.childViewControllers[self.parentViewController.childViewControllers.count -3] title];
}
}
I've shown two different ways that worked to access a title -- in IB you can set a title for the controller which I used in the else clause, or you can use the navigationItem title as I did in the if part of the clause. The "-3" in the else clause is necessary because at the time viewWillAppear is called, the controller that is being popped is still in the childViewControllers array.
addChildViewController should be called first
For adding / removing, you can refer to this great category and have no worry when to call it:
UIViewController + Container
- (void)containerAddChildViewController:(UIViewController *)childViewController {
[self addChildViewController:childViewController];
[self.view addSubview:childViewController.view];
[childViewController didMoveToParentViewController:self];
}
- (void)containerRemoveChildViewController:(UIViewController *)childViewController {
[childViewController willMoveToParentViewController:nil];
[childViewController.view removeFromSuperview];
[childViewController removeFromParentViewController];
}
In addition to rdelmar's answer you should not be calling addView/removeFromSuperview transitionFromViewController does this for you, from the documentation:
This method adds the second view controller’s view to the view
hierarchy and then performs the animations defined in your animations
block. After the animation completes, it removes the first view
controller’s view from the view hierarchy.
I've made a test app to familiarize myself with making a custom container view controller. If I rotate the device when the app first starts or after switching to a different view controller, the new view resizes to take up the whole screen, as I intended. However, if I rotate after the app starts, and then switch to a new view controller, the view keeps its portrait size instead of getting shorter and wider (actually it's slightly different -- it goes from 320,460 to 300,480). The master view controller is alloc init'd in the app delegate (no xib) and set as the window's root view controller. Here is the code I have in my MasterViewController (the custom container controller):
- (void)viewDidLoad {
[super viewDidLoad];
WelcomeController *welcome = [[WelcomeController alloc] initWithNibName:#"ViewController" bundle:nil];
self.currentController = welcome;
[self addChildViewController:welcome];
[self.view addSubview:welcome.view];
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeLeft:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:swipeLeft];
}
- (void)swipeLeft:(UISwipeGestureRecognizer *)gesture {
if (gesture.state == UIGestureRecognizerStateRecognized) {
UIActionSheet *sheet =[[UIActionSheet alloc] initWithTitle:#"Select A Destination" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"welcome",#"Play",#"Scores", nil];
[sheet showInView:self.view];
}
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
switch (buttonIndex) {
case 0:{
if ([self.currentController class] != [WelcomeController class] ) {
WelcomeController *welcome = [[WelcomeController alloc] initWithNibName:#"ViewController" bundle:nil];
[self addChildViewController:welcome];
[self moveToNewController:welcome];
}
break;
}
case 1:{
if ([self.currentController class] != [PlayViewController class] ) {
PlayViewController *player = [[PlayViewController alloc] initWithNibName:#"PlayViewController" bundle:nil];
[self addChildViewController:player];
[self moveToNewController:player];
}
break;
}
case 2:{
if ([self.currentController class] != [HighScores class] ) {
HighScores *scorer = [[HighScores alloc] initWithNibName:#"HighScores" bundle:nil];
[self addChildViewController:scorer];
[self moveToNewController:scorer];
}
break;
}
case 3:
NSLog(#"Cancelled");
break;
default:
break;
}
}
-(void)moveToNewController:(id) newController {
[self.currentController willMoveToParentViewController:nil];
[self transitionFromViewController:self.currentController toViewController:newController duration:.6 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{}
completion:^(BOOL finished) {
[self.currentController removeFromParentViewController];
[newController didMoveToParentViewController:self];
self.currentController = newController;
}];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;//(interfaceOrientation == (UIInterfaceOrientationPortrait | UIInterfaceOrientationLandscapeLeft));
}
Any ideas why this is happening (I don't know if this means that the master view controller's view isn't resizing, but when I get this non-resizing behavior the gesture recognizer only responds in the narrow view, not over the whole screen)?
You are not sending rotation messages to your child view controllers. At least not in the code you posted. After switching Child Controller you are even removing previous child from ChildViewControllers array with [self.currentController removeFromParentViewController] so even if you implement - (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers you have always only one ChildViewController in your ParentViewController.
I have got this working, so i will paste you how am i doing this. First i create all my ViewControllers, add them as child view controllers to ParentViewController. Then call didMoveToParentViewController: method.
//Controller1
Controller1 *c1 = [[Controller1 alloc] init];
c1.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self addChildViewController:c1];
[c1 didMoveToParentViewController:self];
//Controller2
Controller2 *c2 = [storyboard instantiateViewControllerWithIdentifier:#"c2"];
index.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self addChildViewController:c2];
[c2 didMoveToParentViewController:self];
c2.view.frame = m_contentView.frame;
[self.view addSubview:c2.view]; //It is in initial screen so set it right away
m_selectedViewController = c2;
//Controller3
Controller3 *c3 = [storyboard instantiateViewControllerWithIdentifier:#"c3"];
compare.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self addChildViewController:c3];
[c3 didMoveToParentViewController:self];
m_controllers = [NSArray arrayWithObjects:c1, c2, c3, nil]; //Hmm now i think this is not needed, I can access viewController directly from self.childViewControllers array
Then I implemented
- (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers
{
return YES;
}
Switching to child view controller is done with this code
if (value < m_controllers.count)
{
UIViewController *contentViewController = [m_controllers objectAtIndex:value];
contentViewController.view.frame = m_contentView.frame;
[self transitionFromViewController:m_selectedViewController toViewController:contentViewController duration:0 options:UIViewAnimationOptionTransitionNone animations:nil completion:^(BOOL finished) {
m_selectedViewController = contentViewController;
}
];
}
This should be enough. But i have got some issues with this so i send rotation messages to unactive Childs myself.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
for (UIViewController *vc in m_controllers)
{
if(vc != m_selectedViewController)
[vc willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
for (UIViewController *vc in m_controllers)
{
if(vc != m_selectedViewController)
[vc willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
for (UIViewController *vc in m_controllers)
{
if(vc != m_selectedViewController)
[vc didRotateFromInterfaceOrientation:fromInterfaceOrientation];
}
}
manually added
self.view.autoresizesSubviews = YES;
inside
- (void)viewDidLoad
and it solved the problem,
for some reason the value inside storyboard was not being used i guess