iphone - getting UIImageView to repeatedly move - iphone

Background: I am using xcode 3.1.4 and iphone simulator 3.1 (I know it's outdated and please dont comment about that).
Goal: I am trying to get a UIImageView that is created once the view loads to continuously move down. Creating the UIImageView works fine, but the move function does not work. Nothing happens. I use an NSTimer. Here is my code in the view controller.m file:
-(void)viewDidLoad{
UIImageView *six = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"Meteor.png"]];
CGRect rectSix = CGRectMake(arc4random() % (250), arc4random() % (1), 35, 35);
[six setFrame:rectSix];
[self.view addSubview:six];
[self moveMeteor:six];
[NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:#selector(moveMeteor:) userInfo:six repeats:YES];
}
-(void)moveMeteor:(UIImageView *)t{
t.center=CGPointMake(t.center.x, t.center.y + 1);
}
And of course, I declared my moveMeteor function in the view controller.h file. By typing in:
-(void)moveMeteor:(UIImageView *)t;
Any ideas of what the problem is and a solution to it?

Or you could do something like this, which takes advantage of UIView's animateWithDuration and should look much better. No timer required.
// in your interface declaration...
#property (nonatomic, assign) BOOL meteorShouldAnimate;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
// in your implementation...
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.meteorShouldAnimate = YES;
[self moveMeteorWithAnimationOptions:UIViewAnimationOptionCurveEaseIn]; // ease in to the animation initially
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.meteorShouldAnimate = NO;
}
- (void)moveMeteorWithAnimationOptions: (UIViewAnimationOptions) options {
__weak MyViewController * weakSelf = self;
if (self.meteorShouldAnimate) {
[UIView animateWithDuration:0.2 delay:0.0 options:options animations:^{
self.imageView.transform = CGAffineTransformMakeTranslation(20.0, 20.0); // or whatever x and y values you choose
} completion:^(BOOL finished) {
MyViewController * strongSelf = weakSelf; // in case our view controller is destroyed before our completion handler is called
if (strongSelf) {
UIViewAnimationOptions nextOptions = strongSelf.meteorShouldAnimate ? UIViewAnimationOptionCurveLinear : UIViewAnimationOptionCurveEaseOut; // linear if we're continuing to animate, ease out if we're stopping
[strongSelf moveMeteorWithAnimationOptions:nextOptions];
}
}];
}
}

Your method is actually not getting the right parameter, you get NSTimer as a parameter. so instead
-(void)moveMeteor:(UIImageView *)t
the method should be like this
-(void)moveMeteor:(NSTimer *)timer
and you can't treat NSTimer as an UIImageView. :)
*Edit
I would suggest you to do something like
-(void)viewDidLoad{
UIImageView *six = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"Meteor.png"]];
CGRect rectSix = CGRectMake(arc4random() % (250), arc4random() % (250), 35, 35);
[six setFrame:rectSix];
[self.view addSubview:six];
[self moveMeteor:six];
[NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:#selector(moveMeteor:) userInfo:six repeats:YES];
}
and update your method to this
- (void)moveMeteor:(NSTimer *)timer {
UIImageView *six = timer.userInfo;
six.center=CGPointMake(six.center.x, six.center.y + 1);
}
just for information, I am passing the UIImageView in the dictionary as userInfo.

Related

Can you customize UISlider like the "unlock slider" in iPhone?

I have a question about UISliders in IOS and to what extent you can customize them?
I would like to implement a slider like the "Unlock slider" in iPhone.
But it seems like IOS have not provided any "standard" ways for implementing a slider like this?.
Is it possible to implement a standard UISlider and set it to a min.value (0.0) and maximum.value (0.5). If the slider "hits" a value greater then (0.01) it should automatically be pulled back to the min.value (0.0).
If it hits the maximum value (0.5), start an event then automatically pulled back to min.value?
All help is appreciated!
Try this. I use this in my Project
Slider.h
#class Slider;
#protocol SliderDelegate <NSObject>
#required
- (void) slideEnd;
#end
#interface Slider : UISlider
#property (nonatomic, weak) id<SliderDelegate> delegate;
Slider.m
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setMinimumTrackImage:YOUR_MINIMUM_TRACK_IMG forState:UIControlStateNormal];
[self setMaximumTrackImage:YOUR_MAXIMUM_TRACK_IMG forState:UIControlStateNormal];
[self setThumbImage:YOUR_THUMB_IMAGE];
self.minimumValue = 0.0;
self.maximumValue = 1.0;
self.value = 0.0;
[self addTarget:self action:#selector(moved:) forControlEvents:UIControlEventTouchUpInside];
[self addTarget:self action:#selector(moved:) forControlEvents:UIControlEventTouchUpOutside];
}
return self;
}
- (void) moved:(UISlider *) sender
{
if (self.value != 1.0) {
[self setValue: 0 animated: YES];
} else {
[[self delegate] slideEnd];
[self setValue: 0 animated: YES];
}
}
Implement it like this:
[self setSlider:[[Slider alloc] initWithFrame:CGRectMake(645, 25, 120, 50)]];
[[self view] addSubview:[self slider]];
[[self view] bringSubviewToFront:[self slider]];
[[self slider] setDelegate:self];
Don't forget to implement the delegate method:
- (void)slideEnd {
// Things you want to do when slide ends
}

Reference of UIImageview layer created in separate class

Defined resumeLayer and PauseLayer method within the #interface and #end block in h file.
#interface MainViewController : UIViewController
#property (nonatomic, retain) UIToolbar *toolbar;
#property (strong)AVAudioPlayer *audioPlayer;
#property (nonatomic, retain) NSTimer * timer;
- (void)resumeLayer:(CALayer *)layer;
- (void)pauseLayer:(CALayer *)layer;
#end
methods in m file
-(void)pauseLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;
}
-(void)resumeLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}
For calling resumeLayer and PauseLayer method in PlayPauseAction method
-(void)playpauseAction:(id)sender {
if([audioPlayer isPlaying])
{
[sender setImage:[UIImage imageNamed:#"Play Icon.png"] forState:UIControlStateSelected];
[audioPlayer pause];
[self pauseTimer];
[self pauseLayer:ImageView.layer]; // Pause the CALayer of the UIImageView
}else{
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
[self resumeTimer];
if(isFirstTime == YES){
self.timer = [NSTimer scheduledTimerWithTimeInterval:11.0
target:self
selector:#selector(displayviewsAction:)
userInfo:nil
repeats:NO];
isFirstTime = NO;
}
}
}
ImageView is defined in class named Third
- (void)viewDidLoad
{
// Displays UIImageView
UIImageView* ImageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 5, 300, 235)];
self.view.backgroundColor = [UIColor brownColor];
// load all the frames of our animation
ImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"3a.png"],
[UIImage imageNamed:#"3b.png"],
nil];
// all frames will execute in 24 seconds
ImageView.animationDuration = 24;
// start animating
[ImageView startAnimating];
ImageView.layer.borderWidth = 2;
ImageView.layer.borderColor = [[UIColor whiteColor]CGColor];
[ImageView.layer setMasksToBounds:YES];
[ImageView.layer setCornerRadius:15.0f];
[self.view addSubview:ImageView]; }
I want to get reference of this ImageView.layer in MainViewController class to use in
[self pauseLayer:ImageView.layer];
to pause imageview.layer animation
Now how can i get reference of this ImageView using
UIImageView *myImageView = [OtherClass getTheImageView];
to use following in playpauseAction to pause and resume Imageview layer animation
[self pauseLayer:myImageView.layer]; // Pause the CALayer of the UIImageView
Any one can help me with thisHow to reference ImageView.layer in MainviewController
Either you add a property to MainviewController and let ImageView set its value when it's ready, or you use NSNotificationCenter to send a notification from MainViewController to ImageView;
In ImageView:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(pauseMyLayer) name:kPauseLayerNotif object:nil];
In MainViewController:
[[NSNotificationCenter defaultCenter] postNotificationName:kPauseLayerNotif object:self];
The notification mechanism provides you a very loose coupling between the two classes and it is very easy to use.

How to create a new UIImageView with a different instance variable every time a timer is called

how are you guy's?
I want to make a new instance variable every time a timer is called for e.g.
numberofObjects += 1;
i = numberofObjects;
UIImageView *Object[i] = [[UIImageView alloc] initWithFrame:CGRectMake(randomx,0,36 ,36)];
UIImage *imag = [UIImage imageNamed:#"ball.png"];
[Object[i] setImage:imag];
[self.view addSubview:Object[i]];
Is there a way to do this?
Any comments will be appreciated.
This isn't too hard to do. I make the assumption that you are only going to have a maximum number of UIImageViews, as this can add a lot of overhead, and you may run into problems if it's allowed to continue forever. In the .h file,
#interface viewController : UIViewController {
int numberAdded;
NSTimer * timer;
UIImageView * currentImageView;
NSMutableArray * arrayOfImageViews;
}
- (void)addNewImageView;
#end
In the .m file:
#define MaxImageViews 20 // This is changeable!
#implementation viewController
- (void)viewDidLoad; {
[super viewDidLoad];
numberAdded = 0;
arrayOfImageViews = [[NSMutableArray alloc] init];
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(addNewImageView) userInfo:nil repeats:YES];
}
- (void)addNewImageView; {
if(numberAdded >= MaxImageViews){
[timer invalidate];
timer = nil;
return;
}
int randomX = arc4random() % 320; // Gives value from 0 - 319.
int randomY = arc4random() % 480; // Gives value from 0 - 479.
UIImageView * imageView = [[UIImageView alloc] initWithFrame:CGRectMake(randomX, randomY, 36, 36)];
imageView.image = [UIImage imageNamed:#"ball.png"];
[self.view addSubview:imageView];
[arrayOfImageViews addObject:imageView];
[currentImageView release];
currentImageView = imageView;
}
- (void)dealloc; {
[currentImageView release];
[arrayOfImageViews release];
[super dealloc];
}
#end
This should keep track of all of the imageViews in the array arrayOfImageViews, and you can access the i-th imageView by calling [arrayOfImageViews objectAtIndex:i]. The currentImageView pointer keeps track of the latest UIImageView added. Hope that helps!
Store the image views' pointers in an NSMutableArray object.

Splash screen related in iphone

Hi I am trying to splash screen with the help of timer. but it can't. IS any suggestion regarding this code.........
SplashViewController.h:-
#import <UIKit/UIKit.h>
#import "MainMenu.h"
#interface SplashViewController : UIViewController {
UIImage *imgSplash;
NSTimer *timer;
MainMenu *objMainMenuView;
}
#property (nonatomic,retain) NSTimer *timer;
#property (nonatomic,retain) UIImage *imgSplash;
#property (nonatomic,retain) MainMenu *objMainMenuView;
#end
SplashViewController.m:-
#import "SplashViewController.h"
#implementation SplashViewController
#synthesize timer,imgSplash,objMainMenuView;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
timer = [[NSTimer alloc] init];
UIImageView *splashImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,460)];
imgSplash = [[UIImage alloc] init];
imgSplash = [UIImage imageNamed:#"chicocredit_splash.png"];
[splashImageView setImage:imgSplash];
[self.view addSubview:splashImageView];
timer = [NSTimer timerWithTimeInterval:2.0 target:self.timer selector:#selector(fadeScreen) userInfo:nil repeats:NO];
if([timer isValid]==1)
{
[timer fire];
//self.view.alpha = 0.0;
objMainMenuView = [[MainMenu alloc] initWithNibName:#"MainMenu" bundle:nil];
[self.navigationController pushViewController:objMainMenuView animated:YES];
}
}
-(void) onTimer{
NSLog(#"LOAD");
}
- (void)fadeScreen
{
[UIImageView beginAnimations:nil context:nil];
[UIImageView setAnimationDuration:2.0];
[UIImageView setAnimationDelegate:self];
[UIImageView commitAnimations];
//[UIView setAnimationDidStopSelector:#selector(finishedFading)];
//self.view.alpha = 0.0;
//[UIView commitAnimations];
}
/*
- (void) finishedFading
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:5.0];
//self.view.alpha = 1.0;
//viewController.view.alpha = 1.0;
//self.objMainMenuView.view.alpha = 1.0;
[UIView commitAnimations];
//[splashImageView removeFromSuperview];
}*/
- (void)dealloc {
[super dealloc];
}
#end
Use this It may be solution for that.
- (void)viewDidLoad {
timer = [[NSTimer alloc] init];
CGRect myImageRect = CGRectMake(0.0f, 0.0f, 320.0f, 460.0f);
splashImageView = [[UIImageView alloc] initWithFrame:myImageRect];
[splashImageView setImage:[UIImage imageNamed:#"image3.jpg"]];
splashImageView.opaque = YES;
[self.view addSubview:splashImageView];
[splashImageView release];
[self performSelector:#selector(doTHis) withObject:nil afterDelay:2.0];
[super viewDidLoad];
}
-(void)doTHis{
objMainMenuView = [[MainMenu alloc] initWithNibName:#"MainMenu" bundle:nil];
[self.navigationController pushViewController:objMainMenuView animated:YES];
}
Good Luck
Looks like your MianMenu is getting pushed before you can see the fade effect. Its because you are firing the timer and pushing the Main Menu immediately.
// Schedule the timer here.
[NSTimer timerWithTimeInterval:2.0f target:self selector:#selector(timerFireMethod:) userInfo:nil repeats:NO];
// Timer fire method.
-(void) timerFireMethod:(NSTimer *) theTimer {
[UIView beginAnimations:nil context: nil];
[UIView setAnimationDuration:2.0f];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector: #selector(animationDidStop: finished: context:)];
// Put animation code.
[UIView commitAnimations];
}
// Called when animation finishes.
-(void) animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
// Called when animation finishes.
// Push the Main menu here.
}
Keep break point in the timer fire method. It should get called after 2 seconds as specified.
Then keep break point in the animationDidStopSelector method. It will get called after your fade animation of 2 seconds.
Your code is leaked:
1:
timer = [[NSTimer alloc] init]; //Leak here, remove this line
.
.
.
timer = [NSTimer timerWithTimeInterval:2.0 target:self.timer selector:#selector(fadeScreen) userInfo:nil repeats:NO];
2:
imgSplash = [[UIImage alloc] init];//Leak here, remove this line
imgSplash = [UIImage imageNamed:#"chicocredit_splash.png"];
3:
UIImageView *splashImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,460)];
...
[splashImageView setImage:imgSplash]; //Leak here, should release splashImageView
Why not, do everything else after timer expired and fading is done.
- (void) finishedFading
{
objMainMenuView = [[MainMenu alloc] initWithNibName:#"MainMenu" bundle:nil];
[self.navigationController pushViewController:objMainMenuView animated:YES];
}
short cut: use another viewController with imageView present it modally and dismiss with animation dissolve.
You should present view in viewWillAppear.Start timer on viewLoad of second viewController.When timer fires dismiss it.

UIImageView drifting on viewDidLoad

I am programmatically adding a UIImageView and a UILabel to multiple screens in a program I'm working on. As such, I've written a UIViewController that contains the code to load up the UIImageView and UILabel in viewDidLoad, along with a timer to update the contents. I use this view controller as a superclass for any views that need the UIImageView and UILabel.
For the most part it works fine, but when transitioning from specific screens the pair seem to start with a frame of (0,0,0,0) and slowly animate to the frame I've defined. I have no idea what the issue is or even where to look. Any pointers here would be great.
Here is the code I'm using as my superclass.
FoundationViewController.h
#import
#interface FoundationViewController : UIViewController {
IBOutlet UIImageView *activeInventoryImage;
IBOutlet UILabel *activeInventoryLabel;
NSTimer *inventoryStatusTimer;
}
#property (nonatomic, retain) IBOutlet UIImageView *activeInventoryImage;
#property (nonatomic, retain) IBOutlet UILabel *activeInventoryLabel;
- (void) advanceToView:(id)nextView;
- (void) inventoryStatus;
- (BOOL) inventoryActive:(NSDate*)inventoryExpire withImage:(NSString*)imageName;
#end
FoundationViewController.m
#import "FoundationViewController.h"
#import "GameData.h"
#import "Globals.h"
#implementation FoundationViewController
#synthesize activeInventoryImage;
#synthesize activeInventoryLabel;
- (void) viewDidLoad{
// initialize the active inventory icon and label
activeInventoryImage = [[UIImageView alloc] init];
activeInventoryLabel = [[UILabel alloc] init];
// clear
activeInventoryImage.image = [UIImage imageNamed:#""];
activeInventoryLabel.text = #"";
// set the center points
activeInventoryImage.frame = CGRectMake(258, 7, 20, 20);
activeInventoryLabel.frame = CGRectMake(280, 6, 30, 20);
// set label parameters
activeInventoryLabel.backgroundColor = [UIColor clearColor];
activeInventoryLabel.font = [UIFont fontWithName:#"Helvetica" size:11.0f];
activeInventoryLabel.textColor = [UIColor colorWithRed:0.2 green:0.4 blue:0.6 alpha:1];
// add to view
[self.view addSubview:activeInventoryImage];
[self.view addSubview:activeInventoryLabel];
// start the timer if there is any active inventory
if(
[self inventoryActive:[GameData sharedGameData].player.inventory.aExpire withImage:#"a.png"] ||
[self inventoryActive:[GameData sharedGameData].player.inventory.bExpire withImage:#"b.png"] ||
[self inventoryActive:[GameData sharedGameData].player.inventory.cExpire withImage:#"c.png"]
)
inventoryStatusTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(inventoryStatus) userInfo:nil repeats:YES];
[super viewDidLoad];
}
- (BOOL) inventoryActive:(NSDate*)inventoryExpire withImage:(NSString*)imageName{
NSTimeInterval expireSeconds;
NSDateFormatter *formatter;
BOOL runTimer = FALSE;
// expire
expireSeconds = [inventoryExpire timeIntervalSinceNow];
if(expireSeconds > 0){
formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"mm:ss"];
NSDate *expireTime = [NSDate dateWithTimeIntervalSince1970:expireSeconds];
activeInventoryImage.image = [UIImage imageNamed:imageName];
activeInventoryLabel.text = [formatter stringFromDate:expireTime];
[formatter release];
runTimer = TRUE;
}
return runTimer;
}
- (void) inventoryStatus{
// if there is no active inventory kill the timer
if(
![self inventoryActive:[GameData sharedGameData].player.inventory.aExpire withImage:#"a.png"] &&
![self inventoryActive:[GameData sharedGameData].player.inventory.bExpire withImage:#"b.png"] &&
![self inventoryActive:[GameData sharedGameData].player.inventory.cExpire withImage:#"c.png"]
){
activeInventoryImage.image = [UIImage imageNamed:#""];
activeInventoryLabel.text = #"";
if(inventoryStatusTimer != nil)
[inventoryStatusTimer invalidate];
}
}
- (void) advanceToView:(id)nextView{
if([nextView isKindOfClass:[UIView class]]){
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:2.7];
[UIView setAnimationTransition:UIViewAnimationTransitionNone forView:self.view cache:YES];
[self.view addSubview:nextView];
[UIView commitAnimations];
}
else
NSLog(#" Error Loading View: %#",nextView);
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[activeInventoryImage removeFromSuperview];
[activeInventoryImage release];
[activeInventoryLabel release];
[super dealloc];
}
#end
Put a break point in advanceToView as this seems to be your only animation code. Everytime it gets called, look at the call stack in the debugger. From here, you can see what is calling this code when they are not supposed to be.
After some experimenting I've discovered using initWithFrame corrects the drifting problem.
activeInventoryImage = [[UIImageView alloc] initWithFrame:CGRectMake(258, 7, 20, 20)];
activeInventoryLabel = [[UILabel alloc] initWithFrame:CGRectMake(280, 6, 30, 20)];
I still have no idea what the root cause of the issue is. If anyone could tell me what's going on here I would love to know for future reference.