Trying to dismiss subview and UIView - objective-c

I'm still very new to iOS developing. In fact, if there is a super noob, I would be one :p. Currently I am working on creating an IBAction button that accesses a subview. I have 2 ViewControllers, AddClientVC and NewClientVC, both with .nib files. So basically, inside my AddClientVC I implement an IBAction button with the following code:
- (IBAction)buttonPressed:(id)sender
{
UIView *transparentBG = [[UIView alloc] initWithFrame:CGRectMake(-5, -5, 1500, 2500)];
transparentBG.backgroundColor = [UIColor blackColor];
transparentBG.opaque = NO;
transparentBG.alpha = 0.5;
[self.view addSubview:transparentBG];
transparentBG.center = transparentBG.center;
vc = [[NewClientVC alloc] initWithNibName:#"NewClientVC" bundle:nil];
[self.view addSubview:vc.view];
vc.view.center = self.view.center;
}
As you can see I implemented a UIView as a transparent background. Basically AddClientVC --> Transparent Background --> NewClientVC. Now I have created another IBAction button but this time inside NewClientVC as a function to dismiss the accessed subview which looks like this:
- (IBAction)saveDismiss:(id)sender
{
[self.view removeFromSuperview];
}
The problem I'm having right now is when I click the saveDismiss button it only removes the subview that I called previously on AddClientVC but it didn't remove the transparent background I have created as a UIView. So the problem is how do I implement an action which simultaneously removes my subview and the UIView transparent background I created.
I need all the help I can get :)

I'm not too sure I fully understand what you want to happen, but maybe you could try something like this?
- (IBAction)saveDismiss:(id)sender
{
[vc removeFromSuperView];
[self.view removeFromSuperview];
}

I recommend not to manage your screens by adding subviews manually but instead use
- (void)presentModalViewController: (UIViewController *)modalViewController
animated: (BOOL)animated
method on your root viewController.
Or better instantiate a UINavigationController and use push and pop methods to drill down/up your views.
See apple reference here

Do not worry about code execution speed and stay confident in apple's SDK. UIKit is optimized for best user experience. Trying to boost your code by doing inappropriate SDK use is, in my opinion, a risky strategy. ;) – Vincent Zgueb
Sorry Vincent but I don't agree with you. I reached here because I want to implement an gesture that adds a sub-view for my view, which will be the navigation of my app.
[self.view addSubview:ctrl.view];
is faster presenting the view than
[self.navigationController presentModalViewController:ctrl animated:NO]
and by the way, the solution to the topic in my case was:
[self.view sendSubviewToBack:ctrl.view];

Related

How to add UIView as a subview on UIViewController in UIStoryboard

Is there any way that I can add uiview as a subview over a view controller using UIStoryboard, using xib's we can do that, but i'm unable do that using storyboard.
My storyboard is not holding any of the uiview as a subview when I drag and drop on it, it was placing under the view controller.
Is there any way that I can add it programmatically on my view controller using storyboard.? I'm stuck please help me out
Am I right, you want to hold UIView in storyboards without view controller or superview ?
You can't do that. You should use XIBs to hold custom views.
It doesn't matter you add it programmatically or via drag and drop, in storyboards you can't hold "isolated" views, every view must have a superview and therefore a UIViewController.
Check apple's guide, make sure you understand UIViewController,UIView,UIStoryboard classes and relations between them. Also this.
Hope it helped.
Yes, you can override UIViewController's loadView method to do it as i have written code below.
Because loadView is the method which is called first of all other viewController's loading methods. So you can set it here.
Hope this will work for you as I have tested it on my code.
- (void)loadView {
self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, [UIScreen mainScreen].bounds.size.height)];
self.view.backgroundColor = [UIColor blackColor];
// enter your customization code here
}
write this line in function
-(void) ViewDidLoad:
[self.view addSubView:...];

Using buttons on different views and classes to trigger view switch from the main view controller

I am using storyboard to create my page.. each with it's own class... from the mainViewController, I manage the view change with a swipe gesture recognizer... So far so good... But I have certain pages that will appear as "popup" when swiping up and to get rid of them, the user clicks on the X to remove the view... the thing is that doing this and releasing the view from superview is giving me a white screen as the switch is not done by the mainViewController, since the view is release by the popup class... I think I need to use some sort of delegation to do this.. but my brain just doesn't want to sink in how to use the delegate thing, even after reading about it...
Since the view switching is done on index 1, i'd figure that if I put those popup on index 2 and release them, the view at index 1 would still be there, but.. no..
... so at the beginning of my swipe gesture function, I start declaring the animation process... then I have a switch...case that check for the gesture being done.. left will set the animation to curlUP and right to Curl down... this is what happens after the switch... I also put myView into a myViewTemp, and add the new view to myView in the switch..case statement..
if (myView.title == #"popup1") {
[myView viewWillAppear:YES];
[myViewTemp viewWillDisappear:NO];
// [myViewTemp.view removeFromSuperview];
[self.view insertSubview:myView.view atIndex:2];
[myViewTemp viewDidDisappear:NO];
[myView viewDidAppear:YES];
} else {
[myView viewWillAppear:YES];
[myViewTemp viewWillDisappear:YES];
[myViewTemp.view removeFromSuperview];
[self.view insertSubview:myView.view atIndex:1];
[myView viewDidDisappear:YES];
[myViewTemp viewDidAppear:YES];
}
[UIView commitAnimations];
}

Issues with changing UINavigationBar background when presenting modal view controller

I am using this method to change the backgrounds of my uiviewcontrollers. It generally works when I push a view controller.
However, if the viewcontroller is presented using
[self presentModalViewController:customViewController animated:YES];
then, this code doesnt work. Can anyone kindly suggest whats wrong ?
Code used:
To have an image in the navigation bar, you have to draw it yourself, which actually isn't that hard. Save this as UINavigationBar+CustomBackground.m (it adds a custom category to UINavigationBar):
#implementation UINavigationBar (CustomBackground)
- (void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed:#"NavMain.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
#end
If you are running on iOS 5, then drawRect: is no longer called
You will need to either use the UIAppearance or subclass UINavigationController and use that to change to you image.
A tutorial for UIAppearance can be found here
(drawRect: will still work on versions below iOS 5)
Try this ,
UIColor *image = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"imagename.png"]];
replace image name.
not sure if this is it but have you tried
[self presentViewController:customViewController animated:YES completion:NULL]
And setting whatever modalViewStyle you deem appropriate for customViewController? According to the iOS documentation, presentModalViewController is deprecated, so you may have better luck using the above message call (especially since you only seem to be having this issue with modal view controllers)
You have to create a navigation controller, set the root controller and present it.
e.g.
UIViewController *vc = [[UIViewController alloc] init];
UINavigationController *cntrol = [[UINavigationController alloc] initWithRootViewController:vc];
[self presentModalViewController:cntrol animated:YES];
The method you is to set the navigation bar image in navigation controller.
But The new view controller you present is not using navigation method. Instead, you use Modal view Controller.
I have two solution for you:
--- 1 -----
still use Modal View Controller, just add that image on the top of new view controller.
[self.view addSubview:theImage];
---- 2 -----
use
[self.navigationController pushViewController:customViewController animated:YES];
instead of
[self presentModalViewController:customViewController animated:YES];
In this case, you are using navigation.
I will suggest the second one.

Is this a correct way to add/remove views?

Lets say that I have 4 view controllers (call them FirstView,SecondView,ThirdView,FourthView) which are created programmatically and all are in separate files:
In AppDelegate.m didFinishLaunchingWithOptions method I have these lines of code
self.rootViewController = [[rootViewController alloc]initWithNibName:#"rootViewController" bundle:nil];
self.window.rootViewController = self.rootViewController;
In rootViewController.m loadview method I have
self.view = [[UIView alloc]initWithFrame:[UIScreen mainScreen].applicationFrame];
self.firstView = [[FirstView alloc]init];
[self.view addSubview:self.firstView.view];
That code works fine - first view is displayed.
Let's continue
In FirstView.m switchViews method
NOTE: Please see the comments in code
self.secondView = [[SecondView alloc] initWithNibName:#"SecondView" bundle:nil];
// I think here secondView is added to rootViewController - right ?
[self.view.superview addSubview:self.secondView.view];
// Here first view is removed from rootViewController - right ?
[self.view removeFromSuperview];
Here is how I add/remove views.
Is this approach correct?
Can you recommend a better solution?
I have read about UINavigationController, but I don't think it could be a solution in this case.
You say:
I have 4 views (call them FirstView ...
Then you say:
[self.view addSubview:self.firstView.view];
Which makes me think that FirstView isn't actually a UIView - as you claim it is. Instead, it's probably a UIViewController - a different beast altogether.
If my suspicion is correct - then you are "off-track" so to speak.
Going beyond that to your sample code snippet:
self.secondView = [[SecondView alloc] initWithNibName:#"SecondView" bundle:nil];
// I think here secondView is added to rootViewController - right ?
[self.view.superview addSubview:self.secondView.view];
// Here first view is removed from rootViewController - right ?
[self.view removeFromSuperview];
This is definitely not a great idea. Here's why:
First: your view controller doesn't explicitly "know" anything about the superview you are so casually inserting and removing subviews to/from - so it shouldn't do that. You may, alternatively, create your own view and insert/remove subviews from that - which would not only be perfectly acceptable but also common practice.
Second: if these are actually UIViewControllers like I think they are - then you are not properly handling hooking them up to the UIViewController event chain - which means methods on these subclasses like viewDidAppear: or viewDidUnload will not fire.
From what I see in your code, UINavigationController seems like it would help. If you don't want a navigation bar, you can definitely hide it, but the methods in UINavigationController should help you with switching views.
If your views only need to display temporarily, you could also use Modal View controllers. An example of Modal View controllers can be found here.
If you haven't already, check out the View Controller Programming Guide from Apple.

Which is the best implementation to allege code for all viewXXX selectors?

first of all: my question is very theoretical. Even if I post an example, I just want to know which implementation is the best one to solve this kind of problem. Maybe you will laugh when you read this question because it is very fundamentally - but I want to understand how to deal with such a situation.
Imagine the following: You have got an application which communicates with an extern API via XML. As a fact of this the view cannot appear immediately, because the API needs time to react. My idea was to implement a subview which contains a loading animation. When the API sends a response this subview is removed and the main view appears. Here is my example:
- (void)viewWillAppear:(BOOL)animated {
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
[myView setBackgroundColor:[UIColor whiteColor]];
myView.tag = 1;
UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
loadingView.frame = CGRectMake(145, 160, 25, 25);
[myView addSubview:loadingView];
[self.view addSubview:myView];
[loadingView startAnimating];
}
- (void)viewDidAppear:(BOOL)animated
{
[self loadXMLData];
[self.tableView reloadData];
[[self.view viewWithTag:1] removeFromSuperview];
}
Everthing works fine. My problem is the following: it's not only this view where I have to do that. My applications consists of many views, so what is the best way to avoid repeating this code? I thought about following: I modify the (UIKit UIViewController) viewDidAppear selector and put the code in it. I don't know if Apple allows to change their frameworks. Furthermore it looks very dirty to me ;o) Is someone able to tell me how this is usually done? Thank you!
( hope you understand me, my first language is not English :-( )
Why not just make a subclass of UIViewController which has this code implemented in viewWillAppear and viewDidAppear, and then inherit every other view controller in the application from this "base" subclass rather than UIViewController? That will be much easier than trying to do anything to UIViewController directly.