I have been having this issue from last couple of hours and did all the search that i could but unfortunately, i didnt find anything that resolves my issue....
Scenario: i have a CountDownTimer in TimerViewController, NSTimer and other methods are set up in AppDelegate which is suppose to update TimerViewController's Label... as per label's setter, i'm getting the value correctly and its showing in the NSLog HOWEVER, the label is not updating on the screen... this setter is being called from AppDelegate every second and the Label is suppose to show the Timer,
- (void)setMainTimerLabel:(UILabel *)mainTimerLabel
{
_mainTimerLabel = mainTimerLabel;
NSLog(#"ValueUpdated %#",_mainTimerLabel);
}
I have double checked the label, it hooked up with interface correctly, i tried to update the label from ViewDidLoad with test String, the label was showing me the string...
Help please!
EDIT:
AppDelegate Code:
AppDelegate.h
#property (nonatomic, strong) TimerViewController *TimerVC;
- (void)fireTimer;
AppDelegate.m
- (void)fireTimer
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(countDownTimer) userInfo:nil repeats:YES];
}
- (void) countDownTimer
{
.......
TimerVC = [[TimerViewController alloc]init];
self.TimerVC.mainTimerLabel = [NSString stringWithFormat:#"%02d:%02d:%02d",hours,minutes,seconds];
.......
}
I resolved this issue following the below code by jabobadilla
I actually solved it by performing a method that will go and retrieve the value that the NSTimer is updating in my AppDelegate, since the method firing the NSTimer is no longer in the main thread when I leave the view and come back to it. This method will loop as long as my NSTimer is valid. I also placed a delay, allowing for the UI to update the value, and then perform the method again. Here is the code in case it helps someone running into a similar issue. I got this idea from the suggestion provided by chandan, thanks!!
AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate> {
}
#property (nonatomic, retain) NSTimer *countdownTimer;
#property (nonatomic, retain) NSString *timeString;
CountdownTimerViewController.h
#interface CountdownTimerViewController : UIViewController {
AppDelegate *appdelegate;
}
#property (strong, nonatomic) IBOutlet UILabel *labelCountdownTimer;
#property (strong, nonatomic) IBOutlet UIButton *buttonStartTimer;
#property (strong, nonatomic) IBOutlet UIButton *buttonStopTimer;
- (IBAction)startTimer:(id)sender;
- (IBAction)stopTimer:(id)sender;
CountdownTimerViewController.m
#implementation CountdownTimerViewController
#synthesize labelCountdownTimer;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//Instatiating Appdelegate
if(!appdelegate)
appdelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
}
- (void) viewDidAppear:(BOOL)animated {
if ([appdelegate.countdownTimer isValid]) {
[self updateLabel];
} else {
labelCountdownTimer.text = #"00:00:00";
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Button Action Methods
- (IBAction)startTimer:(id)sender {
[self updateCounter];
}
- (IBAction)stopTimer:(id)sender {
[appdelegate.countdownTimer invalidate];
labelCountdownTimer.text = #"00:00:00";
}
int countLimit=30; //seconds
NSDate *startDate;
- (void)updateCounter {
labelCountdownTimer.text = #"00:00:00";
startDate = [NSDate date];
appdelegate.countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0
target:self
selector:#selector(countDown)
userInfo:nil
repeats:YES];
}
- (void)countDown {
if([[NSDate date] timeIntervalSinceDate:startDate] >= countLimit) {
[appdelegate.countdownTimer invalidate];
return;
}
else {
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = -([currentDate timeIntervalSinceDate:startDate]);
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
appdelegate.timeString = [dateFormatter stringFromDate:timerDate];
labelCountdownTimer.text = appdelegate.timeString;
}
}
- (void) updateLabel {
if ([appdelegate.countdownTimer isValid]) {
labelCountdownTimer.text = appdelegate.timeString;
[self performSelector:#selector(updateLabel) withObject:nil afterDelay:0.05];
}
}
There may be problem in your IBOutlet....
Try to create a programatic UILabel and pass the _mainTimerLabel value to that label....
This may help you..
Related
I'm new to developing iOS apps and English is not my native language, so please excuse any mistakes and my ugly code.
The app I'm trying to create should just display one specific image at one specific day (and change the image if the date changes).
Therefore I implemented an infinite loop in which the date is checked. If it differs from the one the image was changed the last time, the image changes again. The images are named in a "YearMonthDay.png"-scheme (e.g. "20131017.png").
I already googled a lot and got some code together (I know it's pretty ugly), but it crashes everytime.
I would really appreciate any help!
smViewController.h:
#import <UIKit/UIKit.h>
#interface smViewController : UIViewController {
UIImageView* mImageView;
}
#property (nonatomic, retain) IBOutlet UIImageView* imageView;
- (IBAction)contentModeChanged:(UISegmentedControl*)segmentedControl;
#end
smViewController.m
#import "smViewController.h"
#interface smViewController ()
#end
#implementation smViewController
#synthesize imageView = mImageView;
- (void)viewDidUnload
{
self.imageView = nil;
[super viewDidUnload];
}
- (void)dealloc
{
[mImageView release];
[super dealloc];
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *oldDateString = #"";
while(true)
{
NSDate *today = [NSDate date];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyy/MM/dd"];
NSString *dateString = [dateFormat stringFromDate:today];
NSLog(#"date: %#", dateString);
if([dateString isEqualToString: oldDateString])
{
}
else
{
NSAssert(self.imageView, #"self.imageView is nil. Check your IBOutlet connections");
UIImage* image = [UIImage imageNamed:dateString];
NSAssert(image, #"image is nil. Check that you added the image to your bundle and that the filename above matches the name of you image.");
self.imageView.backgroundColor = [UIColor whiteColor];
self.imageView.clipsToBounds = YES;
self.imageView.image = image;
oldDateString = dateString;
}
[dateFormat release];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You should override - (void)applicationSignificantTimeChange:(UIApplication *)application in your apps UIApplicationDelegate. Then you will receive a event when date changes and you can remove any loop or timer.
Is probably because of the while loop. It's blocking your app.
You should use timers instead, something like this:
NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(checkDate) userInfo:nil repeats:YES];
[timer fire];
Where you want to check for a new date every 1 seconds (you probably would be fine with higher frequency) and checkDate is the method where you check the date and replace the image if needed.
I have an issue. Maybe I've got something in the wrong place or something, but dang I just can't figure it out! Any help would be appreciated.
I am trying to simply make a clock programmatically that shows only in my subview.
I've setup a timer along with an updater -(void) that I want to show in my subView that I create. I am building the subview programmatically which is the reason for not adding an IBOutlet and just connecting it in my storyboard - I'm trying do do it all with just code.
I am getting the error on my updateTimer label that says - Use of undeclared identifier 'rightLabel' and it's just not working out for me. HA HA - any help would be GREATLY appreciated!
.h
#interface DemoRootViewController : UIViewController <PaperFoldViewDelegate> {
NSTimer *timer;
}
#property (nonatomic, strong) UIView *rightView;
-(void)updateTimer;
.m
- (id)init
{
self = [super init];
if (self) {
//Timer Setup
timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(updateTimer) userInfo:nil repeats:YES];
//PaperFold Setup
_paperFoldView = [[PaperFoldView alloc] initWithFrame:CGRectMake(0,0,[self.view bounds].size.width,[self.view bounds].size.height)];
[_paperFoldView setAutoresizingMask:UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth];
[self.view addSubview:_paperFoldView];
//Setup Subview
_rightView = [[UIView alloc] initWithFrame:CGRectMake(0,0,240,[self.view bounds].size.height)];
//Setup UILabel
UILabel *rightLabel = [[UILabel alloc] initWithFrame:_rightView.frame];
[_rightView addSubview:rightLabel];
//Using PaperFold Framework to Add the Subview (this works fine)
[_paperFoldView setRightFoldContentView:_rightView foldCount:2 pullFactor:1];
}
return self;
}
-(void)updateTimer {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"hh:mm:ss"];
//This is where I get my error "Use of Undeclared Identifier 'rightLabel'
rightLabel.text = [formatter stringFromDate:[NSDate date]];
}
#end
You don't have rightLabel declared as a property (or instance variable). Just change your .m to the code below:
.m
#interface DemoRootViewController ()
#property (nonatomic, strong) UILabel *rightLabel;
#property (nonatomic, strong) NSDateFormatter *dateFormatter;
#end
#implementation DemoRootViewController
- (id)init
{
self = [super init];
if (self) {
//Timer Setup
timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(updateTimer) userInfo:nil repeats:YES];
//PaperFold Setup
_paperFoldView = [[PaperFoldView alloc] initWithFrame:CGRectMake(0,0,[self.view bounds].size.width,[self.view bounds].size.height)];
[_paperFoldView setAutoresizingMask:UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth];
[self.view addSubview:_paperFoldView];
//Setup Subview
_rightView = [[UIView alloc] initWithFrame:CGRectMake(0,0,240,[self.view bounds].size.height)];
//Setup UILabel
self.rightLabel = [[UILabel alloc] initWithFrame:_rightView.frame];
[_rightView addSubview:self.rightLabel];
//Using PaperFold Framework to Add the Subview (this works fine)
[_paperFoldView setRightFoldContentView:_rightView foldCount:2 pullFactor:1];
//Formatter setup
self.formatter = [[NSDateFormatter alloc] init];
[self.formatter setDateFormat:#"hh:mm:ss"];
}
return self;
}
-(void)updateTimer {
self.rightLabel.text = [self.formatter stringFromDate:[NSDate date]];
}
#end
The #interface DemoRootViewController () part is called a class extension. It essentially allows you "private" properties, so they are not exposed through the header file. If you want them exposed, simply put the two property definitions into the .h file.
Since you want to update the label, make the label variable an instance variable. Then you can create it in the init method and access it in the updateTimer method.
Also, make the date formatter an instance variable so you only need to create it once in the init method. No need to create a new date formatter every half second.
And since your timer should be a private instance variable, remove it from the .h file and put in the .m file.
#implementation DemoRootViewController {
NSTimer *timer;
}
Add the rightLabel and formatter ivars there too.
Also, remove the declaration of updateTimer from the .h file. This is a private method only used by the implementation in the .m file. Adding it to the .h file allows other classes to call the method.
You have to declare UILabel *rightLabel in .h file because you are using rightLabel in another method also.
Merged with How to change label in ViewController when app enters the foreground.
i want to change a label in my view controller when the app enters the foreground....:
SalaryAppV4AppDelegate.h
#interface SalaryAppV4AppDelegate : NSObject {
//----------------------------------------------
NSTimeInterval appEnteredBackground;
NSTimeInterval appEnteredForeground;
NSTimeInterval difference;
NSString *times;
//-----------------------------------------------
SalaryAppV4AppDelegate.m
(void)applicationWillEnterForeground:(UIApplication *)application
{
//perform -(IBAction)DoThis
FirstViewController* controller = [FirstViewController alloc];
[controller DoThis];
//releasing
[dateFormatter release];
}
//---------------------------------------------------------------------
FirstViewController.h
import UIKit/UIKit.h>
import "SalaryAppV4AppDelegate.h"
#interface FirstViewController : UIViewController {
IBOutlet UITextField *text1;
IBOutlet UILabel *label;
IBOutlet UILabel *labeltotal;
IBOutlet UILabel *differenceLabel;
int i;
float number1;
NSTimer *timer;
SalaryAppV4AppDelegate *appDelegate;
}
//Actions
-(IBAction)reset:(id)sender;
-(IBAction)backgroundTouched:(id)sender;
-(IBAction) beginTimer;
-(void) DoThis;
//Properties
#end
//--------------------------------------------------------------------
FirstViewController.m
-(IBAction) DoThis
{
appDelegate = [[[UIApplication sharedApplication] delegate] retain];
//This Doesn't Work :(
label.text = #"IT Has Worked";
//This Works
NSLog(#"%#", appDelegate.times);
}
//--------------------------------------------------------
i just want the label.text ti change to anything but nothing in the viewcontroller changes...
At first time i call the timer like this in Third viewcontroller
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(targetMethod) userInfo:nil repeats:NO];
Then timer called the targetMethod
-(void)targetMethod
{
First * sVC = [[First alloc] initWithNibName:#"First" bundle:[NSBundle mainBundle]];
[self presentModalViewController:sVC animated:YES];
[sVC release];
[timer invalidate];
}
First viewcontroller opened..
In First viewcontroller had one button.In button action
i wrote
- (IBAction) Action:(id)sender
{
[self dismissModalViewControllerAnimated:YES];
Third *BVC=[[Third alloc]init];
[Bvc TimerStart]; //Timestart is function i start timer in this function..
//i want to call Third viewcontroller timer function this place
}
timer started..But view didn't open (first )viewcontroller.......
Please help me......
Bala,
Place the NSTimer object in the App Delegate .h file, include that .h file in wherever you use the timer. This will allow the NSTimer to be a global timer which you can call from any other view that includes the app delegate header file.
In app delegate .h file (in the appropriate areas):
NSTimer *delayTimer;
#property (nonatomic, retain) NSTimer *delayTimer;
Synthesize this in the app delegate .m file (remember to release it in dealloc):
#synthesize delayTimer;
Then in whichever views you use the timer in, access it like this:
// get global variable
SomeNameHereAppDelegate *mainDelegate = (SomeNameHereAppDelegate *)[[UIApplication sharedApplication] delegate];
mainDelegate.delayTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(targetMethod) userInfo:nil repeats:NO];
Then when you want to invalidate it from somewhere, you just do this:
[mainDelegate.delayTimer invalidate];
mainDelegate.delayTimer = nil;
What if if i need to have a count down timer which should be shared among the view controllers.do i have to make it in the app delegate where the remaining seconds could be an ivar also in app delegate with property?
In this case i would post notification from the timer handler after updating the remaining seconds
In AppDelegate.h
#property int timePassed;
In AppDelegate.m
#synthesize timePassed;
In ViewController.h
#property (weak, nonatomic)NSTimer *timer;
#property (weak, nonatomic) IBOutlet UILabel *time;
In ViewController.m
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
AppDelegate *delegate = (AppDelegate*) [[UIApplication sharedApplication] delegate];
delegate.timePassed = 180;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(TimePasses) userInfo:nil repeats:YES];;
}
-(void) TimePasses{
AppDelegate *delegate = (AppDelegate*) [[UIApplication sharedApplication] delegate];
delegate.timePassed = delegate.timePassed - 1;
NSLog(#"TimePasses %d", delegate.timePassed);
int minuts = delegate.timePassed / 60;
int seconds = delegate.timePassed - (minuts * 60);
NSString *timerOutput = [NSString stringWithFormat:#"%2d:%.2d", minuts, seconds];
time.text = timerOutput;
}
In SecondViewController.h
#property (weak, nonatomic)NSTimer *timer;
#property (weak, nonatomic) IBOutlet UILabel *time;
In SecondViewController.m
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(TimePasses) userInfo:nil repeats:YES];;
}
-(void) TimePasses{
AppDelegate *delegate = (AppDelegate*) [[UIApplication sharedApplication] delegate];
NSLog(#"TimePasses in 2 %d", delegate.timePassed);
int minuts = delegate.timePassed / 60;
int seconds = delegate.timePassed - (minuts * 60);
NSString *timerOutput = [NSString stringWithFormat:#"%2d:%.2d", minuts, seconds];
time.text = timerOutput;
}
in my app, an NSMutableArray is populated with an object in viewDidLoad (eventually there will be many objects but I'm just doing one til I get it working right). I also start a timer that starts a method that needs to access the NSMutableArray every few seconds. The NSMutableArray works fine in viewDidLoad, but as soon as that method is finished, it loses the object.
myApp.h
#interface MyApp : UIViewController {
NSMutableArray *myMutableArray;
NSTimer *timer;
}
#property (nonatomic, retain) NSMutableArray *myMutableArray;
#property (nonatomic, retain) NSTimer *timer;
#end
myApp.m
#import "MyApp.h"
#implementation MyApp
#synthesize myMutableArray;
- (void) viewDidLoad {
cycleTimer = [NSTimer scheduledTimerWithTimeInterval:4.0 target:self selector:#selector(newCycle) userInfo: nil repeats:YES];
MyObject *myCustomUIViewObject = [[MyObject alloc]init];
[myMutableArray addObject:myCustomUIViewObject];
[myCustomUIViewObject release];
NSLog(#"%i",[myMutableArray count]); /////outputs "1"
}
-(void) newCycle {
NSLog(#"%i",[myMutableArray count]); /////outputs "0" ?? why is this??
}
myApp.m is not retaining the array unless you assign to it using self.myMutableArray, unless you use the self. prefix you do not get the benefit of the (nonatomic, retain).
Your results point to an array that is not allocated at the time you read from it. It's either this or failing to allocate the array before using addObject (unlikely given your NSLog result).
- (void) viewDidLoad {
self.myMutableArray = [NSMutableArray array];
...
}
would probably fix this up.
Try this
- (void) viewDidLoad {
cycleTimer = [NSTimer scheduledTimerWithTimeInterval:4.0 target:self selector:#selector(newCycle) userInfo: nil repeats:YES];
MyObject *myCustomUIViewObject = [[MyObject alloc]init];
NSMutableArray *my_array = [[NSMutableArray alloc] initWithCapacity:3];
self.myMutableArray = my_array;
[my_array release];
[myMutableArray addObject:myCustomUIViewObject];
[myCustomUIViewObject release];
NSLog(#"%i",[myMutableArray count]); /////outputs "1"
}
and don't forget to
- (void) viewDidUnLoad {
self.myMutableArray = nil;
}
and
- (void) dealloc{
[myMutableArray release];
[super dealloc];
}