Immediately initialize UIImage - objective-c

I have an array of UIImage objects as follows:
frames = [[NSMutableArray alloc] initWithCapacity:[sortedArray count]];
for (int nDx = 0; nDx < [sortedArray count]; nDx++)
{
NSString * sImageName = [sortedArray objectAtIndex:nDx];
[frames addObject:[UIImage imageWithContentsOfFile:[NSString stringWithFormat:#"%#/%#", imageFolderPath, sImageName]]];
}
In my timer method I am doing the following to cycle through the images:
self.image = [frames objectAtIndex:currentFrame];
currentFrame++;
if (currentFrame >= [frames count]) currentFrame = 0;
However, when I start the timer the images cycle slow the first time, and then everything works as expected. I have also tried this without a timer.
How can I pre-load the images so they are ready to go when my timer starts?
Thanks for the help.

You can have a separate thread to load the images, using this code.
If it works I'll add it here.

Here img_array is UIImageView
img_array.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"img_1.png"],
[UIImage imageNamed:#"img_2.png"],
[UIImage imageNamed:#"img_3.png"],nil];
[img_array.animationImages setAnimationRepeatCount:HUGE_VAL];
img_array.animationImages .animationDuration = 4;
[img_array.animationImages startAnimating];
[self.view addSubview:img_array]
Try this:

Related

Changing UIImageView dynamically

-(void)viewDidLoad {
NSMutableArray *coolImagesArray = [[NSMutableArray alloc] initWithObjects:#"active-1.jpg", #"active-2.jpg", #"active-3.jpg", #"active-4.jpg", #"active-5.jpg", nil];
}
-(void)someMethodWithData {
dispatch_async(dispatch_get_main_queue(), ^{
NSMutableArray *imagesArray = [[NSMutableArray alloc] init];
NSMutableString *inactiveString = [[NSMutableString alloc] init];
for (int i = 0; i < progress; i++) {
imageView.image = [UIImage imageNamed:[coolImagesArray objectAtIndex:i]];
inactiveString = [NSMutableString stringWithFormat:#"inactive-%d.png",i];
[imagesArray addObject:imageView];
}
UIImage *setImage = [UIImage imageNamed:#"inactive-1.png"];
for (int i = 0; i < [imagesArray count]; i++) {
[(UIImageView*)[imagesArray objectAtIndex:i] setImage:setImage];
}
});
}
This will always set the last or i(th) image correctly. It will not loop and change all the images I need. Is there another way to manage this?
imageView is pointing to one UIImageView object and in a loop you are changing the image of imageView not adding new UIImageView object to your array. All the objects inside the array pointing to 1 UIImageView object. So it is so normal that you can only change the last object's image only, because there is no other object in your array.
you should do it like:
dispatch_async(dispatch_get_main_queue(), ^{
NSMutableArray *imagesArray = [[NSMutableArray alloc] init];
NSMutableString *inactiveString = [[NSMutableString alloc] init];
for (int i = 0; i < progress; i++) {
UIImageView *temp = [[UIImageView alloc] initWithFrame:imageView.frame];
temp.image = [UIImage imageNamed:[coolImagesArray objectAtIndex:i]];
inactiveString = [NSMutableString stringWithFormat:#"inactive-%d.png",i];
[imagesArray addObject:temp];
}
UIImage *setImage = [UIImage imageNamed:#"inactive-1.png"];
for (int i = 0; i < [imagesArray count]; i++) {
[(UIImageView*)[imagesArray objectAtIndex:i] setImage:setImage];
}
});
For starters, I would create the image once so as to save memory.
I would also cast the object to a UIImageView (Not sure how that isn't getting flagged in xcode).
Lastly I would wrap it in a dispatch_async() to make sure it's happening on the main UI thread, because it could be getting called on a background thread and somehow the last image makes it to the main run loop, either way this is what it would look like:
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *setimage = [UIImage imageNamed:#"set-image.png"];
for (int i = 0; i < [imagesArray count]; i++) {
[(UIImageView *)[imagesArray objectAtIndex:i] setImage:setimage]];
}
});

How to Add UIImage to NSMutableArray

I'm trying to add my UIImage from web service to my NSMutableArray using this code:
for (int i=0; i<[totalRowCountString intValue]; i++)
{
NSString *criticsRatingString = [[JSON valueForKeyPath:#"movies.ratings.critics_rating"] componentsJoinedByString:#" "];
NSLog(#"criticsRatingString: %#", criticsRatingString);
if ([criticsRatingString isEqualToString:#"Certified Fresh"])
{
self.ratingImage = [UIImage imageNamed:#"rt_certified_fresh.png"];
}
else if ([criticsRatingString isEqualToString:#"Fresh"])
{
self.ratingImage = [UIImage imageNamed:#"rt_fresh.png"];
}
else if ([criticsRatingString isEqualToString:#"Rotten"])
{
self.ratingImage = [UIImage imageNamed:#"rt_rotten.png"];
}
else if ([criticsRatingString isEqualToString:#"Spilled"])
{
self.ratingImage = [UIImage imageNamed:#"rt_spilled.png"];
}
else if ([criticsRatingString isEqualToString:#"Upright"])
{
self.ratingImage = [UIImage imageNamed:#"rt_upright.png"];
}
[tomatorRatingImages addObject:self.ratingImage];
NSLog(#"tomatoRatingImages: %#", tomatorRatingImages);
}
But my NSLog for tomatoRatingImages returns NULL. Any ideas why it returns NULL?
UPDATE: my NSMutableArray is already initialized in my viewWillAppear method.
You must initialize the array before adding objects to it.
NSMutableArray *tomatorRatingImages = [[NSMutableArray alloc] init];
NSMutableArray * tomatorRatingImages =[[NSMutableArray alloc]init];
[tomatorRatingImages addObject:[UIImage imageNamed:#"rt_spilled.png"]];
[tomatorRatingImages addObject:[UIImage imageNamed:#"rt_spilled1.png"]];
[tomatorRatingImages addObject:[UIImage imageNamed:#"rt_spilled2.png"]];
you can enter multiple image in NSMutableArray.
If you have a property for the NSMutableArray instance, it's better to write getter to initialize it. It takes care of initializing the variable only ones also it gets loaded only when it's required.
-(NSMutableArray *) tomatorRatingImages {
if(_tomatorRatingImages == nil) {
_tomatorRatingImages = [NSMutableArray alloc] init];
}
return _tomatorRatingImages;
}
Initialize like this
NSMutableArray * tomatorRatingImages =[[NSMutableArray alloc]initWithCapacity:3];

Array with UIImageView elements - setImageWithURL

I have such code
arrayWithImages = [[NSMutableArray alloc] init];
NSEnumerator *enumForNames = [arrayWithNames objectEnumerator];
NSEnumerator *enumForURLs = [arrayWithURLs objectEnumerator];
id objName, objURL;
while(objName = [enumForNames nextObject]) {
objURL = [enumForURLs nextObject];
UIImageView *anImage = nil;
[anImage setImageWithURL:[NSURL URLWithString:objURL]];
(...)
[arrayWithImages addObject:anImage];
}
And each time I got SIGABRT in line with "[arrayWithImages addObject:anImage];"
What's here wrong?
I don’t see an setImageWithURL method on UIImageView. Where is this from?
Is there any output from the SIGABRT crash?
Try this code:
// Download the image
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:objURL]];
// Make an UIImage out of it
UIImage *anImage = [UIImage imageWithData:imageData];
// Create an image view with the image
UIImageView *imageView = [[UIImageView alloc] initWithImage:anImage];
// Check to make sure it exists
if (imageView != nil) {
// Add it to your array
[arrayWithImages addObject:imageView];
else {
NSLog(#"Image view is nil");
}
Note that you should download the images asynchronously to avoid hanging the loop. This blog post discussing asynchronous image downloading.
Also if you know that [enumForURLs nextObject]; will return an NSString (or even better, NSURL) you should assign objURL to type NSString (or NSURL).

CAAnimation not animating my sequence of images

I'm having trouble with animating with CAAnimation, it doesn't seem to give me any errors but it isn't animating. I'm confused
NSMutableArray *animationImages = [NSMutableArray array];
//Adding images into array
for (int i=0;i<=5;i++){
UIImage *imgfile = [NSString stringWithFormat:#"%#/ConusOverlay/%d_ConusOverlay.gif",documentsPath,i];
[animationImages addObject: imgfile];
}
CAKeyframeAnimation *animationSequence = [CAKeyframeAnimation animationWithKeyPath: #"contents"];
animationSequence.calculationMode = kCAAnimationLinear;
animationSequence.autoreverses = NO;
animationSequence.duration = 1;
animationSequence.repeatCount = HUGE_VALF;
NSMutableArray *animationSequenceArray = [NSMutableArray array];
for (UIImage *image in animationImages) {
[animationSequenceArray addObject:image]; //<--Does this have to be (id)image.CGImage ?, if I am correct you are unable to add CGImage to an array
}
animationSequence.values = animationSequenceArray;
[mlLayer.contents addAnimation:animationSequence forKey:#"contents"];
CoreAnimation usually takes CGImageRefs and not UIImages. Try replacing the image with the (id)image.CGImage as you suggested. Arrays can store CGImageRefs!

Displaying images in sequence with a loop

I got an NSArray with 5 pictures. I want to display them one after the other in a loop.
My code :
NSArray *tabImage = [[NSArray alloc] init];
tabImage = [[NSArray arrayWithObjects:
[UIImage imageNamed:#"picto_1.png"],
[UIImage imageNamed:#"picto_2.png"],
[UIImage imageNamed:#"picto_3.png"],
[UIImage imageNamed:#"picto_4.png"],
[UIImage imageNamed:#"picto_5.png"],
nil] retain];
int var = 0;
var = indexPath.row;
for (int var = 0; var < 20; var++) {
pictoImage.image = [tabImage objectAtIndex:(var % 5)];
}
I got the same picture all the time.
Thanks for help.
I’m guessing pictoImage is an UIImageView. In that case look at the class reference, specifically the animationImages properties.
pictoImage.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"picto_1.png"],
[UIImage imageNamed:#"picto_2.png"],
[UIImage imageNamed:#"picto_3.png"],
[UIImage imageNamed:#"picto_4.png"],
[UIImage imageNamed:#"picto_5.png"],
nil];
// How many seconds it should take to go through all images one time.
pictoImage.animationDuration = 5.0;
// How many times to repeat the animation (0 for indefinitely).
pictoImage.animationRepeatCount = 4;
[pictoImage startAnimating];
You are not giving the framework time to actually render the images to the window.
All your updates are being coalesced into one "setNeedsDisplay" call. On the next iteration of the run loop, the image view will be rendered using the last image that you set in the loop.
If pictoImage is an UIImageView, #Hagelin's answer is the best way to go. Now, if pictoImage is not an UIImageView object then you will have to take a different approach and that definitely is not a loop.
Set an NSTimer with a desired time interval and invoke a method that updates pictoImage iterating over the tabImages. It should be something like this :-
- (void)setup {
...
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(updatePictoImage:)
userInfo:nil
repeats:YES];
...
}
- (void)updatePictoImage:(NSTimer*)theTimer {
static int i = 0;
if ( i > 20 ) {
pictoImage.image = [tabImages objectAtIndex:(i % 5)];
} else {
[theTimer invalidate];
}
}
This should update the pictoImage every 2 seconds with images in tabImages.
You don't print anything.
You are overriding the contents of your pictoImage 20 times in a row, leaving it with the last assignment when var is 19, so it should be picto_4.png.
Also, the whole var declaration doesn't make much sense at all... first you set it to 0, then you set it to indexPath.row, and in the loop it is completely redefined....