I am trying to create a button represented by an image which whenever is pressed changes the image to the other one so that I can know which image is currently selected.
- (IBAction)imageWasPressed:(id)sender {
UIImage *imageWork = [UIImage imageNamed:#"icn_work"];
NSData *data1 = UIImagePNGRepresentation(self.imageButton.currentImage);
NSData *data2 = UIImagePNGRepresentation(imageWork);
if (data1==data2){
[self.imageButton setImage:[UIImage imageNamed:#"icn_personal"] forState:UIControlStateNormal];}
}
I have also tried this but it didn't work:
- (IBAction)imageWasPressed:(id)sender {
if ([[self.imageButton imageForState:UIControlStateNormal] isEqual:[UIImage imageNamed:#"icn_work"]]){
[self.imageButton setImage:[UIImage imageNamed:#"icn_personal"] forState:UIControlStateNormal];}
}
The line which changes the images works but I can't compare the two images. Any help would be much appreciated! Thank you!
This is rather unconventional approach, and I would recommend keeping track of your selection some other way.
But to answer the issue at hand, it does not work because you are comparing pointers, not data.
data1 * will always be different to data2 *.
From the documentation:
isEqualToData:
Compares the receiving data object to otherData.
- (BOOL)isEqualToData:(NSData *)otherData
If you want to change button image regarding it's state you can assign different images for different states.
[self.imageButton setImage:image1 forState:UIControlStateNormal];
[self.imageButton setImage:image2 forState:UIControlStateHighlighted];
[self.imageButton setImage:image3 forState:UIControlStateSelected];
Since you can get button state and you know what image you set for the state you can get image as well.
if ([data1 isEqualToData: data2])
instead of
if (data1==data2)
Related
I'm a beginner at Objective C.
I'm trying to add a button to the storyboard. When clicked, the button's background will be changed to another image. However, I'm try to get the background image using :
[sender setBackgroundImage: [UIImage imageNamed:#"cardback.jpg"] forState:UIControlStateApplication];
It seems that [UIImage imageNamed:#"cardback.jpg"] just doesn't get the image object for me.
codes
You are using wrong control state flag. You need to use UIControlStateNormal instead of UIControlStateApplication for getting the desired result. Refer UIControlState for more info. Also you don't need to specify the image extension (because you are loading the image from asset catalog), so remove .jpg from the code.
Change:
[sender setBackgroundImage: [UIImage imageNamed:#"cardback.jpg"] forState:UIControlStateApplication];
to
[sender setBackgroundImage: [UIImage imageNamed:#"cardback"] forState:UIControlStateNormal];
[button setImage: [UIImage imageNamed:#"Back.png"] forState:UIControlStateNormal];
[button setTitle: #"Title" forState:UIControlStateSelected];
I would like the button to display the image in normal state but the word "Title" in selected state. But I can't get this code to work. It displays Image when I click the button to selected state and the Image covers the title. I can't get rid of the image in selected state.
[button setImage: [UIImage imageNamed:#"Back.png"] forState:UIControlStateNormal];
[button setImage: [UIImage imageNamed:#"Back2.png"] forState:UIControlStateSelected];
But this works. The image flips from Back to Back2. Or the other way works too
[button setImage: [UIImage imageNamed:#"Back.png"] forState:UIControlStateSelected];
[button setTitle: #"Title" forState:UIControlStateNormal];
It is so simple and I started to think it is UIButton bug.
Has anyone tried this before?
Add some small transparent image (1px is enough) to your project and name it, for example, transparent.png. Then add this line to the code:
[button setImage: [UIImage imageNamed:#"transparent"] forState:UIControlStateSelected];
The other and much simpler solution is to use interface builder and set images for diferent states. In this case you even don't need to use the transparent image; simply left the Image field empty for Selected state.
Like #codeplasma answer, but no need to add a transparent image, just create an empty UIImage:
button.setImage(UIImage(), forState: .selected)
In Objective-C you would create it with [UIImage new].
You have to explicitly set the button state to selected in some UIButtons(like the rounded rect button), it does not happen automatically upon clicking on it.
Bug?
No, it's not a bug, UIButton is designed this way, and here's why: when you set an image for the UIButton's UIControlStateNormal (normal state), it will preserve it throughout the other states (selected, disabled, highlighted) in the event you did not specify an image for those other states.
This means you can set up your button with a single image, the system adds a dark highlight in highlight state and makes the button look like it's alpha 0.5 in disabled state.
You might think setting the image to nil for the selected state will get rid of it for that state, but of course when the state changes, it will see that it doesn't have an image for that state (it's nil !), but it does for state UIControlStateNormal, so it will use that one instead, thus you are stuck with the same image!
Note that if you set the image for a different state then normal, it would have only shown for that state.
Workaround
Honestly your intentions with the button's image/title sound a little odd... Maybe you're new to iOS, maybe with some more info about what your button is and is supposed to be doing, we can suggest a better solution.... but the easiest way to workaround this with the information you've given us is to give a valid image for the selected state, one which is preferably transparent, and it could be 1x1 pixels also to save on space.
Otherwise you can do this, create a UIImage at runtime to use as a placeholder acting as your image, but would be a good idea to cache this, perhaps create it once and hold it in an iVar.
// Create a 1x1 UIImage at runtime
UIGraphicsBeginImageContext((CGSize){1.0f,1.0f});
UIImage *runtimeImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Setup your button
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(20.0, 20.0, 100.0, 100.0);
// set the image for each state
[btn setImage:[UIImage imageNamed:#"Back.png"] forState:UIControlStateNormal];
[btn setImage:runtimeImage forState:UIControlStateSelected];
// have your text for the normal state
[btn setTitle:#"selected !" forState:UIControlStateNormal];
Instead of using setImage, I suggest to use SetBackgroundImage for this scenario. Here is a solution that works for me for a similar solution:
UIImage *cardBackImage = [UIImage imageNamed:#"card.png"];
UIImage *cardFrontImage = [UIImage imageNamed:#"transparent.png"];
[cardButton setBackgroundImage:cardFrontImage forState:UIControlStateSelected];
[cardButton setBackgroundImage:cardFrontImage forState:UIControlStateSelected|UIControlStateDisabled];
[cardButton setBackgroundImage:cardBackImage forState:UIControlStateNormal];
I am trying to compare an image from a button with another image but its not working as expected and as stackoverflow suggestions...
if (favoriteButton.imageView.image == [UIImage imageNamed:#"favorite.png"]) {
NSLog(#"yes!");
}
anything else I can do? I tried to get the image file name but it seems to be impossible.
UIImage is a class, not a native type. You should use the isEqual: method, not the == operator to see if the two objects represent the same data.
if ([favoriteButton.imageView.image isEqual:[UIImage imageNamed:#"favorite.png"]]) {
NSLog(#"yes!");
}
Only use the == operator with object pointers if you really want to see if the two pointer reference the exact same location in memory.
I found this: How to compare two UIImage objects
this is what I tink may help:
- (BOOL)image:(UIImage *)image1 isEqualTo:(UIImage *)image2
NSData *data1 = UIImagePNGRepresentation(image1);
NSData *data2 = UIImagePNGRepresentation(image2);
return [data1 isEqual:data2];
}
Reading the comments of your question, i think u cloud just assign the button a "state" such as "selected".
On the normal state the button cloud load the "not_favorite.png".If the user tap on the button it will be on a selected state and the corresponding image(favorite.png) will load.
On future if you need to know which image is loaded(or if the user already taped on the button to make it favorite) u can just check the button's state.
Personally i will not compare images just to fire an action for a button. It will be costly.
why not try to use imageView to identify the image?
UIImageView *imageView_favorite = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"favorite.png"]];
UIImageView *imageView_not_favorite = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"not_favorite.png"]];
//both imageView_favorite and imageView_not_favorite can be set as an member ivar, and the favoriteButton.imageView can be set to them appropriately.
if (favoriteButton.imageView == imageView_favorite) {
NSLog(#"yes!");
}
try this
must check your buttonname and extension. it must be same.
-(IBAction)btnMaleClick:(id)sender {
if (btnMale.imageView.image == [UIImage imageNamed:#"radiobtn.png"]) {
[btnMale setImage:[UIImage imageNamed:#"radiobtnselected.png"] forState:UIControlStateNormal];
[Female setImage:[UIImage imageNamed:#"radiobtn.png"] forState:UIControlStateNormal];
}
else {
[btnMale setImage:[UIImage imageNamed:#"radiobtn.png"] forState:UIControlStateNormal];
[Female setImage:[UIImage imageNamed:#"radiobtnselected.png"] forState:UIControlStateNormal];
}
}
i'm trying to create a photo viewer like the Apple Photos app in iOS.
The layout is ok, but it receives memory warning and then crashes. Why? This happens even i load 7/8 images from the app documents folder. Have i to manage the memory with specific system? I use ARC with iOS 5.
EDIT :
The code :
for (int i=0; i<[dataSource count]; i++) {
UIButton *button=[UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[dataSource objectAtIndex:i] forState:UIControlStateNormal];
[[button titleLabel] setText:[NSString stringWithFormat:#"%i",i+1]];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[[button layer] setBorderWidth:1];
[[button layer] setBorderColor:[UIColor darkGrayColor].CGColor];
if (i==0) {
[button setFrame:CGRectMake(x, y, width, height)];
} else {
if (i%5==0) {
nRow++;
x=18;
[button setFrame:CGRectMake(x, (y*nRow), width, height)];
} else {
[button setFrame:CGRectMake(x+space+width, (y*nRow), width, height)];
x=button.frame.origin.x;
}
}
[[self view] addSubview:button];
}
The main part of this code is the first 6 lines, after is all x and y.
dataSource is an NSArray declared as property (nonatomic, strong). It contains UIImage objects.
You should be lazily loading your images in conjunction with reusing your buttons to account for the possibility of a large number of images.
To implement:
Keep the paths to the image files in your data array instead of the UIImage objects. Get the image from the path using imageWithContentsOfFile: when you need it.
Load the first z buttons into the scroll view where z is the number that appear on the screen at a time plus one row's worth.
Set the UIViewController that we are currently in as the scrollview's delegate, and respond to changes in offset by repositioning buttons and setting appropriate images and targets.
Also, if 7/8 images is crashing your app, it sounds like you're dealing with some pretty large image files. Try to provide thumbnail-sized versions of the content within the documents directory(whatever the size of your buttons are EXACTLY), or if images are dynamic, see this post for a how-to.
If you are probably using ImageNamed, this article helped me alot:
http://www.alexcurylo.com/blog/2009/01/13/imagenamed-is-evil/
Mainly
DO NOT USE [UIImage imageNamed] for any significant amount of images. It is EVIL. It WILL bring down your application and/or Springboard, even when your application is putting along using just barely a nibble of memory on its own.
and
it is better to implement your own cache
and here's the proposed cached image example:
- (UIImage*)thumbnailImage:(NSString*)fileName
{
UIImage *thumbnail = [thumbnailCache objectForKey:fileName];
if (nil == thumbnail)
{
NSString *thumbnailFile = [NSString stringWithFormat:#"%#/thumbnails/%#.jpg", [[NSBundle mainBundle] resourcePath], fileName];
thumbnail = [UIImage imageWithContentsOfFile:thumbnailFile];
[thumbnailCache setObject:thumbnail forKey:fileName];
}
return thumbnail;
}
I am currently trying to find out, whether it is possible to check which image a button uses.
Lets say I have image1 and image2.
If the buttons image is image1 do this and if buttons image is image2 do that.
But xcode doesnt give me any autofill options....
[m1 setImage:[UIImage imageNamed: #"Penguin.png"] forState:UIControlStateNormal];
This is how i set the images. but how do i find out wheter its Penguin or Penguin2?
Just used This Code for Button Action on the basis of image
- (IBAction)checkButtonClicked:(UIButton *)sender {
if ([checkButton.currentImage isEqual:[UIImage imageNamed:#"checkbox.png"]])
[checkButton setImage:[UIImage imageNamed:#"Checked.png"] forState:UIControlStateNormal];
//do some thing here for your image1
else
[checkButton setImage:[UIImage imageNamed:#"checkbox.png"] forState:UIControlStateNormal];
//do some thing here for your image 2
}
Cocoa Touch was designed around the Model–View–Controller pattern, so you might want to try adopting that pattern. Instead of trying to retrieve state information – the selected penguin – from the view – the button – store it in an instance variable in your controller class.
Your code for setting the image could look like this:
self.currentImage = #"Penguin.png";
[m1 setImage:[UIImage imageNamed: currentImage] forState:UIControlStateNormal];
Then when you need to check the value:
if ([#"Penguin.png" isEqual:self.currentImage]) {
do something;
}
Checking the equality of images is done like so:
if ([[UIImage imageNamed:#"Penguin.png"] isEqual:m1.currentImage]) {
// do something
}
2 methods can be used for this:
1.
UIImage *image = self.myButton.currentBackgroundImage;
2.
myImageView.image = [myButton backgroundImageForState:myButton.state];
UIImage *img=[(UIButton *) sender currentImage];
if(img == [UIImage imageNamed:#"edit"])
{
//If do something
}`
try this hope it will work
In Swift also possible
iOS 8+
if button.currentImage?.isEqual(UIImage(named: "Penguin.png")) {
//do something here
}
iOS 7-
if timerButton.currentImage == UIImage(named: "Penguin.png") {
//do something here
}