How to change images periodically using NSTimer in iPhone progranmming?
I create an image view for loading images.
I want to display images in imageview and periodically change images by using NSTimer.
Instead of using NSTimer, I would just use an arrary of UIImages and animate them. See the documentation from here.
import the images you like to your bundle application
called them image1.png, image2.png image3.png and so on....
Add UIImageview in interface builder call it (reference) "theImage"
in the H file:
#interface delme3ViewController : UIViewController {
UIImageView *theImage;
int imageCount;
}
#property (nonatomic, retain) IBOutlet UIImageView *theImage;
#end
in the M file:
- (void)viewDidLoad
{
[super viewDidLoad];
[NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(animateFunction)
userInfo:nil
repeats:YES];
imageCount = 1;
}
-(void)animateFunction
{
NSLog(#"Timer heartbeat %i",imageCount);
imageCount = imageCount + 1;
NSString *imageName = [NSString stringWithFormat:#"image%i.png"];
[theImage setImage:[UIImage imageNamed:imageName]];
}
you can also use array of image names rather renaming images in your bundle. :)
Related
I am writing a simple application that consists of 2 UIImageViews and 2 UIButtons. The UIImageViews are placed on top of the UIButtons.
I have 1 UIImage that appears on a random UIImageView and disappears after 2 seconds. The user then has to tap on the button they think the image appeared on.
I shuffle the UIImageView array and use the first element (index 0) for the image to be displayed on. When shuffling I keep track of which element (i.e from which index. lets say from index "n") was placed on index 0 of the array.
However, when a button is pressed i compare the id of the button pressed with the id of the button with index n. (because that is the index of the random UIImageView).
But for some reason it is not working. :(
Here is my code: (i didn't upload the .h file. it just contains declarations.)
The code below doesn't produce any error/warning messages. It just doesn't output the result I want.
#interface ViewController ()
#property (strong, nonatomic) NSMutableArray* tempButton;
#property (strong, nonatomic) NSMutableArray *tempViews;
#property (strong, nonatomic) UIImage *myImage;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_myImage = [UIImage imageNamed:#"hello"];
_tempButton = [[NSMutableArray alloc] initWithObjects:_button1, _button2, nil];
_tempViews = [[NSMutableArray alloc]initWithObjects:_image1, _image2, nil];
[self displayonView];
}
-(void)displayToFindSymbol{
[_toFindImage setImage:_myImage];
_toFindImage.contentMode = UIViewContentModeScaleAspectFit;
}
- (IBAction)pressed:(id)sender {
UIButton *result = (UIButton *)sender;
if (result == _tempButton[_correctButton]) {
NSLog (#"Correct");
}
else if (result != _tempButton[_correctButton]){
NSLog (#"Incorrect");
}
}
-(NSMutableArray *)shuffleViews{
NSUInteger count = _tempViews.count;
int n;
for (int i=count-1; i>=0; --i) {
n = arc4random() % (i + 1);
[_tempViews exchangeObjectAtIndex:n withObjectAtIndex:i];
}
_correctButton = n;
return _tempViews;
}
-(void)displayonView{
NSMutableArray *tempArray;
tempArray = [self shuffleViews]; // shuffle views
_correctImage = [tempArray objectAtIndex:0];
_correctImage.contentMode = UIViewContentModeScaleAspectFit;
[_correctImage setImage:_myImage];
NSTimer* myTImer;
myTImer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(hideLabel) userInfo:nil repeats:NO];
}
-(void) hideLabel{
_correctImage.hidden = YES;
for (UIButton *each in self.tempButton) {
each.enabled = YES;
}
[self displayToFindSymbol];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
You could either have each button call a different method as the selector, or assign a different tag to each button and inspect it in a shared method.
Add all imageviews in an array and also all buttons in an array.
when setting image to random image view store its index and use the index later on to get the corresponding button that should have been clicked.
Pseudo code
NSArray a = [NSArray arrayWithObjects:imgVie1,ImgView2...,nil]
// create second array with buttons
int randomIndex = arc4random() % a.count;
UIImageView *imgView = [a objectAtIndex:randomIndex];
//set image and hide later
UIButton *correctButton = [secondarray objectAtIndex:randomIndex];
I have an iPhone application in which i need to load a bulk of images (ie around 50),which has a small rect like (little above thumbnail) containing 3 in each row with 4 columns in one page, and i need to scroll horizontally to load the next 12 images and so on. Also i need to show the page number under it as 1,2 etc.
Can any body guide me in the right direction to achieve this in a scroll view ?i am really in a mess ,how to add imageview to a scrollview like this ,also each image view has its own buttons also.
The way i would tackle this problem goes as follows: (I am not going to provide many details as they are dependent on your particular needs and requirements).
.h file:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIScrollViewDelegate>
#property (unsafe_unretained, nonatomic) IBOutlet UIScrollView *scrollView;//assuming the scrollView is connected in a xib file
-(id)initWithImages:(NSArray*)images;//that could be whatever format you get your images(UIImage, urls to download, file names or custom views. Here we assume that the array contains instances of UIImage)
#end
.m file:
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) NSArray *images;
#property (nonatomic, assign) CGFloat pageWidth;
#property (nonatomic, assign) int currentPage;
#end
#implementation ViewController
-(id)initWithImages:(NSArray*)images{
self = [super init];
if(self){
self.images = images;
}
return self;
}
-(void)viewDidLoad{
[super viewDidLoad];
[self.scrollView setDelegate:self];
[self.scrollView setContentSize:CGSizeMake(self.scrollView.frame.size.width*self.imageURLsArray.count,
self.scrollView.frame.size.height)];
[self.scrollView setPagingEnabled:YES];
[self.scrollView setShowsVerticalScrollIndicator:NO];
self.pageWidth = self.scrollView.frame.size.width;
for(int i = 0; i < self.images.count; i++){
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(self.scrollView.frame.size.width*i,
self.scrollView.frame.origin.y,
self.scrollView.frame.size.width,
self.scrollView.frame.size.height)];
imageView.image = [self.images objectAtIndex:i];
[self.scrollView addSubview:imageView];
}
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
int page = floor(scrollView.contentOffset.x - self.pageWidth/2)/self.pageWidth + 1;
if(self.currentPage != page){
NSLog(#"Scrolled to new page: %d", page);
self.currentPage = page;
//do additional things based on the fact that you have scrolled to a new page (like changing the page number)
}
}
#end
Use UItableview create custom cell with two imageviews on it and load that custom cell to cell for indexpath then create an nsarray and pass the image names into that array and then convert that image into data format for eg
nsdata *data = [NSdata dataWithcontents of url [array object at index:indexpath.row]];
cell.imageview.image = [uiimage imagewithdata:data];
for this you should know to create custom cells.
I got 30 of these codes, with the same implementation:
// .h
#interface ViewController : UIViewController{
IBOutlet UIImageView *circle;
IBOutlet UIImageView *circle2;
}
#property (nonatomic, retain) IBOutlet UIImageView *circle;
#property (nonatomic, retain) IBOutlet UIImageView *circle2;
// .m
#implementation ViewController
#synthesize circle;
#synthesize circle2;
- (void)viewDidLoad
{
circle = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"Circle.png"]];
circle2 = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"Circle.png"]];
}
And somewhere in my code, Im adding it as a subview.
My problem is,Is there a way to make it shorter, for it to be maintainable.
You can use one IBOutletCollection instead of 30 IBOutlets. You probably want to set the tag on each UIImageView though, so you can still tell them apart.
(This answer assumes you use a nib. Remove the lines where you instantiate the UIImageViews in viewDidLoad if so.)
If you use name like - Circle1.png, Circle2.png, then you can go for for loop for creating this in a loop.
Something like -
for (int i = 0; i < imageCount ; i++ ) {
circle = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:[NSString stringWithFormat: #"Circle%d.png" , i]]];
}
Is there a pattern to where you are putting these views in their superview? If so, you could use a for loop that goes to 30 and programmatically create the views and add them to their superview.
So for example:
for (i = 0; i < 100; i++)
{
UIImageView* circle = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"Circle.png"]];
[self.view addSubview:circle];
}
Would add 100 of the image views you would want. Of course you will need to adjust the positions of each of these views in the loop, but this is the general idea.
while creating this viewcontroller pass the frame as a parameter.thats the only thing changing rite??.the image is same and as there are no other properties .. it may work
Ok so I have been searching and have been unable to find an answers to this problem. (And I assume I can't find it because it is a very easy answer that everyone seems to know but me.) I am creating an app for IOS, where there is some opening animation and then I need the opening animation to stop and then different animation to take place instead. So I have the opening animation working fine and I have it stopping on the last frame. How do I get the new animation to start at the end of the opening animation? I am using UIImageView under the viewDidLoad() function. Here is my code for the ViewController.m file:
#implementation ViewController
#synthesize hook_drop_one;
#synthesize hook_swing_one;
- (void)viewDidLoad
{
[super viewDidLoad];
hook_drop_aone=[[NSMutableArray alloc] init];
for (int i=1; i<16; i++) {
NSString *hookpic=[NSString stringWithFormat: #"hook%d.png",i];
UIImage *img = [UIImage imageNamed:hookpic];
if (img) [hook_drop_aone addObject:img];
[hook_drop_one setAnimationImages:(hook_drop_aone)];
[hook_drop_one setAnimationDuration:0.9f];
[hook_drop_one setAnimationRepeatCount:1];
[hook_drop_one startAnimating];
}
hook_swing_aone=[[NSMutableArray alloc] init];
for (int i=1; i<230; i++) {
NSString *hookswingpic=[NSString stringWithFormat: #"hookswing%d.png",i];
UIImage *img = [UIImage imageNamed:hookswingpic];
if (img) [hook_swing_aone addObject:img];
[hook_swing_one setAnimationImages:(hook_swing_aone)];
[hook_swing_one setAnimationDuration:10.2f];
[hook_swing_one startAnimating];
}
}
My code fro the ViewController.h file:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController{
IBOutlet UIImageView *hook_drop_one;
NSMutableArray *hook_drop_aone;
IBOutlet UIImageView *hook_swing_one;
NSMutableArray *hook_swing_aone;
}
#property (nonatomic,retain)UIImageView *hook_drop_one;
#property (nonatomic,retain)NSMutableArray *hook_drop_aone;
#property (nonatomic,retain)UIImageView *hook_swing_one;
#property (nonatomic,retain)NSMutableArray *hook_swing_aone;
#end
Now I understand why both animations are running at the same time when the app loads. I need to figure out how to trigger one animation after the first one stops, or set a delay for the second animation.
Anyone got any ideas?
You can using
[CATransaction setCompletionBlock:^{ ... }]
please review session 421 WWDC 2011 - there is all info in second part of session.
Use i for determining the timming for your next animation , or you can start animation by touch event.
I have three images that I want to cycle through when clicking on a UIButton.
How would I go about doing this?
This is what I have so far, but it's not really working.
//the images
NSString* imageNames[] = {"MyFirstImage", "AnotherImage", whatever else};
int currentImageIndex = 0;
and
- (IBAction)change{
UIImage* imageToShow = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource: imageNames[currentImageIndex] ofType:#"png"];
if( currentImageIndex++ == sizeof(imageNames)/sizeof(NSString)) //check to see if you hit the last image
{
currentImageIndex = 0; //start over
}
}
Ideas?
Any help will be greatly appreciated! Thanks!
Steven's suggestion to subclass UIButton is a good one. Once you get a some more experience with Objective C, you should consider his approach, but I can tell by the code you've posted that you're new to Objective C, so you may need to learn to use the basic Foundation classes first.
One reason your code isn't working is because you're trying to pass C string literals to pathForResource:, which requires an NSString object. NSStrings are objects in Objective C, not character pointers as they are in C. You can construct an NSString object using the literal syntax, #"quotes-with-an-at-in-front".
Here is code that implements the algorithm you attempted to write, using Objective C Foundation classes rather than C data types:
// YourController.h
#interface YourController : UIViewController {
NSArray *imageNames;
NSInteger currentImageIndex;
UIButton *yourButton;
}
#property (nonatomic, retain) NSArray *imageNames;
#property (nonatomic, retain) IBOutlet UIButton *yourButton; // Presumably connected in IB
- (IBAction)change;
#end
// YourController.m
#import "YourController.h"
#implementation YourController
#synthesize imageNames, yourButton;
- (void)dealloc {
self.imageNames = nil;
self.yourButton = nil;
[super dealloc];
}
- (void)viewDidLoad {
self.imageNames = [NSArray arrayWithObjects:#"MyFirstImage", #"AnotherImage", nil];
currentImageIndex = 0;
[super viewDidLoad];
}
- (IBAction)change {
UIImage* imageToShow = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[imageNames objectAtIndex:currentImageIndex] ofType:#"png"];
currentImageIndex++;
if (currentImageIndex >= imageNames.count) {
currentImageIndex = 0;
}
[yourButton setImage:imageToShow forState:UIControlStateNormal];
}
#end
You will want to subclass UIButton and add a new property that maintains state. You will also want to have three properties to maintain the images of the three new states. Then in your "drawRect:" method, swap out the standard buttons images based on your state and then call the [super drawRect:] method.