I have a label that I want to update with the number of seconds that the user has left to complete a certain task. I decided to use an NSTimer which ticks every second, and calls the function updateTime(), which will decrement the property containing the # of seconds left, and then update the label. However, the label is not being updated. I get no errors, nor output. Anything I try to change with the label within updateTime() does not work: mylabel.text, mylabel.frame, mylabel.font, etc... Anywhere else though, I'm able to modify the label normally. Here is my code:
// ViewController.h
#interface ViewController : UIViewController
{
NSTimer* timer;
int secs;
UILabel* timerText;
}
#end
// ViewController.m
- (void)updateTime
{
secs--;
timerText = (UILabel*)[self.view viewWithTag:4]; // i have also tried putting this line in viewDidLoad. i also tried removing the property in the .h file and just doing UILabel* timerText = ....
NSString* updatedTime = [NSString stringWithFormat:#"%d", secs];
timerText.text = updatedTime;
}
- (IBAction)startButton_pressed:(id)sender {
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(updateTime)
userInfo:nil
repeats:YES];
}
EDIT: I am getting a "-[UIView setText:]: unrecognized selector sent to instance" error now. NSLog(#"%#", timerText) outputs ">" so it is not null. Under this, I get "-[UIView setText:]: unrecognized selector sent to instance 0x9767b60
" What is going on? What should I do about this? I tested similar code on a fresh project and it worked, no idea what's going on here. Could having two view controllers in my project possibly be causing this?
Thanks for all your replies everyone. I fixed it by creating a second ViewController class and putting all the initializations in its viewDidLoad.
Related
I have code that flashes the border of a cell in a collection view by changing its color at set intervals. When the flash sequence begins, the original color of the cell is saved, so that when the flash sequence is complete, the color can be restored. The crash that occurs doesn't explain exactly what is wrong, so I'm left trying to deduce the problem, and what I'm seeing in the debugger isn't making much sense.
Note that this is code that in the past has been tested to work without crashing, not sure why it's suddenly failing now.
The error: Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1831e1fd4) (The line appears in red and execution will not continue, so no this is not just stopping at a breakpoint, it is a crash.)
The code...
#interface OrderCollectionViewCell : UICollectionViewCell
. . .
#property (strong, nonatomic) NSTimer *borderTimer;
#property (nonatomic) BOOL blinkStatus;
#property (nonatomic) NSInteger blinkTimes;
. . .
#implementation OrderCollectionViewCell
{
CGColorRef normalBorder;
}
-(void)flashBorder
{
// Save original color for later restore
normalBorder = self.bg.layer.borderColor;
if(self.borderTimer) {
[self.borderTimer invalidate];
}
self.borderTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(blink) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:self.borderTimer forMode:NSRunLoopCommonModes];
self.blinkTimes = 0;
self.blinkStatus = NO;
}
-(void)blink
{
if (self.blinkTimes++ == 3)
{
// Sequence complete. Restore original color
self.bg.layer.borderColor = normalBorder; // <-- This line crashes
[self.borderTimer invalidate];
self.borderTimer = nil;
return;
}
if(self.blinkStatus == NO){
self.bg.layer.borderColor = [UIColor whiteColor].CGColor;
self.blinkStatus = YES;
}else {
self.bg.layer.borderColor = [UIColor orangeColor].CGColor;
self.blinkStatus = NO;
}
}
Here's where things get weird. According to the docs, CGColorRef is a struct, not an object. I set a breakpoint in flashBorder, and check the value of self.bg.layer.borderColor and variable normalBorder after copying the color to it.
Note that the address of each is reported as <CGColor 0x281b6d200>, which is more like object behavior than struct behavior.
When the time comes to restore the color, the variable normalBorder no longer appears to contain valid color data, as it's simply reported as an address (the same address as before) but no descriptive output:
Does anyone know what might be causing this failure, or why in the debugger the CGColorRef seems to be acting like an object rather than a struct?
As you have guessed, "normalColor" is no longer a valid reference by the time you access it. I think there is either an error in the docs or a miscommunication as CGColorRef is actually derived from CFTypeRef and not a struct. I recommend you save the color in a property as a UIColor object. This will solve your issue.
I'm new in xcode and objective-c and trying to developing an app. I would like to set up a timer in some of pages for calculating how much time user spend in that page. In the app, I have 5 theme pages, each pages contains a table view to another 3 sub-pages. I would like to add a counter to these 3 pages (5*3) but not including theme pages themselves. The page shift is controlled by navigation bar. I have put some codes as follows in .m file of viewcontroller.
- (void)viewDidLoad
{
[super viewDidLoad];
//timer
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self
selector:#selector(handleTimer)
userInfo:nil
repeats:YES];
}
-(void)handleTimer
{
MainInt += 1;
self.TimeLabel.text = [NSString stringWithFormat:#"%d",MainInt];
}
and some code in .h file (Brett is one of the 3 sub-pages.)
#interface Brett : UIviewController
{
NSTimer *timer;
int MainInt;
}
# property (weak, nonatomic) IBOutlet UILable *TimLable;
Every time when I leave the page and go back again the counter is always count from 0. Anyone can help to solve this problem??
Every time it Count start form 0, I guess because of you are creating Brett object every time when you push it to navigation.
Create Global Timer in appDelegate class and use it,
in viewWillAppear start timer and in viewWillDisappear pause that timer.
Alternative to the other answer, you can just make the MainInt a static variable
static int MainInt;
What I understood from your question is to simply keep track of the amount of time a user spend in sub pages. If my understanding is correct, then you may try following.
Create and start timer as like now you are doing.
On viewWillDisAppear method of your controller, just update the global variable or NSUserDefaults value like this:
//Get the previous time available in userdefaults
int counter = [[NSUserDefaults standardUserDefaults] integerForKey:#"ScreenACounter"];
//Update the key with existing counter value + current timer value.
[[NSUserDefaults standardUserDefaults] setInteger:counter + currentTimer.Value forKey:#"HighScore"];
Hope this helps.
I can't figure out what is wrong in code pasted below, im learing xcode with Todd Moore book, this is the chapter 2-hello pong, Im getting breakpoint 1.1 crash at scheduledTimerWithTimeInterval. In book at the end of timer configuration is added ] retain]; but xcode 5 says that's deperecated.I modificate this to compile without retain, but the problem is crash.
- (void)animate
{
_puck.center = CGPointMake(_puck.center.x + dx*speed,_puck.center.y + dy*speed);
}
- (void)start
{
if (timer == nil) {
timer = [NSTimer scheduledTimerWithTimeInterval:0.016 target:self selector:#selector(animate) userInfo:NULL repeats:YES];
}
_puck.hidden = NO;
}
Because you are in an ARC setting, automatic reference counting, the object that is doing the animate/start may not be in memory anymore depending on how the rest of the code worked.
If whatever object that is used to have a retain it may not be in memory when that timer gets called.
You may need to do a quick search for how to start a project without automatic reference counting so you can follow the examples in the book more directly.
someObject = [[something alloc] init] retain];
[someObject start];
If you are not storing someObject somewhere that is likely the problem.
[edit]
I found the source code for that Todd Moore example.
These changes should hopefully let it work with ARC.
get rid of this in PaddlesViewController.h
NSTimer *timer;
add (near other #properties)
#property (nonatomic, retain) NSTimer *timer;
in PaddlesViewController.m add (near other #synthesize)
#synthesize timer;
This should allow it to run without the retain
I'm trying to start a NSTimer in my UIView class called "ClockView" with a method as selector that manipulates an initial float which was declared in the ViewController "ClockViewController".
My ClockViewController declares int timerIntWhite as an integer (for example 500). My ClockView needs this Value for the - (void)start method which runs a method called - (void)updateWhiteClock every second:
- (void)start {
timerIntWhite = PLEASE HELP ME AT THIS POINT!;
randomTimerWhite = [NSTimer scheduledTimerWithTimeInterval:(1.0/1.0)target:self selector:#selector(updateWhiteClock) userInfo:nil repeats:YES];
}
Is it possible to access the integer of ClockViewController in ClockView?
Try the following:
In your ClockView also declare the variable (property) int timerIntWhite and set this variable from your View Controller after the View gets created, for example, in viewDidLoad.
-(void)viewDidLoad {
[super viewDidLoad];
self.view.timerIntWhite = self.timerIntWhite;
}
After doing this, ClockView can access it's own timerIntWhite variable:
- (void)start {
timerIntWhite = self.timerIntWhite;
randomTimerWhite = [NSTimer scheduledTimerWithTimeInterval:(1.0/1.0)target:self selector:#selector(updateWhiteClock) userInfo:nil repeats:YES];
}
I'm assuming that your ClockViewController class knows that its view IS-A ClockView. This is very important! Otherwise you'll get a warning.
I also want to mention that according to the MVC rules it's a better idea if your ClockViewController class takes care of the NSTimer. Views should be used to display information to the user only.
Hope this helps!
Is there any method for slide show of an array of strings in UILabel in iphone app?(ie, strings will appear one by one). Anyone please help me.
Look at NSTimer.
This can get you a repeated callback every X seconds. You can use this to swap the strings in an array.
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(swapStrings:) userInfo:nil repeats:YES];
_myStrings = #[ #"a" , #"b", ..... ];
...
- (void) swapStirings:(id)sender
{
myInt ++;
if (myInt >= [_myStrings count]) myInt = 0;
myLabel.text = [_myStrings objectAtIndex:myInt];
}
No, there is not. But, the good news it should be trivial to implement. I suggest creating a subclass of uilabel that has an array of strings as an ivar. The subclass has an init method that sets the array and a time interval. Then it uses an nstimer to change its label and redisplay itself. Good luck!