Hi I’m trying to get an image to change on a method call and if the method is recalled the original image comes back
-(void)change
{
if ((player.image = [UIImage imageNamed:#"first.png"]))
{
player.image = [UIImage imageNamed:#"second.png"]));
}
else
{
player.image = [UIImage imageNamed:#"first.png"]));
}
}
This works change the "first.png" image to "second.png" but when called again it doesn’t.
Where am I going wrong?
As pointed out by Michael Dautermann, the way you're comparing two UIImages is wrong. Can't you simply keep an NSString property that tells you the image you're showing?
-(void)change
{
if ([self.displayedImageTitle isEqualToString:#"first.png"]){
player.image = [UIImage imageNamed:#"second.png"]));
self.displayedImageTitle = #"second.png";
}
else{
player.image = [UIImage imageNamed:#"first.png"]));
self.displayedImageTitle = #"first.png";
}
}
In your code above, you're making an invalid assumption that "[UIImage imageNamed: #"first.png"]" will always be the same UIImage object when you do a comparison. That isn't true. Every time you call the "imageNamed" API, you may be creating a brand new UIImage object.
Now, since UIImage object doesn't know anything about file names or image titles, you need to keep track of which image is being displayed and then toggle on that.
I'd suggest creating a subclassed UIImage object that has a filename or title property (that you would also need to set), or have your two UIImages as properties or ivars loaded into memory (that is, if these aren't giant memory hogging images) and then do your toggling.
Related
I'm writing a test to verify a feature which copies an image to the pasteboard.
Here's the test, as I would prefer to write it:
// reset the paste board
UIPasteboard.generalPasteboard.image = nil; //<-- this explodes
XCTAssertNil(UIPasteboard.generalPasteboard.image);
// Grab some random existing image
UIImage *image = [UIImage imageNamed:#"some-image"];
MJKMyClass *myInstance = [[myInstance alloc] initWithImage:image];
[myInstance doSomethingThatCopiesImageToPasteboard]
XCTAssertNotNil(UIPasteboard.generalPasteboard.image);
This fails with:
failed: caught "NSInvalidArgumentException", "-[UIPasteboard setImage:]: Argument is not an object of type UIImage [(null)]"
Which is surprising, because, according to the UIPasteboard header, image is a nullable field.
#interface UIPasteboard(UIPasteboardDataExtensions)
<...>
#property(nullable,nonatomic,copy) UIImage *image __TVOS_PROHIBITED;
<...>
#end
I presume this means they are doing a runtime check on the argument, even though it is nullable.
Things I have tried:
comparing objects by id doesn't work because UIImage's are copied by the generalPastboard.image (every time you call UIPasteboard.generalPasteboard.image you can a different instance)
comparing by PNG representation might work, but seems gnarly.
comparing by image size has been my closest bet so far, but also seems roundabout.
You can clear the pasteboard without having to pass nil by using the items property:
UIPasteboard.generalPasteboard.items = #[];
Or in Swift:
UIPasteboard.generalPasteboard().items = []
For comparing UIImages, you might want to look at some other questions:
How to compare two UIImage objects
https://stackoverflow.com/search?q=uiimage+compare
I have an outlet called myImage for an imageView that is set up with an animation of 5 images. With a Tap Gesture Recognizer on it, I want to have the users tap on the correct image as it quickly passes to move onto the next level.
There is an error in my code and this does not work:
- (void)viewDidLoad {
[super viewDidLoad];
self.myImage.animationImages =
[NSArray arrayWithObjects:
[UIImage imageNamed:#"examplePic1.png"],
[UIImage imageNamed:#"examplePic2.png"],
[UIImage imageNamed:#"correctPic.png"],
[UIImage imageNamed:#"examplePic4.png"],
[UIImage imageNamed:#"examplePic5.png"],
nil];
[self.myImage setAnimationRepeatCount:0];
self.myImage.animationDuration = 1;
[self.myImage startAnimating];
}
- (IBAction)TapGestureRecognizer:(id)sender {
if (self.myImage.image = [UIImage imageNamed:#"correctPic.png"]) {
// Launch next level
}
else {
// Vibrate Device and subtract points from score
}
}
You have a fundamental misconception in your code about objects and equality. I assume that you meant "==" in your TapGestureRecognizer method. However, even if you changed the = to == would not give you what you want.
The expressions like
[UIImage imageNamed:#"examplePic1.png"]
call a class method of UIImage that creates a new UIImage object. You have created 5 of these objects, put them into an array, an set the animationImage array of your UIImage object to these images. These objects are all different objects from myView.image: I can tell because I can see from your code that you have assigned 5 new objects to the animationObjects array. Your == test cannot ever work because you are comparing self.image to a brand new UIImage object.
What you are trying to do is determine which image the user touched. There is no method in UIImageView that tells you which animation UIImage is currently showing. You are assuming that the image property of the view will be changed as the animation images are displayed, but there is no reason for this assumption to be true: it is certainly not stated in the documentation. Even if you corrected your code (by doing something like this):
if(self.image == [self.animationImages objectAtIndex:2]){
}
your code would not be correct.
If I were trying to do what you want, I would create a UIView with 5 UIImageView as subview, each with their own gesture recognizer. I would use the frame property of each subview to do my animation.
Looks like the options are to determine which image "should" be showing based upon the startTime of the animation.
Determine which of its animationImages a UIImageView is displaying?
Or, just use a timer to set the currently displayed image.
Detect which image was clicked in UIImageView with animationImages
I've got a pretty simple iOS app (adapted from basic master-detail boilerplate).
I've got RestKit set up to load data from a server. If an object's image URL gets updated, I download the image (using an AFHTTPClient subclass) and save its data using UIImagePNGRepresentation(image). Pretty straightforward.
So now, I've got a database that's already populated with objects - including their imageData. But for some reason, though I can get a UIImage instance from the data, that UIImage won't show up in a UIImageView.
I've got a category on the auto-generated NSManagedObject subclass, which (among other things) pulls the image data, and returns a UIImage instance:
#implementation Artwork (Helpers)
// ...
- (UIImage*)image {
if (self.imageData) {
return [UIImage imageWithData:self.imageData];
}
return nil;
}
#end
In my detail view, I have a UIImageView, whose image is set from the above method. Here's the relevant bit from my detail view controller. It gets called just before the segue, and works fine for setting the description text, but doesn't set the image correctly.
- (void)configureView {
// Update the user interface for the detail item (a Artwork instance in this case).
if (self.detailItem) {
// this works just fine
self.detailDescriptionText.text = self.detailItem.rawDescription;
// ... but this doesn't! Nothing is shown in the
UIImage *image = self.detailItem.image;
if (image) {
// Yes, the UIImage *is* there
NSLog(#"UIImage instance: %#, size: %fx%f", image, image.size.width, image.size.height);
// ... but this doesn't seem to any effect
self.imageView.image = image;
}
}
}
The NSLog call prints:
UIImage instance: <UIImage: 0x109a0d090>, size: 533.000000x300.000000
so it certainly seems like the UIImage object exists and has been unpacked from the data just like it should. But nothing shows up in the UIImageView.
Interestingly, if I set up a simple touch-listener on the detail view controller, I can show the image using the exact same code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UIImage *image = self.detailItem.image;
if (image) {
NSLog(#"UIImage instance: %#, size: %fx%f", image, image.size.width, image.size.height);
self.imageView.image = image;
}
}
That works perfectly - tap the screen and the image shows up immediately, and the NSLog call prints:
UIImage instance: <UIImage: 0x10980a7e0>, size: 533.000000x300.000000
So there really is image data, and it does get unpacked into a proper UIImage - but it won't show up.
So, all in all, it seems like there's some sort of timing or threading issue. But here I'm drawing a blank.
Make sure to set your image on the main thread :)
dispatch_async(dispatch_get_main_queue(), ^(void) {
/* your code here */
});
TableViewApplication[1458:70b] CUICatalog: Invalid asset name supplied: (null), or invalid scale factor: 2.000000
Getting this warning while working with TableViewController. How to rectify this error and which block is affected?
This one appears when someone is trying to put nil in [UIImage imageNamed:]
Add symbolic breakpoint for [UIImage imageNamed:]
Add $arg3 == nil condition on Simulator, $r0 == nil condition on 32-bit iPhone, or $x2 == nil on 64-bit iPhone.
Run your application and see where debugger will stop.
P.S. Keep in mind this also happens if image name is empty string. You can check this by adding [(NSString*)$x2 length] == 0 to the condition.
This error (usually) happens when you try to load an image with [UIImage imageNamed:myImage] but iOS is not sure if myImage is really a NSString and then you have this warning.
You can fix this using:
[UIImage imageNamed:[NSString stringWithFormat:#"%#", myImage]]
Or you can simply check for the length of the name of the UIImage:
if (myImage && [myImage length]) {
[UIImage imageNamed:myImage];
}
Since the error is complaining that the name you gave is (null), this is most likely caused by calling [UIImage imageNamed:nil]. Or more specifically, passing in a variable hasn't been set, so it's equal to nil. While using stringWithFormat: would get rid of the error, I think there's a good chance it's not actually doing what you want. If the name you supply is a nil value, then using stringWithFormat: would result in it looking for an image that is literally named "(null)", as if you were calling [UIImage imageNamed:#"(null)"].
Something like this is probably a better option:
if (name) {
UIImage *image = [UIImage imageNamed:name];
} else {
// Do something else
}
You might want to set a breakpoint in Xcode on that "Do something else" line, to help you figure out why this code is getting called with a nil value in the first place.
In Xcode 6.4, this seems to occur when using "Selected Image" for a tab bar item in the storyboard, even if it's a valid image.
This doesn't actually seem to set the selected state image anyway, so it needs to be defined in User Defined Runtime Attributes, and removed from the SelectedImage attribute of the Tab Bar Item
In my case i was passing [UIImage imageNamed:#""] which caused me to show the warning. Just add breakpoints to all the lines where you have used imageNamed and the debug the line where you find the warning.
This happened to me after a storyboard was split into several (the actual change happened when I was on holidays, so I don't know exactly how it was done).
After inspecting the XML of the storyboards, I found that an image reference which previously had pointed to "bottomBar" in the assets catalogue instead pointed to imageView:fFo-1g-jzs:image.
At the end of the XML file under the <resources> tag was tag named <image name="imageView:fFo-1g-jzs:image"> containing a big mutableData blob.
After resetting the image reference in the storyboard and removing the blob, the error went away.
You are supplying some invalid image name, so need to validate before putting it you can do any of the above ways whichever make sense for your code or like
if (iconImageName && [iconImageName length])
{
[UIImage imageNamed:iconImageName];
}
else
{
iconImageName.hidden = YES;
}
Hope it will help!!!!
I have just fixed this error. Just check the usage of the [UIImage imageNamed:(NSString*) imageName] function. If the imageName is nil, then error occurs.
The Reason to the error is passing a nil value to the "imageNamed:" method. To avoid this, you can hide your imageView when you try to pass the nil value. The chances may occur in reusing the imageViews in UITableView or may be in scrollViews.
I avoided the warning with the below check :
UIImageView *your_image_view;
NSString *imageName;
if(imageName && imageName.length){
your_image_view.hidden = NO;
your_image_view.image = [UIImage imageNamed:imageName];
}
else {
your_image_view.hidden = YES;
}
I got this warning when I load image use [[UIImage imageNamed:normalStr] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal], than, I change to [UIImage imageNamed:normalStr], warning was gone.
One approach is do class method swizzling to replace [UIImage imageNamed:] with your own implementation, then check the image name in your implementation. See the following:
How to swizzle a class method on iOS?
I implemented this in my UIImage(Debug) category:
+ (UIImage *)db_imageNamed:(NSString *)imageName {
if ([imageName length] == 0) {
NSLog(#"breakpoint here");
}
return [self db_imageNamed:imageName]; // not a recursive call here after swizzling
}
You might want to swizzle [UIImage imageNamed:inBundle:compatibleWithTraitCollection:] as well.
In my case I have implemented cell with UILabel, UIImageView and UITextFied, sometimes I don't want to display image, in that case I'm sending empty string "" to the imageView. Now the same error/warning is getting.
Error: [framework] CUICatalog: Invalid asset name supplied: ''
Solution is we have to pass nil instead of "" empty string.
Code:
if imgName.count > 0 {
selectedIconView.image = UIImage(named: imgName)
} else {
selectedIconView.image = nil
//You can also use
//selectedIconView.isHidden = true
}
Maybe you can use this to confirm the "imageName" is not a "nil";Then you will leave away this warning.
if (imageName) {
self.imageView.image = [UIImage imageNamed:imageName];
}
I am using iOS 7 SDK and Xcode 5. I want to set icons on UITabBarItem. I am using below method.
setFinishedSelectedImage: withFinishedUnselectedImage:
It was working till now. But suddenly it stopped displaying images.
I tried below various options :
[img imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[tabBarItem setSelectedImage:img];
[tabBarItem setImage:img];
[[UITabBarItem alloc] initWithTitle:title image:img selectedImage:img];
None of them is working. Here, img is the image downloaded from URL.
Then I tried with one of the images in app resource and it was displaying.
After that, I tried using temporary UIImageView with background color to red and set img to this UIImageView, it displayed red color instead of img.
But strange part is that I use the same img in other view controllers where it is displayed correctly.
Any idea how to solve this issue?
It was my mistake in code. I had to initialze img to some UIImage on declaration.
Below is shown what was the issue.
UIImage * img; // Image not initialized
// This condition was not satisfied and hence `img` was not storing any time.
if (condition)
{
img = ...;
}
// Below condition should have been satisfied if `img` was not initialized.
// But it did not. I am not getting why.
if (!img)
{
NSLog(#"Image is nil");
}
[tabBarItem setImage:img];