UIViewController loses track of property - ios

In my first ViewController having property
#property (nonatomic, strong) UIView* snapShotView;
And I call
self.snapShotView = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:YES];
[self.view addSubview: self.snapShotView];
Then I present two viewcontrollers on top of it and dismiss them again. When I am back on the first viewController the snapShotView property is empty, but the view still displays. I want to remove the snapShotView, but I no longer have a reference.
If I only display one ViewController on top of the first ViewController and dismiss it, the property still references the correct view. If I present and dismiss another view on top of it, the property is null once the additional two ViewControllers are dismissed.
How can I reference and remove the snapshoView?

It is really strange that you are loosing the reference to subView, but anyway if you are loosing the reference to subView and because of that if you are not able to remove the subView you added and if that's your problem, I'll say you don't need the reference to remove the subView from view :)
You can do something like this :)
[[self.view subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
This statement will remove all the subViews from your view without reference :)
and in case you have multiple views added to your view and want to remove just a specific view make use of tags :)
self.snapShotView = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:YES];
self.snapShotView.tag = someValue;
[self.view addSubview: self.snapShotView];
and while removing
for (UIView *view in [self.view subviews]) {
if (view.tag == someValue) {
[view removeFromSuperview];
}
}

Related

Remove view of particular class from window

Is there anyway to remove a view from the uiapplication window of a particular class?
I have a class called MainView that is the top header bar for the app on the main screen. I have a view that gets added after that where users can swipe up and down to different screens but on the screen where a user swipes up or down too the MainView bar at the top needs to be removed. How should I go about this? Should I try removing this MainView class from the UIApplication?
[yourSubview removeFromSuperview];
If your MainView instance is added directly to the window, you can get the array of the window's subviews. Then iterate over the subviews until you find a view that is type MainView and remove it from the window.
NSArray *subviews = [UIApplication sharedApplication].delegate.window.subviews;
for (UIView *view in subviews)
{
if ([view isKindOfClass:[MainView class]])
{
[view removeFromSuperview];
break;
}
}

Adding a new view on top of an existing view

I want to add a view called anotherView on top of self.view. But I don't want anotherView to be a subview. Is this possible?
I want anotherView to be at the top of the page and push the contents of self.view down accordingly (without having to change the y or height values.
I have the following and it doesn't work:
UIView *anotherView = [[UIView alloc] initWithFrame: CGRectMake(0, 0, self.view.frame.size.width, 80)];
anotherView.backgroundColor = [UIColor yellowColor];
[self.view insertSubview:anotherView aboveSubview:self.view];
The box is simply on top of the existing view.
Any visible view is subview of some other view or window.
But you can add anotherView to
self.view.superview
or even
self.view.window
or create new UIWindow object and add your subview to this window
Have you tried to present anotherView modally? That way you can make it to appear on top of everything being a completly new view controller. Ex:
[self presentModalViewController:anotherView animated:YES];
assuming of course anotherView is a subclass of UIViewController and has its own View property. Because if anotherView is just subclass of UIView then you can't present it without being a subview of the current View Controller.
EDIT:
Oh yes, you can just pass a nil to the completion block:
[self presentViewController:anotherView animated:YES completion:nil];

Adding a subview releases properties of parent view controller

I am adding a subview (childView) on main view controller (parentView) for selection of some options from the menu. But when I remove it from the view, the properties of parent view returns null. Can anybody explain this behavior. Also I am using ARC.
This is how I am adding subview:
resolutionPopUp=[ResolutionPopUp alloc];
resolutionPopUp.resPopStr = combinedUrl;
[self.view addSubview:resolutionPopUp.view];
And when I remove the subview using:
[self.view removeFromSuperview];
all the properties of the existing view controller returns null.
[self.view removeFromSuperview] removes the parent view from its parent (which will be a UIWindow) and results in self.view being garbaged collected. The correct way to remove the subview, resolutionPopUp.view is this:
[resolutionPopUp.view removeFromSuperview];
This is will remove resolutionPopUp.view from self.view.
self.view is your parentViewController.and you are removing that so this is main reason why you are getting null Value.
instead of that,user
resolutionPopUp=[ResolutionPopUp alloc];
resolutionPopUp.resPopStr = combinedUrl;
[self.view addSubview:resolutionPopUp.view];
[resolutionPopUp.view removeFromSuperView];
this is correct way.

IOS Adding subview from other class programatically

i've tried to create a custom view which works like a bottom bar and it worked
Right now this function is required on multiple classes, so i try writing it into a new class and import it which likes:
//BottomBarLauncher.h
#import <UIKit/UIKit.h>
#interface bottomBarLauncher : UIViewController
-(void)launchBottomBar;
#end
And implement it as :
//BottomBarLauncher.m
-(void) launchBottomBar{
for (UIView *subView in [topView subviews]) {
[subView removeFromSuperview];
}
UIView *btnBarView = [[UIView alloc]initWithFrame:CGRectMake(0, self.view.frame.size.height - 53.3, 320, 53.3)];
btnBarView.backgroundColor = [UIColor redColor];
[self.view addSubview:btnBarView];
}
Now here's the problem, while i try implement it on a new view like follows:
//NewView.m
#import "BottomBarProtocol.h"
#interface NewView()
{
BottomBarLauncher *btnBar;
}
#end
//blahblahblah
[btnBar launchBottomBar];
and nothing happens, i think the problem was with
[self.view addSubview:btnBarView];
but i have no idea how to select the current view as target which i can add subview onto.
First a suggestion, looking at your requirements/code I think you want to create custom view. For creating a custom view, create a class which inherits from UIView rather than creating a UIViewController.
Now moving to the code, your btnBar is a UIViewController which has its own view self.view so when you call this [btnBar launchBottomBar] internally you are adding the bottom bar on self.view that is your btnBar controllers view and not on NewView controllers view. Hope you understand what I am pointing out.
Here you are missing out few calls,
btnBar.view.frame = CGRectMake(0,self.view.bounds.size.height-40,self.view.bounds.size.width,40); // Add suitable frame.
//This call will add the btnBar's view as subview onto your current view controller's view.
[self.view addSubView:btnBar.view];
This is not correct/recommended way and you can face serious challenges regarding memory leaks. To avoid those mistakes, as I suggested, create a custom UIView instead. Take a look around on how to create custom views.
Hope that helps!
You can return the UIView form launchBottomBar method and add as a subView in your current ViewController class
Make custom class and delegate and add that view in window and set its frame so that it is not visible and set its frame and slide from bottom when needed so you can use it in all view controller.
Thanks.

Reordering UIView subviews

In my app I am trying bring a subview to front, then put it back to its original layer position later. The code should be pretty simple:
To bring the subview to front (inside my custom UIView class):
[self.superview bringSubviewToFront:self];
Easy. I store the original z position in an instance variable called, you guessed it, zPosition. So, the line before -bringSubviewToFront: is:
zPosition = [self.superview.subviews indexOfObject:self];
So, all of the code I use to bring my subview to front is:
zPosition = [self.superview.subviews indexOfObject:self];
[self.superview bringSubviewToFront:self];
This works as it should. The problem is when I try to put the subview back where it was. I'm simply doing this:
[self.superview exchangeSubviewAtIndex:zPosition withSubviewAtIndex:
[self.superview.subviews indexOfObject:self]];
Using this code, if I have two subviews, this is what happens:
Let's say I have view A and view B. View A is above view B. I tap view B, it comes to the front. I tap view B again (it should go back to where it was), and nothing happens, so it's now on view A. If I now tap view A, it comes to the front, but when I tap it again (so it should go back to its original z position: below view B), all of its sibling views disappear!
Does anyone see what could be causing this problem?
There is no need to remove from superview:
[self.superview insertSubview:self atIndex:zPosition];
exchangeSubviewAtIndex may well put the view back in the right place, but it will also swap another view on top, which wont be what you started with. You might need to do something like this instead of exchangeSubviewAtIndex :
[self retain];
UIView *superview = self.superview;
[self removeFromSuperview];
[superview insertSubview:self atIndex:zPosition];
[self release];
[ Swift solution ]
As other guys said, there is no need to remove and re-add your subviews.
Instead I've found that the most convenient method is:
superView.insertSubview(subviewYouWantToReorder, aboveSubview: subviewWhichShouldBeBelow)
This question and answers were very helpful to me.
I had the requirement to place an overlay between the viewstack which views are above and below the overlay, and i wanted to keep it dynamic.
That is, a view can tell it is hidden or not.
I used the following algorithm to reorder the views.
Thanks to AW101 below for the "No need to remove view".
Here is my algorithm:
- (void) insertOverlay {
// Remember above- and belowcounter
int belowpos = 0, abovepos = 0;
// Controller mainview
UIView *mainview = [self currentMainView];
// Iterate all direct mainview subviews
for (UIView* view in mainview.subviews) {
if ([self isAboveOverlay:view]) {
// Re-insert as aboveview
[mainview insertSubview:view atIndex:belowpos + (abovepos++)];
}
else {
// Re-insert as belowview
[mainview insertSubview:view atIndex:belowpos++];
}
}
// Put overlay in between above and below.
[mainview insertSubview:_overlay atIndex:belowpos];
}

Resources