call a class level method in scheduledTimerWithTimeInterval - iphone

I make a class level method for Alert:
#interface TestAlert
#end
+ (void)showErrorAlert:(NSTimer *)message
{
.......
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:nil message:messageIn delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alert show];
}
and I want to call it directly in scheduledTimerWithTimeInterval like:
[NSTimer scheduledTimerWithTimeInterval:0.001 target:TestAlert selector:#selector( showErrorAlert:) userInfo:error repeats:NO];
There have grammar error of course.
I know I can put showErrorAlert to a method:
- (void)showError:(NSTimer *)timer
{
//NSLog(#"show error %#", error);
[TestAlert showErrorAlert:(NSString *)[timer userInfo]];
}
Then
[NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:#selector(showError:) userInfo:error1 repeats:NO];
But it will cause crash when showErrorAlert is called, because error message from showError method has been released.
Can i call showErrorAlert directly, If I can't, how should I avoid error message's release ?

Just use [TestAlert class] as a target instead of TestAlert.

How about trying this.
You can find all the types of provided performSelector: methods here:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/nsobject_Class/Reference/Reference.html
performSelector:
performSelector:withObject:
performSelector:withObject:withObject:
– performSelector:withObject:afterDelay:
performSelector:withObject:afterDelay:inModes:
performSelectorOnMainThread:withObject:waitUntilDone:
performSelectorOnMainThread:withObject:waitUntilDone:modes:
performSelector:onThread:withObject:waitUntilDone:
performSelector:onThread:withObject:waitUntilDone:modes:
performSelectorInBackground:withObject:

Related

EXC_Bad_Request "only" after calling the uialert 3 or more times

I am a newbie in objective c;
I am getting an error at creating a UIAlertview instantiation statements (UIAlert * myAlert, they are in separate scopes)
I have referred the following stackoverflow entries such as This, this, this too and much more research over the internet.
I am unable to get a break through
Following are my alert calls
This is my view controller code where I have put up the "UIAlertViewDelegate"
#import <UIKit/UIKit.h>
#interface gameFirstViewController : UIViewController<UIAlertViewDelegate>
#end
This is my class declaration
#import <Foundation/Foundation.h>
#interface GameLogic : UIView
//all sorts of various non relevant property declarations
#end
Here is my implementation for the alerts
//action to take when an alert is shown
- (void)alertView:(UIAlertView *)alertView
didDismissWithButtonIndex:(NSInteger) buttonIndex
{ NSLog(#"OK Tapped");
NSUserDefaults *MySettingsData = [NSUserDefaults standardUserDefaults];
row= [MySettingsData integerForKey:#"Row_count"];
col = [MySettingsData integerForKey:#"Column_count"];
if(buttonIndex==0)
{
for(int i=0;i<row;++i)
{
for(int j=0;j<col;++j)
{
myarr[i][j]=0;
}
}
if(_TimerStatus ==1)
{
[mainTimer invalidate];
mainTimer=nil;
_TimerStatus=0;
}
[self super_reset];
[self setNeedsDisplay];
NSLog(#"Game reset");
return;
}
}
//my usage of the alerts at 2 different places
UIAlertView *myAlert = [[UIAlertView alloc]initWithTitle: #"GAME OVER"
message:#"You clicked on a mine, tap on ok to reset"
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil, nil];
[myAlert performSelectorOnMainThread:#selector(show)
withObject:nil
waitUntilDone:YES];
UIAlertView *myAlert = [[UIAlertView alloc]initWithTitle: #"You Won! Whoo Hoo"
message:#"You have successfully dodged every minefield"
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil, nil];
[myAlert performSelectorOnMainThread:#selector(show)
withObject:nil
waitUntilDone:YES];
I am not sure where I am going wrong, any help would be great!
Thanks.
The way you are creating the UIAlertView is not safe in ARC. It's fine if you use the object right away, but you're passing it the performSelectorOnMainThread method. ARC may dealloc your myAlert variable by the time the main thread gets to perform the selector. That's likely why you're seeing the EXC_Bad_Request.
Either make myAlert a strong property, so it survives, or delay the creation of the UIAlert until the main thread is able to call the show method. You can do that like this:
dispatch_async(dispatch_get_main_queue(), ^{
[[[UIAlertView alloc] initWithTitle:#"GAME OVER" message:#"You clicked on a mine, tap on ok to reset" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil] show];
});
Note: I removed your double nil for the titles. I don't think that would make a difference, but just in case.

Load more than one URL in UIWebView one by one

Hi! I am developing an application. In that I am creating one webview. By using that webview I want to load the next url after completion of first one. I written the - (void)webViewDidFinishLoad:(UIWebView *)webView like this
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
alert_View=[[UIAlertView alloc]initWithTitle:#"\n\nData sent successfully!" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:nil, nil];
[alert_View show];
[alert_View release];
[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:#selector(removeAlert:) userInfo:nil repeats:NO];
}
And the removeAlert method looks like
-(void)removeAlert:(id)sender
{
[alert_View dismissWithClickedButtonIndex:-1 animated:YES];
[web loadRequest:[arr objectAtIndex:1];
}
arr array contain all prepared requests. When ever this removeAlert method executed directly -(void)webView:didFailLoadWithError: method is fired. So please tell me how can I load another request after end of first one?
If you're using ARC, you should get rid of the [alert_View release]. The alert view may not be retained, and that could be contributing to the problem.
Also, try [self performSelector: #selector(removeAlert:) withObject:nil afterDelay:3.0]; and see if that works, instead of your NSTimer call.
One way you can do it is by delegating. So once your first request is processed and you get a response, you can send the next one.
If you arent familiar with delegates, here's a link to get you started.

My alertview for the UIWebView doesn't work

Why doesn't this code work? All I have is this:
-(void)_webview:(UIWebView *)_webview didFailLoadWithError:(NSError *)error {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error!" message:#"You have no internet connection!" delegate:self cancelButtonTitle:#"Close" otherButtonTitles:nil, nil];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
exit(0);
}
It should work, right?
Because you mistyped the name of the UIWebViewDelegate method. You have
_webview:didFailLoadWithError:
whereas the real name of this method is
webView:didFailLoadWithError:
The delegate method is mistyped, as stated in the above response. Also, did you set the delegate of the UIWebView to the instance of the class that has those methods implemented?
for example, if it's a view controller, it could be in viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
_webView.delegate = self;
}

Creating a timer to timeout and pop up an alert

I'm trying to get a recent location using CLLocationManger. If I cannot get one within 30 seconds, I want an alert to pop up saying that "we're having problems right now" or something along those lines. In my CLLocationManager Delegate, I do this:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSDate *eventDate = newLocation.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
NSTimer *timer;
if (abs(howRecent) < 1.0) { // process time if time is less than 1.0 seconds old.
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updateCount:) userInfo:nil repeats:NO];
return;
}
My updateCount method:
- (void)updateCount:(NSTimer *)aTimer {
count++;
NSLog(#"%i", count);
if (count == 30) {
[aTimer invalidate];
NSLog(#"Timer invalidated");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Server Down" message:#"Sorry, but we cannot find your location at this time. Please try again later." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
[alert release];
}
}
But I don't see my alert get fired. I tried with a repeating timer, but after it hits 30 seconds, and the alert is shown, it repeats again. So I'm not quite sure what I'm doing wrong here. Thanks!
just a small update to updateCount method :
- (void)updateCount:(NSTimer *)aTimer {
count++;
NSLog(#"%i", count);
if (count == 30) {
[aTimer invalidate];
NSLog(#"Timer invalidated");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Server Down" message:#"Sorry, but we cannot find your location at this time. Please try again later." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
[alert release];
[timer invalidate];
timer = nil;
}
}
Don't use NSTimer *timer; in locationManager method. instead directly call timer = [[NSTimer....]] method and I think because there is one argument in updateCount method i.e. NSTimer and we are using different NSTimer instance so here is basically problem. Try without using argument in updateCount Method and invalidate the timer that is declared in .h file.
I checked the documentation and found following paragraph in that.
However, for a repeating timer, you must invalidate the timer object yourself by calling its invalidate method. Calling this method requests the removal of the timer from the current run loop; as a result, you should always call the invalidate method from the same thread on which the timer was installed.
So, for invalidating timer try calling performSelector.
I am not sure weather it will help or not but if it works then please post here so that other too can take advantage.

iPhone memory management question and object livecycle

Here is the code I have:
Phone SDK undestanding cocoa object live cycle:
- (void) DismissWelcomeMessage: (UIAlertView *) view
{
[view dismissWithClickedButtonIndex:0 animated:YES];
}
- (void) ShowWelcomeMessage
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Blah" message:#"Blah Blah" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[self performSelector:#selector (DismissWelcomeMessage:) withObject: alert afterDelay: WELCOME_MESSAGE_DELAY];
[alert release];
}
ShowWelcomeMessage is called first.
Why DissmissWelcomeMessage works fine and does not crash even though alert object is released?
Is because Dismiss function uses copy of the object passed on stack as a parameter when function? But even then would not it be just a copy of the pointer pointed to the now deallocated object?
Or [alert release] just decriment reference counting and does not really do the same as
delete in C++?
performSelector retains the object, thus your release doesn't cause its retain count to go to zero.
See NSObject docs
This method retains the receiver and the anArgument parameter until after the selector is performed.
It's possible that performSelector is retaining the object passed in, which is why it's still valid when DismissWelcomeMessage is called.