Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community!

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

General Discussion

Extra Credit: Add button programatically

I am not fully understanding why one I have to make a CGRect when I init the button. I'm trying to complete the following, but instead of using text on the button, I'm using the images for UIControlState differences:

Set an image for the button using its background image property and then set the title text. This should allow you to change the text of your button without having to change the image.

If I do the following, the button does not show on the screen:

UIButton *predictButton = [[UIButton alloc]init];

[predictButton setImage:[UIImage imageNamed:@"button-off"] forState:UIControlStateNormal];

[self.view addSubview:predictButton];

If I do the following the button does show up. Why do I have to specify a rect?

UIButton *predictButton = [[UIButton alloc]initWithFrame:CGRectMake(0, 20, 100, 20)];

[predictButton setImage:[UIImage imageNamed:@"button-off"] forState:UIControlStateNormal];

[self.view addSubview:predictButton];

5 Answers

If you don't specify a frame for the button, Xcode won't be able to draw it in you view. I think it's that simple, but someone correct me if I'm wrong.

Is this only for buttons, or do you have to specify a frame for all elements you add?

I didn't have to do it for an UIImageView, that's why I ask.

When you create an UIView in code, you just use alloc and initWithFrame, which is UIView's designated initializer. You can also use alloc init, but then the frame will be something called a CGRectZero (where origin is zero and width and height is zero).

I'm not completely sure why you didn't have to specify a frame for the UIImageView. UIImageView inherits from UIView, so it has the frame property, but maybe you set it after you declared the object? I haven't seen your code, so it's a little hard to say.

In the "Programming a Background Image" we did the following:

UIImage *backgroundImage = [UIImage imageNamed:@"background"];

UIImageView *imageView = [[UIImageView alloc] initWithImage:backgroundImage];

[self.view addSubview:imageView];

When we instantiate the UIImage with imageNamed is it possibly doing the background work of specifying the CGRect? Or is it doing it in UIImageView with the initWithImage method?

(Thanks for the answers so far, I'm just curious to learn more, and you are being extremely helpful!)

Yes! I found something in the description for the initWithImage: method:

"This method adjusts the frame of the receiver to match the size of the specified image. It also disables user interactions for the image view by default."

It seems like the frame of the imageView is being set for you.