UIView addSubview works once but not twice - ios

I would like to add a UIButton in a UIView from my xib file.
In my xib, I declare a UIView outlet named "content" with interface builder: here is the generated code :
#property (weak, nonatomic) IBOutlet UIView *content;
I would like to add a button, here is the code for this:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(0, 8, 141.0, 56.0);
[button setBackgroundImage:[UIImage imageNamed:#"TAB_NORMAL"]
forState:UIControlStateNormal];
button.frame = CGRectMake(0, 8, 56.0, 141.0);
[self.content addSubview:button];
If I put this code in -viewDidLoad method, it works, but if I put it in a function called later, the button is never displayed.
What could be the reason ?
Thanks for your help.

If your UIView content is a top level item, that is, not contained in your main view - then it has to be strong. Only items that are not top-level can use weak, since the containing view would keep a strong reference to them. I also assume that content was immediately added to the primary view, which kept a strong reference to it (it in viewDidLoad happened before ARC nil'ed out content.
If for some reason changing the property to strong does not fix the problem, then for sure add a NSLog (or assert) to insure that content is non-nil.

Related

Programmatically added view objects not showing up in storyboard

I can't see any of the view objects I've added programmatically. I need to link them to IBAction and/or IBOutlet, but without being able to ctrl-click-drag, I can't.
For example, I have this in viewDidLoad:
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(789, 60, 215, 72)];
[imageView setAnimationImages:imgListArray];
[self.view addSubview:imageView];
The animation shows up in the simulator, but not in the storyboard.
How can I either make these objects show up in storyboard (preferred), or link them to IBActions/Outlets programmatically?
As #vikingsegundo said, Image Builder allows you to add objects to views and then connect them to IBOutlets and IBActions in your classes, but if you add things programatically then you are on your own in terms of Image Builder/Storyboards.
You can still create an iVar or property (preferred) to store the reference to your object, but you don't need the IBOutlet tag, so
#property (strong,nonatomic) UIImageView *imageView;
and then
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(789, 60, 215, 72)];
[self.imageView setAnimationImages:imgListArray];
[self.view addSubview:self.imageView];
You can also add action handlers to objects through code (the equivalent of ctrl-dragging to an IBAction method)
[self.aButton addTarget:self action:#selector(buttonEventHandler) forControlEvents: UIControlEventTouchUpInside];
To set a code-instantiated object as an instance variable, just set it. Like this:
// your code
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(789, 60, 215, 72)];
[imageView setAnimationImages:imgListArray];
[self.view addSubview:imageView];
// and then:
self.myImageView = imageView; // assumes you've got a `#property` called `myImageView`
That's exactly the same thing that constructing an outlet connection in the storyboard does, but now you're doing it yourself.
To set a code-instantiated control's action, call addTarget:action:forControlEvents:.
That's exactly the same thing that setting up an action connection in the storyboard does, but now you're doing it yourself.

Displaying UIButton programmatically

I'm trying to display a button to the view programmatically with this code:
- (void)viewDidLoad {
_detailButton = [UIButton buttonWithType:UIButtonTypeCustom];
_detailButton.frame = CGRectMake(23, 294, 72, 37);
[_detailButton setTitle:#"UIButton!" forState:UIControlStateNormal];
[_detailButton addTarget:self
action:#selector(showPop:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_detailButton];
}
I have the button declared in the .h file like this:
#property (strong, nonatomic) UIButton *detailButton;
The code does not throw any errors or warnings, but when I run there is no button displayed.
I check your code in my project its working fine i think in your case there are some other view that cover this button so check that your code has no problem at all.
Your button probably covered by another view. Just make sure its on top of other views.
In viewWillAppear add the following line of code:
[self.view bringSubviewToFront:self.detailButton];
If your button's type is of UIButtonTypeCustom, the button's default title color is white, so you can't see it if your view's background color is white.
[_detailButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];

Move a programmatically generated button

I have a programmatically created button and I want to move it to a different location when a specific method is called. So far I can see the button I created, and I can move a different button that I drag-dropped into storyboard, but I am not sure how I can refer to the programmatically generated button in my code to change its location.
Code for generating button:
UIButton *generatedButton = [UIButton buttonWithType:UIButtonTypeCustom];
[generatedButton addTarget:self
action:#selector(genButtonTouched:)
forControlEvents:UIControlEventTouchDown];
generatedButton.frame = CGRectMake(84.0, 80.0, 70.0, 40.0);
[self.view addSubview:generatedButton];
Inside another method, I have code for changing a button's location. If this code is in the same method as where I generate the button it works fine, but I need to place this in a different method:
[generatedButton setFrame:CGRectMake(xCoord, yCoord, buttonWidth, buttonHeight)];
In your ButtonViewController.h
#interface ButtonViewController : UIViewController{
}
#property (retain, nonatomic) UIButton *generatedButton;
In your ButtonViewController.m
#implementation ButtonViewController
#synthesize generatedButton;
- (void)viewDidLoad
{
generatedButton = [UIButton buttonWithType:UIButtonTypeCustom];
[generatedButton addTarget:self
action:#selector(genButtonTouched:)
forControlEvents:UIControlEventTouchDown];
generatedButton.frame = CGRectMake(84.0, 80.0, 70.0, 40.0);
[self.view addSubview:generatedButton];
}
// to call the button anywhere within the class, do like this :-
-(void)methodToMoveButton{
[generatedButton setFrame:CGRectMake(xCoord, yCoord, buttonWidth, buttonHeight)];
}
If you want something else, please let me know.
It's no different than moving the button added in the storyboard. Create an instance variable to hold a reference to your generated button. Then you can access the button in the other method using that instance variable.

How to perform performSegueWithIdentfier from within UIView

Ok so I have a UIButton embedded into a UIImageView which forms part of a UIView.
The button's selector calls a method which should run:
[self performSegueWithIdentifier:#"SegueToMoreInfo"];
However I get the error:
no visible at interface for 'myclassname' declares the selector 'performSegueWithIdentifier'.
Basically I really need to perform a segue from within the UIView. If not possible how would I call from the UIViewController instead?
EDIT: MORE INFO:
//adding button
UIButton *attractionButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[attractionButton addTarget:self
action:#selector(buttonClicked:)
forControlEvents:UIControlEventTouchUpInside];
[attractionButton setTitle:#"Attraction Info" forState:UIControlStateNormal];
attractionButton.frame = CGRectMake(80.0, 80, 160.0, 40.0);
[_image1 addSubview:attractionButton];
My method :
(IBAction)buttonClicked:(id)sender
{
[self performSegueWithIdentifier:#"SegueToMoreInfo" sender:sender];
}
[self performSegueWithIdentifier:#"aseguename" sender:self];
is a UIViewController method. That is why you are getting this error. Also views should not talk to ViewControllers except through protocols.
Having said that, you are going about this the wrong way. IBActions for buttons and other UIView objects should be in the ViewController. So I would move the IBAction to your View Controller and hook it to the button from there. Then insert your code in that IBAction.
Update after the code posted:
All of the code posted should be in your View Controller. I would just change:
[_image1 addSubview:attractionButton];
to
[self.view addSubview:attractionButton];
or if you really want that button to be a subview to your image, then you can leave your code, just make sure to create an IBOutlet property for that image, from your image in interface builder to your View Controller and call it _image1.
Hope this helps

UIView/UIButton coordinates flipped

I have a coreplot project. The class of the view in viewcontroller has been changed to CPTGraphHostingView.
After creating the graph (this works fine),
I am adding a button as a subview , this launches a popover
the button shown is inverted. I have the same control in different view controllers and it works fine. The Popover also appears fine.
Here is the code that creates and adds the UIButton
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(monthSelection)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Change Month" forState:UIControlStateNormal];
button.frame = CGRectMake(330, 650, 111, 40);
[self.view addSubview:button];
[here is a screenshot of whats happening. UIButton is suppose to show somewhere below the popover. What am i missing.
Do not add subviews to the graph hosting view. Instead, make other views siblings of the hosting view, i.e., add them as subviews of the same superview.

Resources