Goal is to enumerate every character in the String. That is 'w' will appear then after 1 sec will be replaced by 'h' then 'e' then 'n'.
Problem my label only shows the last letter.
What i did:
1. drag a label and a button on the PlayViewController.
2. create the property for Label
3. create action for button
In my PlayViewController.h:
#import <UIKit/UIKit.h>
#interface PlayViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *listChar;
- (IBAction)startGame:(id)sender;
#end
In my PlayViewController.m:
#import "PlayViewController.h"
#interface PlayViewController ()
#end
#implementation PlayViewController
NSString *word;
NSTimer *myTimer;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.listChar.text = #" ";
word = #"when";
}
- (IBAction)startGame:(id)sender {
myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(listLetter:) userInfo:nil repeats:YES];
}
-(void) listLetter:(NSTimer*) myTimer {
for(int i=0; i<[word length]; i++){
unichar letter = [word characterAtIndex: i];
self.listChar.text = [NSString stringWithFormat:#"%C", letter];
}
}
#end
If you want to know about why this happning then refer #Nitin's answer, and if you want to solve in other way then just use following code
-(void) listLetter:(NSTimer*) myTimer
static int pos = 1;
self.listChar.text = [word substringToIndex:pos];
if (++pos > word.length) {
[myTimer invalidate];
}
}
Related
I'm using Objective-C to make a stopwatch. I already have a basic stop watch with 3 buttons: Start, Stop and reset. Here is my code for viewcontroller.m:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
-(IBAction)Start:(id)start
{
Timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(addingthetime) userInfo:nil repeats:YES];
}
-(IBAction)Stop:(id)sender
{
[Timer invalidate];
}
-(IBAction)Restart:(id)sender
{
[Timer invalidate];
addingtheTime = 0;
Label.text = [NSString stringWithFormat:#"0.00"];
}
-(void)addingthetime
{
addingtheTime = addingtheTime + 0.01;
Label.text = [NSString stringWithFormat:#"%.2f", addingtheTime];
}
#end
And here is my code for viewcontroller.h:
#import <UIKit/UIKit.h>
float addingtheTime;
#interface ViewController : UIViewController
{
IBOutlet UILabel *Label;
NSTimer *Timer;
}
#end
So my question is how do I make the Start button do the following once clicked:
Start the timer
Change the title to stop
(Click the same button again)
Stop the timer
Change the title to start
So the aim is to have only one button which starts and stops the timer but please I want the title to change as well.
Don't worry about the reset button as I want that to remain by itself.
PS. Please explain things clearly because I find it really hard to understand some things and I am a beginner so try and keep it fairly simple thanks, and sorry if the question isn't clear.
You can use button.tag property to achieve this. By Default the button.tag property have 0. So assume that 0 is a state when timer is Not started and 1 is the state when timer is started. You can manipulate .tag property according to your custom logic.
-(IBAction)Start:(id)start
{
UIButton *button = (UIButton *)start;
if (button.tag == 0){
button.tag = 1;
[button setTitle:#"Stop" forControlState:UIControlStateNormal];
Timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(addingthetime) userInfo:nil repeats:YES];
}else {
button.tag = 0;
[button setTitle:#"Stop" forControlState:UIControlStateNormal];
//Invoke your method to stop Timer.
}
}
In the ViewController.h:
#import <UIKit/UIKit.h>
float addingtheTime;
#interface ViewController : UIViewController
{
IBOutlet UILabel *Label;
NSTimer *Timer;
}
#end
In the ViewController.m:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)addingthetime
{
addingtheTime = addingtheTime + 0.01;
Label.text = [NSString stringWithFormat:#"%.2f", addingtheTime];
}
- (IBAction)startOrStopAction:(UIButton *)sender {
// stop
if ([sender.titleLabel.text isEqualToString:#"stop"]) {
[Timer setFireDate:[NSDate distantFuture]];
[sender setTitle:#"start" forState:UIControlStateNormal];
}
// start
else {
if (!Timer) {
Timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(addingthetime) userInfo:nil repeats:YES];
}else {
[Timer setFireDate:[NSDate date]];
}
[sender setTitle:#"stop" forState:UIControlStateNormal];
}
}
#end
The result:
In iPhone:
In iPad:
I'm trying to display the yaw pitch and roll of the device in a label. I cannot seem to get the values to display, it only shows a '...' where the numbers should be. This is my code, any help is greatly appreciated.
#import "ViewController.h"
#import <CoreMotion/CoreMotion.h>
#interface ViewController (){
}
#property (strong, nonatomic) CMMotionManager *motionManager;
#end
#implementation ViewController
#synthesize motionManager;
#synthesize roll;
#synthesize pitch;
#synthesize yaw;
#synthesize xLabel;
#synthesize yLabel;
#synthesize zLabel;
- (void)viewDidLoad {
[super viewDidLoad];
/** Do any additional setup after loading the view, typically from a nib.
UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];
accelerometer.updateInterval = 1.0f/60.0f;
accelerometer.delegate = self;
**/
//motionManager = [[CMMotionManager alloc] init];
//motionManager.deviceMotionUpdateInterval = 1.0 / 60.0;
motionManager = [[CMMotionManager alloc] init];
NSTimer *timer;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:#selector(doGyroUpdate) userInfo:nil repeats:YES];
//CMDeviceMotion *deviceMotion = motionManager.deviceMotion;
//CMAttitude *attitude = deviceMotion.attitude;
[motionManager startDeviceMotionUpdates];
}
-(void)doGyroUpdate
{
double x = motionManager.deviceMotion.attitude.roll*180/M_PI;
double y = motionManager.deviceMotion.attitude.pitch*180/M_PI;
double z = motionManager.deviceMotion.attitude.yaw*180/M_PI;
NSString *myString = [NSString stringWithFormat:#"%g", x];
xLabel.text = myString;
myString = [NSString stringWithFormat:#"%f", y];
yLabel.text = myString;
myString = [NSString stringWithFormat:#"%f", z];
zLabel.text = myString;
}
... indicates the UILabel you're using for displaying the text is not as wide as it should be.
Try and make it wider in your storyboard or xib file.
Try -
label.numberOfLines = 1;
label.minimumFontSize = 6;
label.adjustsFontSizeToFitWidth = YES;
Or you can try it by storyboard (Autoshrink option) -
You can use Autolayout for this. Here I have given 2 constraint
1. top from superView
2. leading from superview
Now whatever is your text it will display without .... .
Right now here is the code I'm using. It only updates when the button is pressed and is the average rather than instantaneous.
-(IBAction)button:(id)sender {
[self incrementTapCount];
NSMutableString *aString = [NSMutableString stringWithFormat:#"%.2f", averageTapsPerSecond];
[aString appendFormat:#"%s", " per second"];
current.text = aString;
}
- (void)incrementTapCount
{
tapCountInPastSecond++;
}
- (void)timerActions
{
secondsElapsed = secondsElapsed + .1;
averageTapsPerSecond = (averageTapsPerSecond*(secondsElapsed-.1) +tapCountInPastSecond) / secondsElapsed ;
tapCountInPastSecond = 0;
}
On the view did load...
[NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:#selector(timerActions) userInfo:Nil repeats:YES];
I'm trying to get it to update without pressing the button, and not be the average speed, rather the speed at that moment.
Your timer fires every .1 second and you want to keep a "sliding" total of the taps in the last second. I would suggest an array of 10 integers. Each time the timer ticks you can add the most recent tap count to the end of the array and subtract the oldest.
#property (assign) NSInteger runningTotal;
#property (assign) NSInteger tapsInLastSample;
#property (strong,nonatomic) NSMutableArray *tapHistory;
-(void) viewDidLoad {
[super viewDidLoad];
self.runningTotal=0;
self.tapHistory=[NSMutableArray arrayWithCapacity:11];
[NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:#selector(timerActions) userInfo:Nil repeats:YES];
}
-(IBAction)button:(id)sender {
self.tapsInLastSample++;
}
- (void)timerActions {
self.runningTotal+=self.tapsInLastSample;
[self.tapHistory addObject:[NSNumber numberWithInteger:self.tapsInLastSample]];
if (self.tapHistory.count >10) {
self.runningTotal-=[self.tapHistory[0] integerValue];
[self.tapHistory removeObjectAtIndex:0];
}
current.text=[NSString stringWithFormat:#"Taps in last second=%ld",(long)self.runningTotal];
self.tapsInLastSample=0;
}
If the user keeps clicking on button1 one or two , progress2.progress keeps increasing/decreasing on each click and progress1.progress keeps the same value until the user stops clicking. And in case he will surely lose , if he also keeps clicking nothing happens until he stops clicking. I don't want it to be that way since I want to hide/disable the buttons as soon as it's confirmed that he's losing to fix this issue. Any way to fix that?
Here is my .m :
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (BOOL)prefersStatusBarHidden { return YES; }
- (void)viewDidLoad
{
progress1.progress=arc4random() % 11 * 0.1;
count1=0;
count2=0;
label1.hidden = NO;
gameOver.hidden = YES;
score=0;
[super viewDidLoad];
;
}
// Do any additional setup after loading the view, typically from a nib.
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)regulator{
if(timer1)
{
[timer1 invalidate];
timer1 = nil;
}
if(timer4)
{
[timer4 invalidate];
timer4 = nil;
}
timer4 =[NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:#selector(conditioner) userInfo:nil repeats:YES];
;}
-(void)conditioner {
if (fabs(progress2.progress-progress1.progress)<=0.25 )
{
score=score+1;
scorenumber.text= [NSString stringWithFormat:#"%i",score];
[self newGame];
;
} else{
stop1=YES;
stop2=YES;
gameOver.hidden=NO;
stick.hidden=YES;
bg.hidden=YES;
progress1.hidden=YES;
progress2.hidden=YES;
supply.hidden=YES;
demand.hidden=YES;
}}
-(void)newGame{
progress1.progress=arc4random() % 11 * 0.1;}
- (IBAction)start:(UIButton *)sender {
progress2.progress=arc4random() % 11 * 0.1;
if(timer4)
{
[timer4 invalidate];
timer4 = nil;
timer1 = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(regulator) userInfo:nil repeats:YES];
[self regulator];
stop1=NO;
stop2=NO;
label1.hidden=YES;
UIButton *button1 = (UIButton *)sender;
button1.enabled = NO;
UIButton *button2 = (UIButton *)sender;
button2.enabled = NO;
}
- (IBAction)button1:(UIButton *)sender {
if(stop1==YES){button12.hidden = TRUE;}
progress2.progress=progress2.progress-0.05;
;
[self regulator];
count2=0;
count1 = count1 +1;
}
- (IBAction)button2:(UIButton *)sender {
[self regulator];
progress2.progress=progress2.progress+0.05;
if(stop2==YES){button22.hidden = TRUE;}
count1 =0;
count2 = count2+1;
}
#end
and my .h:
#import <UIKit/UIKit.h>
int count1;
int count2;
int score;
void *regulator;
void *newGame;
void *conditioner;
BOOL stop1;
BOOL stop2;
void *firstLaunch;
#interface ViewController : UIViewController{
IBOutlet UILabel *scorenumber;
IBOutlet UIImageView *stick;
IBOutlet UILabel *label1;
IBOutlet UIImageView *bg;
IBOutlet UILabel *supply;
IBOutlet UILabel *demand;
IBOutlet UILabel *gameOver;
IBOutlet UIProgressView *progress1;
IBOutlet UIProgressView *progress2;
IBOutlet UIButton *button12;
IBOutlet UIButton *button22;
NSTimer *timer1;
NSTimer *timer2;
NSTimer *timer3;
NSTimer *timer4;
}
- (IBAction)button1:(UIButton *)sender;
- (IBAction)button2:(UIButton *)sender;
#end
Thanks a lot for any help or information. I edited my question with the full code to give further explanation about the issue I'm facing. Regards.
This is actually a coding issue. MVC basics.
I believe you miss some understanding of things. So I'll explain:
IBAction - It's an action sent from the view to the controller.
IBOutlet - Meant for the controller to control the view.
On your code you are getting the sender (which should be read only when coding right) and you are trying to set it up. I assume you need to define a new IBOutlet to represent the button then connect it on your storyboard and then inside this function to make it enable/disabled.
Also a good practice would be to use "TRUE" and "FALSE" and not "YES/NO".
Hope this helps.
There are couple of ways you can approach this to make sure when user touches the button then it doesn't do anything.
It wasn't clear from your question so I assume on touch down of button you call (IBAction)button1. So Try
- (IBAction)button1:(UIButton *)sender
{
if(stop1==YES)
{
//game has stopped so don't do anything
}
else
{
progress2.progress=progress2.progress-0.05;
[self regulator];
}
}
If you want to hide it so that the user can't do anything try this
- (IBAction)button1:(UIButton *)sender
{
if(stop1==YES)
{
//game has stopped so hide this button
//assuming you have connected an IBOutlet to your button1
button1.hidden = YES;
}
else
{
button1.hidden = NO;
progress2.progress=progress2.progress-0.05;
[self regulator];
}
}
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.
}
Use tags instead, set a unique tag to both of the buttons, and set the tag of image to the button that the image will belong, later on, compare the tag of both image and the button to check if they are the same or not.
https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/UIView/UIView.html#//apple_ref/occ/instp/UIView/tag
I'm kinda new to objective-c and iOS aswell, but i don't think you should compare like this:
result == _tempButton[_correctButton]
try this comparison instead:
[result isEqual:_tempButton[_correctButton]]