My application needs to show a temporary message, so I created Toast like android myself. It works well for only one toast. I am using NSTimer to hide the message. If I display more than one toast the timer becomes a problem. Only the last added toast becomes hidden, others do not become hidden. How can I hide all toasts?
Code:
Remove function:
-(void)removeToast
{
NSLog(#"removed");
[self.view removeFromSuperview];
}
Timer start:
timer = [NSTimer scheduledTimerWithTimeInterval:(4.0f)
target:self
selector:#selector(xxxx)
userInfo:nil repeats:NO];
I wrote this in above in separate NSObject class and created an object. I need some clarification on how run the two NSTimer simultaneously or keep track of all NSObjects.
Object creation in viewcontroller is
#property(nonatomic,strong)Toast *toast;
No need to keep the istance of timer in a ivar for your purpose. Use the userinfo: parameter to pass the view you mean to hide when the timer fires, like this:
[NSTimer scheduledTimerWithTimeInterval:(4.0f)
target:self
selector:#selector(xxxx)
userInfo:yourView repeats:NO];
Then in your selector retrieve the view from the userInfo and hide it. You can find a working sample here, line 37.
Related
I need guidance for the following concept:
My iOS app has a text/messaging feature... I want to create a class that checks a database every 2 mins for new data no matter where the user is at in the application. I am assuming I would create a new class and just include it on all of my other files.
Is that the best workflow for what I am trying to achieve?
You can probably run a repeat NSTimer with defined frequency from your AppDelegate and in the implemented selector you can write your piece of code to check DB for new data and may be fire a notification if it finds new data. Then you can have any of your viewController listen to that notification to get their UI updated.
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(checkDBForUpdates) userInfo:nil repeats:YES];
I make an asynchronous http request using NSURLConnection every 11 seconds using a NSTimer.
The NSTimer runs on the main run loop. The request has a timeout of 10 seconds.
The NSTimer works well until I increase UI activity on the app (like tapping on UIButtons, dismissing UIAlertViews frequently).
After this the NSTimer speeds up and runs like a while loop without any delays. This creates a lot of problems in the app as I can't make proper handling of the connection responses.
The problem is that you are declaring an NSTimer inside your button action... now every time this button is pressed the NSTimer interval is compiled onto its previous interval and the result is that it gets called twice as often... the next time it's twice as often than the previous twice as often.... etc.
The best way to do it is define the NSTimer in the .h file and then every time you have code in your .m file to call it first check if it's already there and if so invalidate and release it.
if(myTimer){
[myTimer invalidate];
[myTimer release];
}
myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timeInterval) userInfo:nil repeats:YES];
Have a question...
I have Timer
[NSTimer scheduledTimerWithTimeInterval:120
target:self
selector:#selector(action1:)
userInfo:nil
repeats:YES];
But when I move to another screen of my app I want to change selector...How can I change selector ? I know that I can stop my timer and set a new one, but I don't wont to reset a time remained to fire action...Thanks....
You can't. NSTimer takes its targeting information in its instantiation methods, and doesn't expose any properties to modify that later.
You're going to have to invalidate this timer and create a new one on the new target.
It looks like the selector is immutable. I would wrap this functionality into it's only tiny class with a setSelector method. Internally, create the NSTimer with a private selector. Inside that method, call the external selector that's been set using the setSelector method.
You might call a generic selector that, depending on the page shown, calls other methods:
[NSTimer scheduledTimerWithTimeInterval:120
target:self
selector:#selector(selectorDispatcher)
userInfo:nil
repeats:YES];
and than obviously your method selectorDispatcher will look something like:
- (void) selectorDispatcher{
if(pageshown1)
[self callmethod1];
else
[self callmethod2];
}
I think this should work...let me know!
I am creating a repeating NSTimer object that calls the -Loop() method every iteration of the run loop:-
NSTimer *loopTimer = [NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self selector:#selector(Loop) userInfo:nil repeats:YES];
Within Loop() I am invalidating the timer when it becomes necessary:-
[loopTimer invalidate];
However, after using -invalidate(), the Touch handling methods -touchesBegan(), -touchesEnded() stop responding to touch events. Does NSTimer affect the run loop to somehow?
what else you are using in loop method...
I am not sure what problem exactly you have.Anyway try this...
You can use schedular method..
[self schedule:#selector(loop) interval:TIMER_INTERVAL];
If you unscheduling with in the same function,you can use
[self unschedule:_cmd];
otherwise,
You can use [self unschedule:#selector(loop)];
This sounds like you didn't correctly retain the view or have released it once too often. A NSTimer retains its target object, and once you invalidate a timer it releases its target object. In your case, that seems to make the retain counter drop to 0 and it thus gets deallocated.
You can verify this by adding a NSLog right in front of your [loopTimer invalidate]; and another one at the start of your view's dealloc. My bet is that you will see dealloc's log message immediately after your invalidate log.
No, it doesn't affect your runloop in anyway. Infact I checked it myself, after i invalidated the timer i was able to process touches on screen.So i guess problem is something else.
I seem to have fixed the problem by putting -invalidate() inside the -dealloc() method. So when i want end the loop i call [self.view removeFromSuperView] and this calls invalidate eventually.
Putting -invalidate() inside view lifecyle seems to deallocate the view...
I'm making a simple iPhone app whose sole function is to update a UIView forever (until it exits).
I tried this in applicationDidFinishLaunching and viewDidLoad:
while(1) {
// update view here
}
but that doesn't work- the app never finishes loading. I'm sure there's a simple solution to this, I just don't know what it its.
Also: ideally, this process should consume very little resources.
You can't have a while (1) statement like there, as it not allow viewDidLoad to return, and your app will never get any other calls such as tap processing, screen draw updates, etc.
In viewDidLoad, set up a timer task using:
updateTimer = [NSTimer scheduledTimerWithTimeInterval: kUpdateTimeInterval target:self selector:#selector(updateView) userInfo:nil repeats:YES];
And have a method called updateView that actually does the updating. Instead of updateView you could also use setNeedsDisplay which will trigger a call the -drawRect method of your view class, and do the actual drawing there.
What ends up happening now is that your viewDidLoad will set up a repeating task and at every kUpdateInterval, your view will be updated.
Instead of updating the view all the time, maybe you could just call its -setNeedsDisplay method when the data that you're displaying changes.