Make a timer link to a action - objective-c

I have the code to make it so a notification pops up when I press a button. I want it so it appears when 10 seconds is up.
I know i need to do this:
(NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds invocation:
(NSInvocation *)invocation repeats:(BOOL)repeats
My action is:
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"UIAlertView"
message:[NSString stringWithFormat:#"%d", hi]
delegate:hi
cancelButtonTitle:#"Ok"
otherButtonTitles: nil];
[alert show];
}

You can just do:
[self performSelector:#selector(actionMethodName) withObject:nil afterDelay:10];
If you replace actionMethodName with the true method name.
If you want to use the timer route (which is perfectly valid too) it's easier to use scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: than to create an invocation. If you do this, keep a reference to the timer and invalidate it when you're done.
Based on the updated question details, using a timer and invalidating it is becoming a more preferable method, cancelling perform selector is doable but it isn't as clear as the timer route. I'll show the code for the perform selector route anyway:
- (void)startEverything
{
[self performSelector:#selector(showAlert) withObject:nil afterDelay:10];
}
- (void)handleButtonTap:(id)sender
{
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(showAlert) object:nil];
}
- (void)showAlert
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"UIAlertView"
message:[NSString stringWithFormat:#"%d", hi]
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
}
Using timers would have the same method structure, but would require a #property to store the timer and instead of cancelPreviousPerformRequestsWithTarget... you would [self.timer invalidate]; self.timer = nil;.

try this:
-(IBAction)btnDoneClick:(id)sender {
[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:#selector(buttonactionalert) userInfo:nil repeats:NO];
}
-(void) buttonactionalert {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"UIAlertView"
message:[NSString stringWithFormat:#"%d", hi]
delegate:hi
cancelButtonTitle:#"Ok"
otherButtonTitles: nil];
[alert show];
}

I would personally just use performSelector:withObject:afterDelay: It would look something like this:
// Action on button press
- (IBAction)myActionButtonPress:(id)sender {
// setup the selector to fire in 10 seconds
[self performSelector:#selector(showAlert) withObject:nil afterDelay:10.0];
}
// the selector to be called
- (void)showAlert {
// display alert
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"UIAlertView"
message:#"This alert displayed 10 seconds after button press"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
this would activate your action method after 10 seconds.

Related

UIAlertView is causing a EXC_BAD_ACCESS and app hang

Ive the following code which is working fine , but when I add UIAlertView its start giving me exc_bad_access and the app hanged ,
The main idea is to show alert when timestamp dedtected ,
any tips what im doing wrong ?
- (void) onPayload:(PayloadEvent *) event {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *header = #"[OnPayload] ";
if (event.payloadType == TYPE_IDENTIFIED) {
if ((event.contentID != -1) && (event.timeStamp == -1)) {
[mUI performSelectorOnMainThread: #selector(Trace:) withObject:[NSString stringWithFormat:#"%# StaticID detected: %x\t\tConfidence: %f\n", header,(int)event.contentID, event.confidence] waitUntilDone:NO];
}
if ((event.timeStamp != -1) && (event.contentID == -1)) {
[mUI performSelectorOnMainThread: #selector(Trace:) withObject:[NSString stringWithFormat:#"%# Timestamp detected: %f\t\tConfidence: %f\n", header, event.timeStamp, event.confidence] waitUntilDone:NO];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Poll" message:#"MY alert Poll" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[alert release];
}
}
else if (event.payloadType == TYPE_NOT_IDENTIFIED) {
[mUI performSelectorOnMainThread: #selector(Trace:) withObject:[NSString stringWithFormat:#"%# Content not marked\n", header] waitUntilDone:NO];
}
else if (event.payloadType == TYPE_MARKED_BUT_NOT_IDENTIFIED) {
[mUI performSelectorOnMainThread: #selector(Trace:) withObject:[NSString stringWithFormat:#"%# Content marked but not identified\n", header] waitUntilDone:NO];
}
[event release];
[pool release];
}
My error appear here
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Poll" message:#"MY alert Poll" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show]; <<=====
[alert release];
Any code that changes the UI should be called from the main thread:
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Poll" message:#"MY alert Poll" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[alert release];
});
On the contrary to some comments, the view that is displaying the alert will retain the UIAlertView instance, so there is no need to call autorelease instead of release.
Considering that you are calling -performSelectorOnMainThread a few times in the same method, I imagine it's being called on a background thread. UI changes must occur on the main thread, and thus, you should be calling [alert show]; on the main thread in order to bypass the error.
[alert performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:NO];

Two UIAlertView consecutively in didFinishLaunchingWithOptions

I want two alert views to show up only when the user opens my application for the first time -- the second to appear after the first is dismissed. I have it set up to only show the UIAlertViews when it has not been shown before and I do not need help with this. I need help figuring out how to display two alert views in a row when this is the case.
-(void) alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex does not work for me.
Here is the code I have -- remember this is in didFinishLaunchingWithOptions:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL didFirstLaunch = [defaults boolForKey:#"DidFirstLaunch"];
if (!didFirstLaunch) {
[defaults setBool:YES forKey:#"DidFirstLaunch"];
UIAlertView *successAlert = //not important
[successAlert show];
[successAlert release];
//Somehow show second alert after the first is dismissed
}
I'm gonna post a very simple solution using GCD & blocks (GCD part is just in case the alert view is created on another thread then the main thread, callback should be safe to perform on the main thread). Remember, I just coded this in like 5 mins, so you definitely should work on improving the code. One thing that's a bit ugly is the delegate parameter that is overridden in my subclass. The interface of the subclass could be changed a bit to make it more obvious of what happens ...
Anyway, here goes ...
First create a subclass of UIAlertView, make it look somewhat like the following ...
#interface FSAlertView () <UIAlertViewDelegate>
#property (nonatomic, copy) void (^dismissHandler)(NSInteger buttonIndex);
#end
#implementation FSAlertView
#synthesize dismissHandler = _dismissHandler;
- (void)showWithDismissHandler:(void (^)(NSInteger buttonIndex))dismissHandler
{
self.dismissHandler = dismissHandler;
self.delegate = self;
[self show];
}
// Alert view delegate
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
dispatch_async(dispatch_get_main_queue(), ^ {
if (_dismissHandler)
{
_dismissHandler(buttonIndex);
}
});
}
Now in the app we can create alert views like the following ...
FSAlertView *alert1 = [[FSAlertView alloc] initWithTitle:#"Alert 1"
message:#"Some message"
delegate:nil
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Show 2nd Alert", nil];
[alert1 showWithDismissHandler:^ (NSInteger buttonIndex) {
NSLog(#"button pressed: %d", buttonIndex);
if (buttonIndex == 1)
{
UIAlertView *alert2 = [[UIAlertView alloc] initWithTitle:#"Alert 2"
message:#"Hi!"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert2 show];
}
}];
If i understand your question correctly , then this may help:
UIAlertView *firstAlert = [[UIAlertView alloc] initWithTitle:#"Alert 1" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:nil, nil];
[firstAlert show];
[self performSelector:#selector(test:) withObject:firstAlert afterDelay:2];
[firstAlert release];
UIAlertView *secondAlert = [[UIAlertView alloc] initWithTitle:#"Alert 2" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:nil, nil];
[secondAlert show];
[self performSelector:#selector(test:) withObject:secondAlert afterDelay:2];
[secondAlert release];
-(void)test:(UIAlertView*)alert{
[alert dismissWithClickedButtonIndex:-1 animated:YES];
}
This will show two alert views one after the other.
NOTE: I am not sure if you are dismissing the alerts with cancel button so i am dismissing them automatically after few seconds.
Try this:
UIAlertView *firstAlert = [[UIAlertView alloc] initWithTitle:#"Title" message:#"Message" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok", nil];
[firstAlert setTag:444];
[firstAlert show];
firstAlert = nil;
AlertView Delegate Method:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
switch (alertView.tag) {
case 444:
{
//Cancel ButtonIndex = 0
if (buttonIndex == 1) {
UIAlertView *secondAlert = [[UIAlertView alloc] initWithTitle:#"Title 2" message:#"Message2" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Dismiss", nil];
[secondAlert setTag:555];
[secondAlert show];
secondAlert = nil;
}
}
break;
case 555:
{
if (buttonIndex == 1) {
NSLog(#"Code Here");
}
}
break;
}
}

clickedButtonAtIndex: not working

Hi guys i have this i IBAction linked to a button:
- (IBAction)showCurl:(id)sender {
alert1 = [[UIAlertView alloc]initWithTitle:#"Loading" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
[alert1 show];
}
and a clickedButtonIndex to auto run but somehow it doesn't load SecondViewController:
#pragma mark UIAlertView
- (void)alertView:(UIAlertView *)alert1 clickedButtonAtIndex:(NSInteger)buttonIndex {
if(buttonIndex == 0){
SecondViewController *sampleView = [[SecondController alloc] init];
[sampleView setModalTransitionStyle:UIModalTransitionStylePartialCurl];
[self presentModalViewController:sampleView animated:YES];
}
else{
// Cancel prompt
}
}
Am i missing something here?
If you don’t give the alert view some button titles, there won’t be any buttons to tap on and that delegate method won’t get called.
- (IBAction)showCurl:(id)sender {
alert1 = [[UIAlertView alloc] initWithTitle:#"Loading" message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert1 show];
}
Your code doesn't show a button
alert1 = [[UIAlertView alloc]initWithTitle:#"Loading" message:nil delegate:self cancelButtonTitle:**nil** otherButtonTitles:**nil**];
You pass nil as cancelButtonTitle AND nil as otherbuttonTitles, you should at least have one button title set.

Alert View in the Beginning and the End of a void

I have a Void. This void do something really slow, so at the beginning of Void I put an alert, and in the end I put another warning. Like here:
-(void)action {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Start" message:#"Start." delegate:self cancelButtonTitle:#"Ok." otherButtonTitles:nil];
[alerta show];
[alert release];
//Something really slow
UIAlertView *alertEnd = [[UIAlertView alloc] initWithTitle:#"End" message:#"End." delegate:self cancelButtonTitle:#"Ok." otherButtonTitles:nil];
[alertEnd show];
[alertEnd release];
}
But when I run this code, the alerts are only shown at the end of the Void, after all the slow action.
How can I fix this?
First of all: try to avoid using many alerts since it's not humane to you users. Show UIActivityIndicator instead.
If you must, then try this code for showing the first alert:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Start" message:#"Start." delegate:self cancelButtonTitle:#"Ok." otherButtonTitles:nil];
[alert performSelector: #selector(show)
onThread: [NSThread mainThread]
withObject: nil
waitUntilDone: NO];
you will have to separate the two in two methods and then call one using
[self performSelector: afterDelay:]
method

UIAlertView without any buttons

I wanted to know whether the following code is okay or not. I am trying to dismiss the alertView automatically after 2 seconds (and without any buttons in the alertView) from the "timedAlert" method.
//this is in another method
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:#"Login successful." delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
[alert show];
[alert release];
[self timedAlert];
}
-(void)timedAlert
{
[self performSelector:#selector(dismissAlert:) withObject:alert afterDelay:2];
}
-(void)dismissAlert:(UIAlertView *) alertView
{
[alertView dismissWithClickedButtonIndex:nil animated:YES];
}
If the cancelButton of the alertView is set to "nil", how will the "[alertView dismissWithClickedButtonIndex:0 animated:YES];" thing work??? I tried making the cancelButton "nil" and it worked, but cant figure out how....
P.S: I call the timedAlert method from another
Any help is appreciated! Thank you!
First let me say it would be better if you handle this with a custom view, but with that said the problem looks to be with
[alert release];
You are releasing the object before you are done with it (I am surprise it does not crash).
Do something like this
// other code
alert = [[UIAlertView alloc] initWithTitle:nil message:#"Login successful." delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
[alert show];
[self performSelector:#selector(dismissAlert:) withObject:alert afterDelay:3.0f];
}
-(void)dismissAlert:(UIAlertView *) alertView
{
[alertView dismissWithClickedButtonIndex:nil animated:YES];
[alertView release];
}
Your code should work, and you should have no problems. I have done this in one of my previous apps. The button is not displayed because the title is nil but I think the instance of the button still exists. Put a breakpoint before closing your alert and take a look at the alert variable, and check to see if there is a buttons array or something, that should tell you how that works.