I want to pause the image from an array - ios

I am creating an animation using the below code:
NSMutableArray *dashBoy = [NSMutableArray array];
for (int i = 1; i<= 20; i++) {
butterfly = [NSString stringWithFormat:#"5c_%d.jpg", i];
if ((image = [UIImage imageNamed:butterfly]))
[dashBoy addObject:image];
}
[stgImageView setAnimationImages:dashBoy];
[stgImageView setAnimationDuration:7.0f];
[stgImageView setAnimationRepeatCount:-1];
[stgImageView startAnimating];
My requirement is if dashBoy is 5c_10.jpg, then pause the image for about 5 sec and then resume animation and another if dashBoy is 5c_20.jpg, then pause the image again for about 5 sec and resume again. Is it possible?

You can't use variable speeds for UIImageView animations like this.
There are a couple of ways around it though.
1. Do it all yourself.
For this you would use something like an NSTimer and have it fire a method repeatedly to change the images for you. Using this you can time each image individually (you could even create a data object that holds an image and the length of time to show it and then create and array of these.
2. Manipulate the current method.
If you have 20 images and you want to show them all in 7 seconds then thats... 0.35 seconds per image. So a 5 second pause is about 14 images worth.
So instead of adding each image once you can add 1-9 once and then add 10 fourteen times. 11-19 once and then 20 fourteen times.
This will then swap like it is doing but when it reaches 10 it will swap it for another copy of the same image so it will look like it's pausing.
You will then have to increase the duration... to 17 seconds to get a similar duration for each image.
Which I'd do?
Although it sounds like a hack (because it is) I think I'd give the second method a go first. It's a lot easier to get working so if it does fail you haven't spent a long time setting it up.
The first method is a lot more work to set up but will allow for greater control of the animation.
Quick and dirty example for method 1
Create an object something like...
MyTimedImage
------------
UIImage *image
CGFloat duration
So for instance...
// probably want this as a property
NSMutableArray *timedImages = [NSMutableArray array];
MyTimedImage *timedImage = [MyTimedImage new];
timedImage.image = [UIImage imageNamed:[NSString stringWithFormat:#"5c_%d.jpg", i]];
timedImage.duration = 0.4;
[timedImages addObject:timedImage];
Then you want a way of displaying them...
//set up properties something like this...
#property (nonatomic, assign) NSInteger currentIndex;
#property (nonatomic, assign) BOOL paused;
#property (nonatomic, assign) NSTimer *imageTimer;
- (void)displayNextImage
{
if (self.paused) {
return;
}
NSInteger nextIndex = self.currentIndex + 1;
if (nextIndex == [self.timedImages count]) {
nextIndex = 0;
}
MyTimedImage *nextImage = self.timedImages[nextIndex];
self.currentIndex = nextIndex;
self.imageView.image = nextImage.image;
self.imageTimer = [NSTimer scheduledTimerWithInterval:nextImage.duration target:self selector:#selector(displayNextImage) userInfo:nil repeats:NO];
}
Using the properties that you've exposed you can pause the image view on the current image from a button press (for example).
To start the process just run [self displayNextImage]; you can start anywhere in the loop of images too.

using UIImageView animation, this is not possible, you may need to create your own animation logic like loading all UIImages in array and through timer, switch to next animation frame and when you desire to pause, invalidate the timer.

Related

Changing UICollectionView cell image at regular interval

I am developing an IOS 10.x application using UICollectionView and would like to change the image of specific cells, at regular interval.
The code below shows the current implementation. Even though it should change the cell background image every half of second, it changes the images immediately disregarding the NSThread SleepAt interval of 0.5 seconds.
I suspect something about the main thread handling or the ReloadItem method but hasn't reached a clear conclusion. Any insight is very welcome! Thank you.
NSNumber* originalCardSelected;
int position;
for (int i = 0; i < [opponentOriginalCardArray count]; i++) {
originalCardSelected = [opponentOriginalCardArray objectAtIndex:i];
position = [self convertLevelDataPositionToCellViewPosition:[originalCardSelected intValue]];
NSMutableArray *tmpBackgroundAssets = [self getNewAssetBackgroundBasedOnBackgroundType:playbackBackground Index:position];
self.backgroundAssets = tmpBackgroundAssets;
dispatch_async(dispatch_get_main_queue(), ^{
[collectionViewRoot reloadItemsAtIndexPaths:[collectionViewRoot indexPathsForVisibleItems]];
});
[NSThread sleepForTimeInterval:0.5];
}
You should use performBatchUpdates(_:completion:) methods and add your for loop inside it.
Remember to not keep strong references inside the block to avoid retain cycles.
EDIT:
and in the completion block, you can check if finished and add your NSThread methods

Updating images in UIImageView during execution?

I have an interface which contains several UIImageView components on a view and i would like to update the animation images in run-time.
The main idea is to change the animation images into a thread with a delay of 2 seconds. The code below works fine. However, when i introduce a sleep time (with the commented NSThread sleepForTime); it no longer works. I am sure there is a logical explanation but i cannot identify it.
It's important to note that the animation is already running with another set of animated images.
Any help or tip is more than welcome :)
dispatch_async(allowToTouchThread, ^{
//[NSThread sleepForTimeInterval:2.0];
int randomnReward = 0;
WizzReward* currentReward = [rewardListForPages objectAtIndex:randomnReward];
WizzAnimalModel* animalModel = [gameLevelManager getAnimalModelByCategoryId: [currentReward getAnimalId]];
NSMutableArray* expressionsForAnimals = [animalModel getArrayForClosedEyesFaceExpression];
float animationDuration = [animalModel getStandardRewardAnimationDuration];
pageContentViewController.imagesArrayFileLevel1 = expressionsForAnimals;
pageContentViewController.animationLevel1Duration = animationDuration;
}
});
What about replacing your dispatch_async to a dispatch_after and set a delay of 2 seconds:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
int randomnReward = 0;
WizzReward* currentReward = [rewardListForPages objectAtIndex:randomnReward];
WizzAnimalModel* animalModel = [gameLevelManager getAnimalModelByCategoryId: [currentReward getAnimalId]];
NSMutableArray* expressionsForAnimals = [animalModel getArrayForClosedEyesFaceExpression];
float animationDuration = [animalModel getStandardRewardAnimationDuration];
pageContentViewController.imagesArrayFileLevel1 = expressionsForAnimals;
pageContentViewController.animationLevel1Duration = animationDuration;
});
Changing the animated images without any timer, could be done directly by modifying the array of images.
However, changing the same animated images with a timer, needed 3 steps:
first the modification of the image arrays
second the actual re-association of the UIView AnimationImages to the modified array of images;
and finally startAnimating the UIView eventhough it hasn't been stopped beforehand
The source code below now works fine with a timer:
WizzReward* currentReward = [rewardListForPages objectAtIndex:0];
WizzAnimalModel* animalModel = [gameLevelManager getAnimalModelByCategoryId: [currentReward getAnimalId]];
NSMutableArray* expressionsForAnimals = [animalModel getArrayForClosedEyesFaceExpression];
pageContentViewController.imagesArrayFileLevel1 = expressionsForAnimals;
pageContentViewController.reward1CurrentPage.animationImages = pageContentViewController.imagesArrayFileLevel1;
[pageContentViewController.reward1CurrentPage startAnimating];
I did find neither "time vs no-timer difference"information in the literature nor actual reason why it should be done like that; but it works every time. Hope it helps anyone who runs into the same problem.

iOS Animating a series of images

I have an iOS App that loads a set of images and a duration into an array then I have a timer that displays the images like so:
- (void)fireTimer:(NSTimer *)theTimer
{
self.image = [frames objectAtIndex:currentFrame];
NSTimeInterval time = [[durations objectAtIndex:currentFrame] floatValue];
self.timer = [NSTimer scheduledTimerWithTimeInterval:time target:self selector:#selector(fireTimer:) userInfo:nil repeats:NO];
currentFrame++;
if (currentFrame >= [frames count])
{
currentFrame = 0;
[timer invalidate];
}
}
To start the animation I call fireTimer and cycle through the images then when all the images are processed I call [timer invalidate] to stop the animation. I cannot use startAnimation because I need different durations for each image.
Right know I am NOT doing this on a background thread so the animation is choppy because other processing is happening whilst the image animates.
What is the best way to animate this in the background? Can I simply put this call to fireTimer in a block?
I know this may not be the best way to animate an image on iOS, but I do not want to do a lot of refactoring on the code right now.
Thanks for any suggestions or examples for a better solution!!!
I would suggest you use UIImageView to animate your images : it is made to do this task. If, like you say, some images needs to remains longer then others, then you can just display them many times. Let's say that image2 needs to be displayed twice longer than image1 and image3, just initialize the array animationImages on your UIImageView like : #[image1, image2, image2, image3].
Instead of using a timer, you could use performSelector: withObject: afterDelay:
-(void)loopBackground:(int)index
{
if(index < [self.durations count]{
self.image = [self.frames objectAtIndex:index];
[self performSelector:#selector(loopBackground:) withObject:index++ afterDelay:[[self.durations objectAtIndex:index] floatValue]];
}
}

How can I take the current integer value out of my array loop when I press my button on Xcode?

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.

scrolling images in ios automatically

i have multiple images in array and a scrollView all the images should scroll automatically and when i clicked the image it should navigate to other view and display its details. after completing images scrolling from 0 to end of the array it should Again load 1st image i.e 0. in Animating i have lot of problem please help me....
iam using this code
[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(onTimer) userInfo:nil repeats:YES];
- (void) onTimer {
// Updates the variable h, adding 100 (put your own value here!)
h += 100;
//This makes the scrollView scroll to the desired position
yourScrollView.contentOffset = CGPointMake(0, h);
}
try iCarousel library for scrolling the images, use autoscrolling example for the reference, set wrap property to yes if you want to repeat the content in the loop. add image array to carousel and implement carousel datasource and delegate methods to scroll the images. you can change different types like linear, rotary or overflow etc.
you can create image outlet after that
NSMutableArray *imgArray = [[NSMutableArray alloc]init];
for (int i =0; i<imgUrlArray.count; i++) {
NSString *imgStr = [serviceImgArray objectAtIndex:i];
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:imgStr]];
[imgArray addObject:[UIImage imageWithData:imageData]];
}
yourimageView.animationImages = imgArray;
yourimageView.animationDuration = 10;
[yourimageView startAnimating];
that's it.

Resources