I'm having trouble with loops. I have one imageView which displays an artist's image and another imageView which I would like to display artwork of a random song. BUT, this artwork must not match the artist image. [To clear things up - the artist image is one of the song's artwork].
I'd like to essentially write this in Objective-C for iPhone:
Do {
Get artwork of random song in songsArray
Until{
image1 != image2;
}
This is what I've tried so far (firstArtwork is the artist's image and secondArtwork is the randomly-chosen artwork that must not be the same as firstArtwork).
-(UIImage *)getSecondImage{
MPMediaItemArtwork *firstArtwork = [self.mediaItem valueForProperty:MPMediaItemPropertyArtwork];
// Choose random song in songsArray + get Artwork
MPMediaItem *myItem = [songTracks objectAtIndex:arc4random() % songsArray.count];
MPMediaItemArtwork *secondArtwork = [myItem valueForProperty:MPMediaItemPropertyArtwork];
// Get images
UIImage *firstImage = [firstArtwork imageWithSize:CGSizeMake(1, 1)];
UIImage *secondImage = [secondArtwork imageWithSize:CGSizeMake(1, 1)];
// IF the two images are the same, repeat this block
// IF NOT, return secondImage
if ([firstImage isEqual:secondImage]){
[self getSecondImage];
}
else{
return secondImage;
}
return secondImage;
}
But this sometimes returns an image that's the same as the artist's image.
I've also tried using an NSPredicate but I get the error that you can't filter using the MPMediaItemPropertyArtwork.... so I can't use a preciate.
I'm not sure if I'm going about this logically/the correct way. Can anybody help me out and explain where I'm going wrong?
I think the problem is with your return value. Note that your if statement that checks the value of the 2 images doesn't actually change anything that gets returned to the initial method invoker. Also, your else statement is useless because whether or not your if statement is true, it will then return secondImage. You need to do something like this:
if ([firstImage isEqual:secondImage]){
secondImage = [self getSecondImage];
}
return secondImage;
This way, you update the value that is returned to the initial invoker.
Long story short: your pseudo-code is correct (a simple loop), but your implementation contains recursion, which is an unnecessary complexity in this case IMO (and seems that you're not quite sure what you're doing).
-(UIImage *)getSecondImage{
MPMediaItemArtwork *firstArtwork = [self.mediaItem valueForProperty:MPMediaItemPropertyArtwork];
UIImage *firstImage = [firstArtwork imageWithSize:CGSizeMake(1, 1)];
UIImage *secondImage = nil;
do {
// Choose random song in songsArray + get Artwork
MPMediaItem *myItem = [songTracks objectAtIndex:arc4random() % songsArray.count];
MPMediaItemArtwork *secondArtwork = [myItem valueForProperty:MPMediaItemPropertyArtwork];
// Get image
secondImage = [secondArtwork imageWithSize:CGSizeMake(1, 1)];
// IF the two images are the same, repeat this loop
// IF NOT, return secondImage
} while ([firstImage isEqual:secondImage]);
return secondImage;
}
Related
I found a way to store images of UIImagePickerControllerSourceTypePhotoLibrary in an NSArray but I can not find a solution to view images in an UIImageView from the NSArray. Here is the link to store image:
Can the selected images from library be stored in an array?
You just need to iterate through that array...
for(UIImage *img in self.imageArray){
self.image = img;
}
Or imageView:
for(UIImageView *imgView in self.imageArray){
self.imageView = imgView;
}
Lets say you stored images in array :
NSArray *imageArray = #[image1, image2, image3]; //imageX are arbitrary name for images.
To view these images one by one, you need to load them and show in UIImageView:
//lets assume you have multiple buttons and all targeted to this method.
-(IBAction)buttonClicked:(UIButton *)sender{
NSInteger index = sender.tag;
//here index is the integer to load the image.
if(index < imageArray.count){
self.imageView setImage: imageArray[index];
}
}
I am comparing cell.imageView.image with UIImage as below code.
Please refer below Code
UIImage *imgOne = [UIImage imageNamed:#"One"];
if([customCell.imageView.image isEqual: imgOne]){
NSLog(#"Right Image");
}
While debugging, I write as po [customCell.imageView.image isEqual imgOne], but it always returns as 'nil'.
Can anyone tell me how to compare this or proper way to compare?
Generally UIImageView can not store file name of image but it store only UIImage so, it is not possible to get file name of image which you add in UIImageView.
Thats way if you want to compare only image file name then it is not possible to compare it.
But If you want to compare two UIImage object then
UIImage *secondImage = [UIImage imageNamed:#"image.png"];
NSData *imgData1 = UIImagePNGRepresentation(self.imageView.image);
NSData *imgData2 = UIImagePNGRepresentation(secondImage);
BOOL isCompare = [imgData1 isEqualToData:imgData2];
if(isCompare)
{
NSLog(#"Image View contains image.png");
}
else
{
NSLog(#"Image View doesn't contains image.png");
}
If you matain the "image one" as a member var.(1)
And set the cell's image this value.(2)
Then you can compare using those two pointers.(3)
See this code:
//1
self.imgOne = [UIImage imageNamed:#"One"];
//2
customCell.imageView.image=self.imgOne
//3
if(customCell.imageView.image == self.imgOne)
{}
Instead of Imageview I tried with Button
And than i Check as below
if([cell.button.currentImage isEqual: [UIImage imagenamed:"Your Imagenem"]]){
NSLog(#"Right Image");
}
It works fine..
Thank you.
I need to take the current value of mtype and pass it forward to Mselect so that the image pushed forward is the same as the one rotating in the animation.
here is the code sample
- (void)viewDidLoad
{
//Array to hold Images
NSMutableArray *imageArray = [[NSMutableArray alloc] initWithCapacity:Mush_Count];
for (mtype = 1; mtype < Mush_Count; mtype++)
{
[imageArray addObject:[UIImage imageNamed:[NSString stringWithFormat:#"Mush%i.png", mtype]]];
//make button
SelectBt.imageView.animationImages = [NSArray arrayWithArray:imageArray];
SelectBt.imageView.animationDuration = 5;
[SelectBt.imageView startAnimating];
Mselect = mtype;
}
}
-(IBAction)Selection:(id)sender{
[self Placement];
}
-(void)Placement{
if (Place1Occ == NO) {
[self Place1];
}
}
-(void)Place1{
if (Place1Occ == NO) {
Place1.image =[UIImage imageNamed:[NSString stringWithFormat:#"Mush%i.png", Mselect]];
Place1Occ = YES;
}
}
The animation loops just fine and the selection of the images works but it's not selecting the image the is currently on the screen it selects the last image on the Array.
Any suggestions?
for (mtype = 1; mtype < Mush_Count; mtype++)
{
[imageArray addObject:[UIImage imageNamed:[NSString stringWithFormat:#"Mush%i.png", mtype]]];
}
That loop is enough to build the array of images - you don't need to set the imageView's animation images until this loop completes and the array is populated.
As it stands, you reset the animation images each loop and set Mselect to type each iteration: this is why you always get the last image index stored in Mselect
This code should be after the for loop:
SelectBt.imageView.animationImages = [NSArray arrayWithArray:imageArray];
SelectBt.imageView.animationDuration = 5;
[SelectBt.imageView startAnimating];
As far as I know, you can't get the current frame of the animation directly - you have to create a timer when you start the animation and have this count the number of frames (by increasing your Mselect value. Then use that to load the current image
Is SelectBT a subclass of UIButton? if so is it the (id)sender coming from your IBAction?
If so then you can just grab the image directly from the SelectBT instance by calling sender.imageView.image
As an aside, objective-C convention is to capitalize ClassNames, but start instances with lowerCase like this ClassName *instanceOfClassName and you're likely to take flack for it around here if you don't adhere to that convention
Update
Could you bump your imageArray into a class variable or a property? It already contains all the fully loaded UIImages, which you can get back out by calling [imageArray objectAtIndex:i]
Then you just have to keep track of which numeric index is facing your user, or which index they tapped and pull the corresponding image.
Feel free to post your whole class if you'd like us to explain more.
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.
This is my question:
I want to rotate my image when I got the degree it should rotate.
And my code is here
UIImage *image = imageView.image;
UIImage *originalImage = imageView.image;
CGAffineTransform transform = imageView.transform;
if (CGAffineTransformEqualToTransform(transform, CGAffineTransformRotate(CGAffineTransformIdentity, M_PI_2))) {
image = [UIImage imageWithCGImage:originalImage.CGImage scale:originalImage.scale orientation:UIImageOrientationRight];
} else if (CGAffineTransformEqualToTransform(transform, CGAffineTransformRotate(CGAffineTransformIdentity, M_PI))) {
image = [UIImage imageWithCGImage:originalImage.CGImage scale:originalImage.scale orientation:UIImageOrientationDown];
} else if (CGAffineTransformEqualToTransform(transform, CGAffineTransformRotate(CGAffineTransformIdentity, M_PI_2 * 3))) {
image = [UIImage imageWithCGImage:originalImage.CGImage scale:originalImage.scale orientation:UIImageOrientationLeft];
} else if (CGAffineTransformEqualToTransform(transform, CGAffineTransformRotate(CGAffineTransformIdentity, M_PI * 2))) {
image = originalImage; // UIImageOrientationUp
}
As I hope , the image will show as rotated. But after rotating, this images is still what it was. It means the method imageWithCGImage:scale:orientation: didn't work.
Some one can tell me why? Thanks.
You use
UIImage *image = imageView.image;
to get the handle of imageView.image, and you've set your changed image for (UIImage*)image which is just a reference of imageView.image.So if you want imageView.image to be change, you should set imageView.image again to make it change
add this in the back after your codes
imageView.image = image;
You need set the image again (after all that code)
imageView.image = image;
This is something that you will need to fundamentally understand. When you get a pointer to another object, and then set that pointer to something else, it doesn't affect the original object. Think of it this way:
Lunch *myLunch = myFriend.CurrentLunch;
This means that your lunch is current your friend's lunch.
myLunch = new MisoRamen();
Now your lunch is a different lunch.
myLunch.InsertWeirdSauce();
You just inserted a sauce into your own lunch, while your friend's lunch remains safe. If you want to change your friend's lunch you have to do this.
Lunch *newLunch = new MisoRamen();
newLunch.InsertWeirdSauce();
myFriend.CurrentLunch = newLunch;
Now your friend will gasp in shock as he/she eats a lunch with weird sauce in it.