Loop through UIImageViews - Objective C - ios

I have some UIImageViews in an array and want to loop through them to set an image, but I don't know how.
If I have one ImageView, imgv, then I do this:
self.imgv.image =
But how do I behave with many UIImageViews in a loop? I can't do the following:
for(int i = 0; i < [imageViewArray count]; i++)
{
self.i.image =
}

You use the index in the loop to get an item out of the array:
for(int i = 0; i < [imageViewArray count]; i++)
{
UIImageView *imageView = imageViewArray[i];
imageView.image = ...;
}
or, you use a for in loop:
for (UIImageView *imageView in imageViewArray)
{
imageView.image = ...;
}

for(int i = 0; i < [imageViewArray count]; i++)
{
UIImageView *tempImageView = [imageViewArray objectAtIndex:i];
tempImageView.image=image;
}

for(int i = 0; i < [imageViewArray count]; i++)
{
[imageViewArray[i] setImage:image];
}

If you need to set same image to all image views in the array then simply use,
[imageViewArray makeObjectsPerformSelector:#selector(setImage:) withObject:image];
If you need to set different images then you have to loop through the array like most of the answer have mentioned.
Hope that helps!

Try this
for(UIImageView *imgVw in imageViewArray)
{
imgVw.image = ...;
}
for - in is used to iterate through all the element of an array.

Related

Objective-C: Setting an alpha value with an array of elements

I'm quite new at objective-c and I'm trying to set an array of labels at 0.0 Alpha with a for loop. Can someone give me a help?
NSArray *fadeLabels = #[#"_lonLabel", #"_firstLat",#"_firstLon",#"_firstReal",#"_firstMagnetic",#"_firstSpeed",#"_speedLabel",#"_realNorthLabel",#"_magneticNorthLabel"];
for (int i=0; i<[fadeLabels count]; i++) {
[fadeLabels objectAtIndex:i];
//setAlpha:0.0f?
}
Use an array of views instead of array of strings. insert you views in the array.
NSArray *fadeLabels = #[ _lonLabel, _firstLat, _firstLon, _firstReal, _firstMagnetic, _firstSpeed, _speedLabel, _realNorthLabel, _magneticNorthLabel];
for (int i=0; i<[fadeLabels count]; i++) {
UIView *view = (UIView *)[fadeLabels objectAtIndex:i];
[view setAlpha:0.0f];
}
Your are assigning array with the String with name is equalTo your UILabel object so you need to
replace your array elements like this
#"_lonLabel" to _lonLabel
NSArray *fadeLabels = #[ _lonLabel, _firstLat, _firstLon, _firstReal, _firstMagnetic, _firstSpeed, _speedLabel, _realNorthLabel, _magneticNorthLabel];
for (int i=0; i<[fadeLabels count]; i++) {
UILabel *label = (UILabel *)fadeLabels[i];
label.alpha = 0.0;
}
You also should better use for...in instead of the "old" for.
NSArray *fadeLabels = #[ _lonLabel, _firstLat, _firstLon, _firstReal, _firstMagnetic, _firstSpeed, _speedLabel, _realNorthLabel, _magneticNorthLabel];
for (UILabel *label in fadeLabels) {
label.alpha = 0.0;
}

Randomly swap the positions of 4 UIButtons

I have 4 UIButtons, positioned in my VC. I want to randomly swap the positions of each button. I've placed all of the UIButton positions into a NSMutableArray
self.frameArray = [[NSMutableArray alloc] init];
[self.frameArray addObject:[NSValue valueWithCGRect:CGRectMake(60,171,64,64)]];
[self.frameArray addObject:[NSValue valueWithCGRect:CGRectMake(198,171,64,64)]];
[self.frameArray addObject:[NSValue valueWithCGRect:CGRectMake(60,333,64,64)]];
[self.frameArray addObject:[NSValue valueWithCGRect:CGRectMake(198,333,64,64)]];
`
and all of my buttons are in a NSArray
self.buttons = #[self.button1, self.button2, self.button3, self.button4];
but i'm really not sure where to go from here, to make the positions of the UIButtons to randomly swap. Any help would be appreciated
Basically you want to create the frameArray then randomize the order of the frames and then apply them to the buttons.
Step One: Randomize the frameArray (place code after creation of frameArray)
NSUInteger count = [self.frameArray count];
for (NSUInteger i = 0; i < count; ++i) {
NSInteger remainingCount = count - i;
NSInteger exchangeIndex = i + arc4random_uniform((u_int32_t )remainingCount);
[self.frameArray exchangeObjectAtIndex:i withObjectAtIndex:exchangeIndex];
}
Step Two: Set Button Frames
for (int i = 0; i < [self.buttons count]; i++) {
[[self.buttons objectAtIndex:i] setFrame:[self.frameArray objectAtIndex:i]];
}
You can use arc4random_uniform() to get a random button and a random Rect from the arrays, and then assign the random Rect to the random button's frame:
NSInteger randomButton = arc4random_uniform((u_int32_t)self.buttons.count);
NSInteger randomRect = arc4random_uniform((u_int32_t)self.frameArray.count);
UIButton *button = self.buttons[randomButton];
NSValue *theRectValue = self.frameArray[randomRect];
CGRect rect = [theRectValue CGRectValue];
button.frame = rect;
I think this will work.

UIImageView animationDuration with fade effects

I'am searching for a (very) simple way to crossfade images within animationDuration time. I tried using NSTimer and some other stuff I found here, but no solution satisfy or helps me.
I create this stuff in a method (without comments) ...
- (UIImageView *)playSequence{
NSArray *structureArray = self.contenManager.ImageViewControllerSize;
NSMutableArray *structuresToPlay = [[NSMutableArray alloc] init];
// walk thru current collection
for(NSInteger i = 0; i < [self.currentCollection count]; i++)
{
NSInteger index = [[self.currentCollection objectAtIndex:i] integerValue];
[structuresToPlay addObject:[UIImage imageNamed:[structureArray objectAtIndex:index]]];
}
_playSequence = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
_playSequence.animationImages = structuresToPlay;
_playSequence.animationDuration = 5 * structuresToPlay.count;
[_playSequence startAnimating];
return _playSequence;
}
Here is the part where the method is called ...
- (void)justPlaySelection
{
UIView *justPlaySelection = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
// some background music code ...
// add play sequence
[justPlaySelection addSubview:self.playSequence];
// add close button
// { ... }
[self presentSemiView:justPlaySelection];
}
- (UIImageView *)playSequence
{
if (_playSequence == nil)
{
NSArray *structureArray = self.contenManager.ImageViewControllerSize;
NSMutableArray *structuresToPlay = [[NSMutableArray alloc] init];
// walk thru current collection
for(NSInteger i = 0; i < [self.currentCollection count]; i++)
{
NSInteger index = [[self.currentCollection objectAtIndex:i] integerValue];
[structuresToPlay addObject:[UIImage imageNamed:[structureArray objectAtIndex:index]]];
}
_playSequence = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
}
_playSequence.animationImages = structuresToPlay;
_playSequence.animationDuration = 5 * structuresToPlay.count;
[_playSequence startAnimating];
return _playSequence;
}
Here is another way to switch between to UIImageViews, it wouldn't be hard to add in the fade in and out.
- (void) performAnimationOfFrameAtIndex:(NSNumber*)indexNum
{
int index = indexNum.intValue;
BOOL completedSequece = index >= [self.frames count];
if (completedSequece) return;
UIImageView *imgIn;
UIImageView *imgOut;
if (index % 2 == 0) {
imgIn = self.animationImageViewOne;
imgOut = self.animationImageViewTwo;
}
else {
imgIn = self.animationImageViewTwo;
imgOut = self.animationImageViewOne;
}
imgIn.image = [self.frames objectAtIndex:index];
[self.view sendSubviewToBack:imgOut];
double speed = 0.1;
[self performSelector:#selector(performAnimationOfFrameAtIndex:) withObject:[NSNumber numberWithInt:index + 1] afterDelay:speed];
}
I created a project that does exactly what you describe (an effect like UIImageView animation sequence, but with a cross-fade between images.)
The project is on github: https://github.com/DuncanMC/Animate-Img
You need to have 2 image views.
The trick I use is to stack them on top of each other, and simply animate the top image view from alpha 1 -> 0, then switch images in the top image view and animate it from alpha 0 -> 1.0, so the new image is revealed.
The project demos a morph transition using only 5 frames. Each frame is marked with a number so you can see the frame changes. It has a switch which lets you turn cross-fading on or off.

Change Animation Speed Series of Images

I have a series of images, I want them to repeat. However, I want the first half to play in, for example 2 seconds, then the second half to play in 5 seconds.
It is quite easy to play a series of images, using the following
- (void) completeCycles:(int) cycles inhalePercentage:(int) inhalePercent exhalePercentage:(int) exhalePercent totalCycleTime:(int) time
{
NSMutableArray *textures = [NSMutableArray array];
for (int i = 0; i < kNumberBreathingImages; i++) {
NSString *textureName = [NSString stringWithFormat:#"breath%d.png", i];
for (int i = 0; i < inhalePercent; i++) {
[textures addObject:[UIImage imageNamed:textureName]];
}
}
for (int i = kNumberBreathingImages - 1; i > 0; i--) {
NSString *textureName = [NSString stringWithFormat:#"breath%d.png", i];
for (int i = 0; i < exhalePercent; i++) {
[textures addObject:[UIImage imageNamed:textureName]];
}
}
self.animationImageView.animationImages = textures;
self.animationImageView.animationDuration = time;
self.animationImageView.animationRepeatCount = cycles;
[self.animationImageView startAnimating];
}
However, I want the first half of the animation to take x time and the second half to take y time.
I don't think the above will allow me to do this, just wondering what a better approach would be.
Pretty sure will need to use
UIView animateWithDuration:animations: completion:
Thanks for any assistance.
This code creates this effect,
The animation system on UIImageView is very limited. I would suggest that you make your own implementation with say 2 image view.
You would than change the image in one imageview and the fade in and out using UIView animateWithDuration
I have written a method for you. Please note: I have not tested it.
It assumes you have your frames in a array called 'frames' and have two UIIMageView placed on top of each other called 'imgv1' and 'imgv2'
-(void)performAnimationOfFrameAtIndex:(NSNumber*)indexNum
{
int index = [indexNum intValue];
if(index >= frames.count)
{
return;
}
UIImage *img = [frames objectAtIndex:index];
UIImageView *imgIn;
UIImageView *imgOut;
if(index % 2 == 0)
{
imgIn = imgv1;
imgOut = imgv2;
}
else
{
imgIn = imgv2;
imgOut = imgv1;
}
imgIn.image = img;
[self.view sendSubviewToBack:imgIn];
[UIView animateWithDuration:0.1 animations:^
{
imgIn.alpha = 1;
imgOut.alpha = 0;
} completion:^(BOOL finished)
{
[self performSelectorOnMainThread:#selector(performAnimationOfFrameAtIndex:) withObject:[NSNumber numberWithInt:index+1] waitUntilDone:NO];
}];
}
Thanks for the idea,
I changed your code above to get the desired effect I wanted, now it works perfect. The alpha was causing a "strobe" effect even when the duration is 0 seconds.
Here is my final code
Enjoy the 100 :-)
- (void) performAnimationOfFrameAtIndex:(NSNumber*)indexNum
{
int index = indexNum.intValue;
if (index >= self.frames.count) return;
UIImage *img = self.frames[index];
UIImageView *imgIn;
UIImageView *imgOut;
float speed = (index <= self.frames.count / 2) ? 0.1 : 1; // first half : second half speed.
if (index % 2 == 0) {
imgIn = self.animationImageViewOne;
imgOut = self.animationImageViewTwo;
}
else {
imgIn = self.animationImageViewTwo;
imgOut = self.animationImageViewOne;
}
imgIn.image = img;
[self.view sendSubviewToBack:imgIn];
[self performSelector:#selector(performAnimationOfFrameAtIndex:) withObject:[NSNumber numberWithInt:index+1] afterDelay:speed];
}
I don't think the above will allow me to do this, just wondering what a better approach would be.
Actually, it will. You just need to repeat the images as you form the sequence. For the images in the first group, repeat each one twice before going on to the next one. For the images in the second group, repeat each one five times before going on to the next one. Now set the time for the total animation to 7 seconds. Since there are about the same number of images in each group originally, you can readily see that this means the first group will take about 2 seconds and the second group will take about 5 seconds.

UIButton cannot be displayed

in my app i'm using a scroll View (paging). each view in the scroll view (UIImageView) contains an image and each image has tags (buttons) scattered all over the pic. so here is my code:
for (int i = 0; i < self.pictures.count; i++)
{
//The first loop is to loop to every picture
int nbOfTags = classObject.tagsImages.count;
for (int j = 0; j < nbOfTags; j++)
{
//Second loop is to loop to each tag corresponding to the picture
ListTags *listTags = [[ListTags alloc]init];
NSMutableArray *tagInfo = [[NSMutableArray alloc]init];
listTags = [tagInfo objectAtIndex:j];
float tagX = [listTags.tag_x floatValue];
float tagY = [listTags.tag_y floatValue];
float x = 1024*i+ tagX;
float y = tagY;
CGRect rect = CGRectMake(x, tagY, 20, 20);
UIButton *button = [[UIButton alloc] initWithFrame:rect];
UIImage * buttonImage = [UIImage imageNamed:#"blueCircle.png"];
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[self.scrollView addSubview:button];
}
}
problem: when i run the code i can't see the buttons (tags) on the picture. if i replace "i" with "j" in
float x = 1024*i+ tagX;
the buttons can be seen, however it's not the desired coordinates. so why "i" can't work? am i doing anything wrong or missing anything?
In interface builder (or storyboard - IB) uncheck autolayout (if it's checked) then your button will be displayed where you want.
See my comments in the code below:
for (int i = 0; i < self.pictures.count; i++)
{
//The first loop is to loop to every picture
/*
* This will give you the same number of tags for every image.
* Is that what you want?
*/
int nbOfTags = classObject.tagsImages.count;
for (int j = 0; j < nbOfTags; j++)
{
//Second loop is to loop to each tag corresponding to the picture
/* This allocates a brand new ListTags object EVERY time through the loop. */
ListTags *listTags = [[ListTags alloc]init];
/* This allocates a brand new EMPTY array EVERY time through the loop. */
NSMutableArray *tagInfo = [[NSMutableArray alloc]init];
/*
* This discards the new ListTags object that you just created two lines ago
* and replaces it with an object from tagInfo. Which doesn't exist because
* you just created a new array in the previous line. This really should
* crash, which leads me to believe that this isn't the actual code that you
* are using. Post the actual code that you are using so that we can help you
* better.
*/
listTags = [tagInfo objectAtIndex:j];
/* None of this is valid since listTags is nil/we never should have gotten here. */
float tagX = [listTags.tag_x floatValue];
float tagY = [listTags.tag_y floatValue];
float x = 1024*i+ tagX;
float y = tagY;
CGRect rect = CGRectMake(x, tagY, 20, 20);
UIButton *button = [[UIButton alloc] initWithFrame:rect];
UIImage * buttonImage = [UIImage imageNamed:#"blueCircle.png"];
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[self.scrollView addSubview:button];
}
}

Resources