Warning generated by UIButton setting code - iphone

I have a for loop setting the background images on buttons, basically the buttons are thumbnail previews of different items & can't be set statically, however the code gives an warning because it runs through all the UIViews but then calls setBackgroundImage which does not apply to all views. The warning is an irritation, I understand what it's complaining about, how can I get rid of it? (I don't want to turn off the warning, I want to fix the problem)
// For loop to set button images
for (UIView *subview in [self.view subviews]) // Loop through all subviews
{
// Look for the tagged buttons, only the 8 tagged buttons & within array bounds
if((subview.tag >= 1) && (subview.tag <= 8) && (subview.tag < totalBundles))
{
// Retrieve item in array at position matching button tag (array is 0 indexed)
NSDictionary *bundlesDataItem = [bundlesDataSource objectAtIndex:(subview.tag - 1)];
// Set button background to thumbnail of current bundle
NSString *picAddress = [NSString stringWithFormat:#"http://some.thing.com/data/images/%#/%#", [bundlesDataItem objectForKey:#"Nr"], [bundlesDataItem objectForKey:#"Thumb"]];
NSURL *picURL = [NSURL URLWithString:picAddress];
NSData *picData = [NSData dataWithContentsOfURL:picURL];
// Warning is generated here
[subview setBackgroundImage:[UIImage imageWithData:picData] forState:UIControlStateNormal];
}
}

You can either do this:
for (id subview in [self.view subviews])
So that the id type will stop any type checking... or check whether the object responds to the selector and call it like this:
if ([subview respondsToSelector:#selector(setBackgroundImage:forState:)]) {
[subview performSelector:#selector(setBackgroundImage:forState:)
withObject:[UIImage imageWithData:picData]
withObject:UIControlStateNormal];
}
Note that I coded that last part from memory.

A dangerous bit of code with so many assumptions, but...you would first do well to check the class of the UIView before sending it a setBackgroundImage message and then just simply cast your UIView to remove the warning:
if ([subview class] == [UIButton class]) {
[((UIButton *)subview) setBackgroundImage:[UIImage imageWithData:picData] forState:UIControlStateNormal];
}

Related

How to hide buttons which I had allocated in for loop?

I have created 3 UIbuttons on the top of the screen. Now after clicking every button I got the 5 buttons for each at below with different background images. Below is the code for my first button(located at top) by which I got 5 images in my view controller.
-(IBAction) btnforimages1click:(id)sender {
for (int a=0; a<5 ; a++) {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
{
buttonsforbundle1 = [[UIButton alloc]initWithFrame:CGRectMake(100*a,300 ,100 ,90 )];
[buttonsforbundle1 addTarget:self action:#selector(btn4images1:) forControlEvents:UIControlEventTouchUpInside];
buttonsforbundle1.tag = a;
[buttonsforbundle1 setBackgroundImage:[UIImage imageNamed:[bundle1 objectAtIndex:a]] forState:UIControlStateNormal];
[self.view addSubview:buttonsforbundle1];
}
}
I do the same for other two buttons also. Now here I want is, when I click any of my top 3 buttons
I just want to display the related buttons (created in for loop)
I want to hide the other buttons related to other Top most buttons.
Please suggest me how to solve this.
You have at least three options:
1) Access UI element by tag:
If you can manage to issue unique tag number in your btnforimages1click, btnforimages2click, btnforimages3click for your other 5 added UIButtons, then you can access them:
UIButton *button = (UIButton *)[self.view viewWithTag:99];
[button removeFromSuperview];
2) Keep reference of the created buttons:
// in view.h
NSMutableArray *my_created_buttons;
...
// in view init
[[my_created_buttons alloc] init];
...
-(IBAction) btnforimages1click:(id)sender {
for (UIButton *b in my_created_buttons {
[b removeFromSuperview];
}
if([my_created_buttons count]) {
[my_created_buttons removeAllObjects];
}
... let buttonsforbundle1 local variable since we store current 5 button set in array
UIButton *buttonsforbundle1;
... in your for loop add this after creating and adding to view
[my_created_buttons addObject:buttonsforbundle1];
}
You can further refactor these code eg. by making mutablearray management to other method.
3) Keep it in Interface Builder
I think it is the easiest option, create 5 UIButtons in Interface Builder and have 5 IBOutlet for them. Then in your btnforimages1click you can eg:
-(IBAction) btnforimages1click:(id)sender {
self.IBbutton1 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:0]] forState:UIControlStateNormal];
self.IBbutton2 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:1]] forState:UIControlStateNormal];
self.IBbutton3 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:2]] forState:UIControlStateNormal];
self.IBbutton4 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:3]] forState:UIControlStateNormal];
self.IBbutton5 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:4]] forState:UIControlStateNormal];
}
So you don't hide them, just change the background image. Moreover you don't have to deal with different touchUpInside event, use only one method, and in that one click method, you can distinguish between the different clicked UIButton by checking their tag (plus you have to use a variable to check which of the 3 top UIButton was clicked).

Image Checkbox in Objective-C

I'm working on a form for the iphone and I would like a female/male button choice. The buttons originally have an M and an F written on them and when you choose one, an image flips over. I managed to display the images when the buttons are pressed. The problem I was having is that they were able to both be displayed at the same time but when one is enabled the other image should disappear. I've tried to correct it and now the program crashes.
implementation file:
-(IBAction) setCheckBox2: (id) sender
{
UIImage *selected = [UIImage imageNamed:#"female.tiff"];
// UIImage *notSelected = [UIImage imageNamed:#"male.tiff"];
if (sender == selected)
{
[sender setImage:selected];
}
else
{
[sender setImage:NO];
}
Then I was going to create another function for the male image being selected. Any suggestions?
Thanks!
You are testing that sender == selected hence implying that sender is of type UIImage, and then sending setImage: to sender... with itself as parameter.
This doen't make sense. I think what you were trying to do must look something like:
-(IBAction) setCheckBox2: (UIImageView *) sender
{
UIImage *selected = [UIImage imageNamed:#"female.tiff"];
UIImage *notSelected = [UIImage imageNamed:#"male.tiff"];
if (sender.image == selected)
{
[sender setImage:notSelected];
}
else
{
[sender setImage:selected];
}
}
Why not you are using default(for not selected) and selected(for selected) property for these two state. The advantage to do this is you will not have to write a bunch of code. OK set selected image and default image.
Take a global variable of UIButton for currentSelectedButton.
connect both the UIButton with single IBActionMethod named genderButtonClicked(or you want).
Now
-(IBAction)genderButtonClicked:(UIButton)sender
{
if(currentSelectedButton)
[currentSelectedButton setSelected:FALSE];
currentSelectedButton = sender;
[currentSelectedButton setSelected:TRUE];
}
I Think this will solve your problem

How to remove customviews added programmatically?

In one of the iPad Application, I am working I have added custom views to a view. This works fine but now I want to remove all the custom views added. How do I do that?
Following is my code for adding custom views
for (int col=0; col<colsInRow; col++) {
// NSLog(#"Column Number is%d",col);
x=gapMargin+col*width+gapH*col;
//self.styleButton=[[UIButton alloc] initWithFrame:CGRectMake(x, y, width, height)];
ComponentCustomView *componentCustomobject=[[ComponentCustomView alloc] initWithFrame:CGRectMake(x, y, width, height)];
componentCustomobject.backgroundColor=[UIColor redColor];
componentCustomobject.componentLabel.text=[appDelegate.componentsArray objectAtIndex:row];
[self.formConatinerView addSubview:componentCustomobject];
tempCount1++;
}
You can remove all the subviews of type ComponentCustomView from your parent views
for (UIView *view in self.formConatinerView.subviews) {
if ([view isKindOfClass:[ComponentCustomView class]) {
[view removeFromSuperview];
}
}
I'm not sure if removing objects from the array being iterated (in this case subviews) was safe or not (I remember reading something about a discrepancy between Mac OS X and iOS, but not sure...); Unless property subviews returns a copy of the internal array (very likely since the internal array needs to be mutable), a 100% safe, just-in-case way to do it would be this:
NSArray* copyOfSubviews = [[NSMutableArray alloc] initWithArray:[myView subviews]];
// Explicitly made mutable in an attempt to prevent Cocoa from returning
// the same array, instead of making a copy. Another, tedious option would
// be to create an empty mutable array and add the elements in subviews one by one.
for(UIView* view in copyOfSubviews){
if ([view isKindOfClass:[ComponentCustomView class]){
[view removeFromSuperview];
}
}
// (This is for non-ARC only:)
[copyOfSubviews release];
NSArray *arr = [self.view subViews];
for (UIView *view in arr) {
if ([view isKindOfClass:[ComponentCustomView class]) {
[view removeFromSuperview];
}
}

Changing The Alpha Property Of Some Labels As A Result Of A Random Number In Xcode

I need to change the alpha property of some labels as a result of a random number generation and I don't know hot to identify those labels in order to call them in the code.
For example:
If the number generated is 1, change the alpha or hidden property of the label that contains the text "1" and so on.
I wonder if exists something like the javascript function GetElementById() in xcode.
Thanks!
I think you can use Tag, you can try the example below:
UILabel * aLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 160.0f, 30.0f)];
[aLabel setTag:1]; // Set tag here
[aLabel setText:#"1"];
[self.view addSubview:aLabel];
[aLabel release];
UILabel * newLabel = (UILabel *)[self.view viewWithTag:1]; // Get the label here whit tag=1
NSLog(#"%#",newLabel.text); // Print the label text with right tag
[newLabel release];
But the tag can only be number.
You can set the UIView tag property (which is an NSInteger), then identify your interface elements using that. Alternately, if you want to set the alpha depending on the UILabel text, you can do something like
NSInteger generatedNumber = 5;
if ([label.text integerValue] == generatedNumber)
// set your alpha value
However note (of the NSString integerValue method) that:
The NSInteger value of the receiver’s text, assuming a decimal
representation and skipping whitespace at the beginning of the string.
Returns 0 if the receiver doesn’t begin with a valid decimal text
representation of a number.
If that is a problem you can use NSScanner to convert the NSString to an NSInteger, which will allow you to detect conversion failure.
suppose u want3 random no..then write something like this...
int counter = random() %3;
if(counter == 0)
{
//change alpha according to ur requirement
}
if(counter == 1)
{
//change alpha according to ur requirement
}
if(counter == 2)
{
//change alpha according to ur requirement
}
Store the labels in an NSMutableArray, so you have a reference later. Or if you really don't wanna put them in an array for some reason, you can iterate through the subviews of your main view, and find the right label, like this:
for (UIView *subview in [mainView subViews])
{
if ([subview isKindOfClass:[UILabel class]])
{
if ([[(UILabel *)subview text] isEqualToString:#"1"])
{
[subview setHidden:YES];
}
}
}

changing a button's text from another method when the buttons are in a subclass?

How do you access a button that's in a subview of a view?
I have a viewController 'GamePlay', which has a scrollview in it called 'gameScroll'. Within this scrollview I have about 100 buttons, each with a tag, and I want to be able to change the text of the button from another method.
- (void) viewDidLoad {
//Created buttons in a for-loop, assigning each a tag
//numOfButtons is total number of buttons created
}
I imagine it would be something like this? but I cant seem to find an answer on exactly how i do it when the button is in a subview
- (void) otherMethod {
for (int i=0; i<numOfButtons; i++) {
// tagsForAction = get list of buttons that need to be changed from another array
for (j=0; j<tagsForAction.length; j++) {
intTagForAction = [tagsForAction objectAtIndex:j];
if (i = tagForAction) {
UIButton* button = [Gameplay.gameScroll.view viewWithTag:tagForAction];
button.title = #"A";
}
}
}
}
I know this code isnt totally right. Im just giving you an idea of the process. I can do everything except this part in the if statement:
UIButton* button = [Gameplay.gameScroll.view viewWithTag:tagForAction];
button.title = #"A";
so how do I change the text of these buttons?
NSArray *subViewList = [gameScroll subviews];
for (id button in subViewList)
{
if ([button isKindOfClass:[UIButton class]])
{
[button setTitle:#"OK" forState:UIControlStateNormal];
}
}
Try this code
You don't have to use the for loop like that, you can get an array of subviews from any view by doing something like [someView subviews]. So, inside of your otherMethod function you can do something like:
for (UIView *v in [gameScroll subviews]) {
if (v.tag == <some_int_here>) {
[v setTitle:#"Some other title" forState:UIControlStateNormal];
}
}
I'm not exactly sure what your criteria is for determining which buttons inside the gameScroll view have to get updated, but you can work from here.