Iphone remove sub view - ios

I have a UINavigationController. On the right top i have a button on click of which i have to get a drop down table view. I created another UIViewController Class, with xib and added it as a subView to the current view. It should appear on 1st click and disappear on the 2nd click. This should happen for all click(open view and close view). I wrote this code but dont know where i'm going wrong. someone please help
-(void)modalTableView
{
tableView1 = [[TableViewController alloc] initWithNibName:#"TableViewController" bundle:nil];
for (UIView *subView in self.view.subviews)
{
if ([subView isKindOfClass:[TableViewController class]])
{
[subView removeFromSuperview];
}
else
{
[self.view addSubview:tableView1.view];
}
}
}
What am i missing here?
EDIT : TableViewController is the name of my UIViewController Class

The clue is here
for (UIView *subView in self.view.subviews)
each subView is of class UIView and your test
isKindOfClass:[TableViewController class]
is testing for class TableViewController
I would suggest a way of doing this would be by tagging the views that you add dynamically, with say 99 - and then in your loop you can identify those views by their tag.
eg.
for (UIView *subView in self.view.subviews)
{
if (subView.tag == 99)
{
[subView removeFromSuperview];
}
}

Swift version
To remove a single subview:
subView.removeFromSuperview()
To remove all subviews:
for subView in self.subviews as [UIView] {
subView.removeFromSuperview()
}
Source: What is the best way to remove all views from parent view / super view?

Try this,
if ([subView isKindOfClass:[UITableView class]])
{
[subView removeFromSuperview];
}

Here is something that should go some way to working - assuming that tableView1 is a retained #property (If not then maybe this SO answer on lazy loading techniques is for you).
-(void)modalTableView
{
if (tableView1 != nil)
{
tableView1 = [[TableViewController alloc] initWithNibName:#"TableViewController" bundle:nil];
}
if (tableView1.view.superview == nil)
{
[self.view addSubview:tableView1.view];
} else
{
[tableView1.view removeFormSuperview];
}
}

Related

ObjectiveC - How to remove same previous UIView before create new

I am creating a view on UITableView here is the code
UIView *olderLinesView = (UIView*)[self.view viewWithTag:1820];
for (UIView* view in [olderLinesView subviews]) {
[view removeFromSuperview];
}
[olderLinesView removeFromSuperview];
UIView *linesView=[[UIView alloc]initWithFrame:CGRectMake(2, -2, 1022, height)];
[linesView setBackgroundColor:[UIColor clearColor]];
[linesView setUserInteractionEnabled:NO];
[linesView setTag:1820];
[tableView addSubview:linesView];
But the problem is if i remove olderLinesView before creating linesView (same view) the linesView is not created at all. And if i don't remove this view before creating it, it redraws the view over and over. I am calling this code again and again so need to remove this view before creating its new instance. What i am doing wrong here?
You need to modify code as below
UIView *olderLinesView = (UIView*)[self.view viewWithTag:1820];
for (UIView* view in [tableview subviews])
{
if( [view isKindOfClass:[olderLinesView class]] )
{
for (UIView* subview in [view subviews])
{
[subview removeFromSuperview]; //if you want all views
}
}
}
///(OR)
for (UIView* view in [tableview subviews])
{
if( [view isKindOfClass:[olderLinesView class]] )
{
for (UIView* subview in [view subviews])
{
if(subview.tag==1820)
{
[subview removeFromSuperview];//if you want remove single view
}
}
}
Hope it helps you...!

Changing the action bound to the send button in MFMessageComposeViewController

I know it's not officially possible. I don't want to release it to the store, it's just a prototype.
I tried finding the button:
MFMessageComposeViewController *messageController = [[MFMessageComposeViewController alloc] init];
messageController.messageComposeDelegate = self;
NSArray * allViewControllers = [messageController viewControllers];
for (UIViewController *viewController in allViewControllers)
{
NSArray *allSubviews = [viewController.view subviews];
NSLog(#"class name: %#", viewController.class);
for(UIView *view in allSubviews)
{
if([view isMemberOfClass:[UIButton class]])
{
UIButton *button = (UIButton *)view;
NSLog(#"title: %#", button.titleLabel.text);
}
}
}
But nothing worked, so is it possible to change that send button? A sort of a hack? or importing a private header?
Thanks you.
Update:
Tried the following:
NSArray *allSubviews = [[messageController toolbar] subviews];
for(UIView *view in allSubviews)
{
if ([view isKindOfClass:[UIToolbar class]])
{
UIToolbar *navigationBar = (UIToolbar *)view;
for(UIView *subview in navigationBar.subviews)
{
NSLog(#"%#", [subview subviews]);
if([subview isMemberOfClass:[UIBarButtonItem class]])
{
UIBarButtonItem *button = (UIBarButtonItem *)view;
NSLog(#"title: %#", button.title);
}
}
}
Behind the hood, yes you can trick the label of Send Button.
Officially it is not allowed, but for private use you can use following framework which is available on github.
https://github.com/nst/iOS-Runtime-Headers/tree/master/Frameworks/MessageUI.framework.
Instead of default framework include this in your project.
And change whatever you want.
If any query let me know i will show the code.
I've never done this but here are some ideas to point you in the right direction.
MFMailComposeViewController is a UINavigationController. The "Send" and "Cancel" buttons are actually in its navigation bar. The navigation bar is a subview of the UINavigationController's view, rather than belonging to any of its children. You are logging the subviews of each child view, so you would never actually see the navigation bar since it is managed by the parent.
Try logging the subviews of the messageController.view, that should give you the navigation bar. The other thing is that you are checking for UIButton whereas you may want to be checking for a UIBarButtonItem.

How to check if subview is button or not

I am developing an application. In that I get all subviews of UITableViewCell.
The code for this one is:
(void)listSubviewsOfView:(UIView *)view {
// Get the subviews of the view
NSArray *subviews = [view subviews];
// Return if there are no subviews
if ([subviews count] == 0) return;
for (UIView *subview in subviews) {
NSLog(#"%#", subview);
// List the subviews of subview
[self listSubviewsOfView:subview];
}
}
But my problem is how to find out button from that subviews list. Please tell me how to solve this one.
You can iterate through all subviews like this.
for (id subview in subviews) {
if ([subview isKindOfClass:[UIButton class]]) {
//do your code
}
}
Swift
for subview in view.subviews {
if subview is UIButton {
// this is a button
}
}
Check if the subview is a button with is AnyClass, isKind(of aClass: AnyClass) or isMember(of aClass: AnyClass) API.
Using is-
for subview in self.view.subviews{
if subview is UIButton{
//do whatever you want
}
}
Using isMember(of:)-
for subview in self.view.subviews{
if subview.isMember(of: UIButton.self){
//do whatever you want
}
}
Using isKind(of:)-
for subview in self.view.subviews{
if subview.isKind(of: UIButton.self){
//do whatever you want
}
}
To expand on the 'do your code' part of Martin's answer. Once I got the subview, I wanted to test whether it was the right button and then remove it. I can't check the titleLabel of the button directly by using subview.titleLabel so I assigned the subview to a UIButton and then checked the button's titleLabel.
- (void)removeCheckboxes {
for ( id subview in self.parentView.subviews ) {
if ( [subview isKindOfClass:[UIButton class]] ) {
UIButton *checkboxButton = subview;
if ( [checkboxButton.titleLabel.text isEqualToString:#"checkBoxR1C1"] ) [subview removeFromSuperview];
}
}
}

Check if a subview is in a view

I'm making an app where I add a subview to a view using addSubview: on an IBAction. In the same way, when the button with that IBAction is touched again should call removeFromSuperview on that subview added on that IBAction:
PSEUDO CODE
-(IBAction)showPopup:(id)sender
{
System_monitorAppDelegate *delegate = (System_monitorAppDelegate *)[[UIApplication sharedApplication] delegate];
UIView *rootView = delegate.window.rootViewController.view;
if([self popoverView] is not on rootView)
{
[rootView addSubview:[self popoverView]];
}
else
{
[[self popoverView] removeFromSuperview];
}
}
You are probably looking for UIView's -(BOOL)isDescendantOfView:(UIView *)view; taken in UIView class reference.
Return Value
YES if the receiver is an immediate or distant
subview of view or if view is the receiver itself; otherwise NO.
You will end up with a code like :
Objective-C
- (IBAction)showPopup:(id)sender {
if(![self.myView isDescendantOfView:self.view]) {
[self.view addSubview:self.myView];
} else {
[self.myView removeFromSuperview];
}
}
Swift 3
#IBAction func showPopup(sender: AnyObject) {
if !self.myView.isDescendant(of: self.view) {
self.view.addSubview(self.myView)
} else {
self.myView.removeFromSuperview()
}
}
Try this:
-(IBAction)showPopup:(id)sender
{
if (!myView.superview)
[self.view addSubview:myView];
else
[myView removeFromSuperview];
}
UIView *subview = ...;
if([self.view.subviews containsObject:subview]) {
...
}
The Swift equivalent will look something like this:
if(!myView.isDescendantOfView(self.view)) {
self.view.addSubview(myView)
} else {
myView.removeFromSuperview()
}
Check the superview of the subview...
-(IBAction)showPopup:(id)sender {
if([[self myView] superview] == self.view) {
[[self myView] removeFromSuperview];
} else {
[self.view addSubview:[self myView]];
}
}
Your if condition should go like
if (!([rootView subviews] containsObject:[self popoverView])) {
[rootView addSubview:[self popoverView]];
} else {
[[self popoverView] removeFromSuperview];
}
Here we used two different views. Parent view is the view in which we are searching for descendant view and check wether added to parent view or not.
if parentView.subviews.contains(descendantView) {
// descendant view added to the parent view.
}else{
// descendant view not added to the parent view.
}

Remove gradient background from UIWebView?

How do remove the gradient from a UIWebView - the one that you see if you overscroll the top or bottom.
This code
webView.backgroundColor = [UIColor whiteColor];
just changes the color of the gradient, it doesn't removes it. How can this be done?
(note: not the same question as UIWebView underside)
Aha, yes terminology fail. I wouldn't call that a shadow at all, but c'est la vie. Here is my type-safe code to achieve the effect. To summarise: this will hide any image-view children of the scroll view. It's not as vulnerable to change as the (objectAtIndex:0) methods, so if Apple re-order the children of the webView control it will work fine, but still relies on the fact that the gradient effect is applied by imageviews parented to the scroll view (and that there is indeed a scrollview underpinning the web view).
{
webView.backgroundColor = [UIColor whiteColor];
for (UIView* subView in [webView subviews])
{
if ([subView isKindOfClass:[UIScrollView class]]) {
for (UIView* shadowView in [subView subviews])
{
if ([shadowView isKindOfClass:[UIImageView class]]) {
[shadowView setHidden:YES];
}
}
}
}
}
To transparent the UIWebView and remove the scrolls.
webView.opaque = NO;
webView.backgroundColor = [UIColor clearColor];
for(UIView *view in webView.subviews){
if ([view isKindOfClass:[UIImageView class]]) {
// to transparent
[view removeFromSuperview];
}
if ([view isKindOfClass:[UIScrollView class]]) {
UIScrollView *sView = (UIScrollView *)view;
for (UIView* shadowView in [sView subviews]){
//to remove shadow
if ([shadowView isKindOfClass:[UIImageView class]]) {
[shadowView setHidden:YES];
}
}
}
}
for hide scroll indicators
You mean the shadow? Remove UIWebView Shadow?
The only way I found how to do this was :
for(UIView *aView in [[[webView subviews] objectAtIndex:0] subviews]) {
if([aView isKindOfClass:[UIImageView class]]) { aView.hidden = YES; }
}
It just just steps thru the subviews of UIWebView and removes the view if it is an image view.
I haven't put this in any App Store apps, so I don't know if Apple would accept it.
EDIT: Brian's link provides more details.
Using method suggested above you won't be able to edit your scroll indicator/insets later. They appear as UIImageView also, so you should check for last object:
UIView* lastView = [[subView subviews] lastObject];
for (UIView* shadowView in [subView subviews])
{
if(shadowView!=lastView) ... <-this one is a scroll
}
I was able to do this by adding white subviews to the top and bottom of the WebView’s scrollView. I control the content of the WebView, so I know that white is OK - this won’t work if you are loading arbitrary content.
// _topCover and _bottomCover are ivar UIViews
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
// with cover views 300pt high, I couldn't scroll far enough to see the shadow,
// even in portrait on an iPad, which gives you the longest scroll distance
CGFloat coverage = 300;
_topCover = [[UIView alloc] initWithFrame:CGRectMake(0, -coverage, webView.bounds.size.width, coverage)];
_bottomCover = [[UIView alloc] initWithFrame:CGRectMake(0, webView.scrollView.contentSize.height, webView.bounds.size.width, coverage)];
_topCover.backgroundColor = [UIColor whiteColor];
_bottomCover.backgroundColor = [UIColor whiteColor];
// in case the webView is resized, e.g. by rotating the device
_topCover.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth;
_bottomCover.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
[webView.scrollView addSubview:_topCover];
[webView.scrollView addSubview:_bottomCover];
}
I run it it after the page loads so that webView.scrollView.contentSize.height will give me the correct height. I’m not sure how this will work if your pages are dynamically changing height. My page loads only once; if yours is reloading, you will want to skip running alloc/init on _topCover and _bottomCover after the first time for efficiency.
Update: I’m not sure that my use of autoresizingMask, above, is sufficient when the view rotates. You may need to put this in the UIViewController that contains your UIWebView to resize the covers after rotating:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
CGFloat coverage = 300;
_topCover.frame = CGRectMake(0, -coverage, self.webView.bounds.size.width, coverage);
_bottomCover.frame = CGRectMake(0, self.webView.scrollView.contentSize.height, self.webView.bounds.size.width, coverage);
}
I've built upon #damithH 's answer
#implementation UIWebView (Extensions)
- (void)setBackgroundAndShadowVisible:(BOOL)visible
{
self.opaque = !visible;
self.backgroundColor = [self.backgroundColor colorWithAlphaComponent:visible ? 1.0 : 0.0];
for(UIView *view in [self subviews])
{
if([view isKindOfClass:[UIImageView class]])
{
view.hidden = !visible;
}
if([view isKindOfClass:[UIScrollView class]])
{
UIScrollView *scrollView = (UIScrollView *)view;
for (UIView *shadowView in [scrollView subviews])
{
if ([shadowView isKindOfClass:[UIImageView class]])
{
shadowView.hidden = !visible;
}
}
}
}
}
#end
if (UIDevice.currentDevice.systemVersion.intValue < 7)
for (UIImageView *imageView in webView.scrollView.subviews)
if ([imageView isKindOfClass:[UIImageView class]] && imageView.image.size.width == 1)
imageView.hidden = YES;

Resources