Am I releasing memory correctly? - iphone

I have the following helper object:
LikeHelper* likeHelper = [[LikeHelper alloc]init];
likeHelper.delegate = self;
[likeHelper performLike:self.messageID];
[likeHelper release];likeHelper=nil;
performLike will do some NSURLConnection stuff and then tell the delegate whether or not it was successful.
#pragma mark LikeHelperDelegate Methods
-(void)performLikeFinished:(BOOL)isSuccessful{
if (isSuccessful) {
UIAlertView *alertView;
alertView = [[UIAlertView alloc] initWithTitle:#"Success!" message:#"The message has been liked" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
}
else {
UIAlertView *alertView;
alertView = [[UIAlertView alloc] initWithTitle:#"Error!" message:#"There was a problem liking your message" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
}
}
Am I releasing the likeHelper in the right place?

If the performLike: method is asynchronous, the likeHelper will propably be released before the performLikeFinished: method is called. You should release the likeHelper in the dealloc: method of the owner object or in the performLikeFinished: implementation in the LikeHelperDelegate to prevent releasing it too soon but if you do that, be aware of JeremyPs comment below!.
If the performLike: method is synchronous, you are doing the right thing but you wouldn't need the delegate to collect the result.

Yes you are, your code is according to the guidelines.
If your code do not work then the problem might be that LikeHelper need to retain self from within -[LikeHelper performLike:].
You should also not retain the LikeHelperDelegate, that might be another cause of confusion or errors.

Related

EXC_BAD_ACCESS code 2 on UIAlertView in iOS6

I'm trying to figure out why im getting this crash in my app.
It works perfectly fine in Xcode 4.4 running in the simulator with ios5.1, but when i switch into xcode 4.5 and ios6 I'm getting an EXC_BAD_ACCESS code 2. Here is my code:
- (void) myMethod
{
UIAlertView *alertview = [[[UIAlertView alloc]initWithTitle:#"Title" message:#"message" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil] autorelease];
alertview.tag = 1
[alertview show];
}
this is giving me an EXC_BAD_ACCESS code 2 on the [UIAlertView show] line
any ideas?
thanks!
I've got it.
I have the same problem, in my case it seems that the method is thrown from background now (now in ios7, in ios6 UIAlertView was automatically put into the main-thread as #nodepond says -thanks!-)..
try to assure that the method is shown from main thread:
[alertView performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:YES];
Good luck!
It's happened with me, even in 2014.
The problem is want to use an object already released.
What I did wrong:
//class B with UIAletViewDelegate
-(void) showAlert{
UIAlertView * alert = [[UIAlertView alloc] initWithTitle bla bla...];
[alert show];
}
//class A
viewDidLoad{
MyClassB *B = [[B alloc] init];
[B showAlert];
}
What is the right way:
//Class A
#implementation A{
ClassB *B;
}
viewDidLoad{
B = [[B alloc] init];
[B showAlert];
}

locationManager didFailWithError Repeatedly Called

I am showing alertViews when Location manager unable to find current location. I did it like this
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
[manager stopUpdatingLocation];
switch([error code])
{
case kCLErrorNetwork: // general, network-related error
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Please check your network connection or that you are not in airplane mode" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
break;
case kCLErrorDenied:{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"User has denied to use current Location " delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
break;
default:
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Unknown network error" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
break;
}
}
My problem is locationManager didFailWithError method get called repeatedly. So my alertviews repeatedly display.
How can I solve this issue?
Apple documentation states:
If the location service is unable to retrieve a location right away,
it reports a kCLErrorLocationUnknown error and keeps trying. In such a
situation, you can simply ignore the error and wait for a new event.
If the user denies your application’s use of the location service,
this method reports a kCLErrorDenied error. Upon receiving such an
error, you should stop the location service.
So you might skip some cases where you stop updating and show the alert, especially the default case.
A good start for error messages that can be triggered by an ongoing background process - like the location manager - is to store the reference to the UIAlertView. When the delegate receives alertView:clickedButtonAtIndex:, reset this reference to nil. Before displaying new errors, check if one is already visible.
Even better, don't display modal error messages from background processes. Just walking around, you'll occasionally lose reception, and it's tedious to have to dismiss an error when that happens. If your app has a configuration or help screen, include a space there for the most recent error message from the Location Manager (or Game Center, or iCloud, or anything else that loses connectivity occasionally.)

EXC_BAD_ACCESS error - sometimes only

my app has a button that checks whether an entered value is correct.
sometimes it causes it to crash, but the strange thing is that it happens at irregular intervals (sometimes on the third iteration, sometimes the tenth, sometimes never).
i get a EXC_BAD_ACCESS error in the debugger. so it seems like something is being released when it shouldn't be. the button calls this function:
- (IBAction)checkValue:(id)sender{
int actualDifference = [firstNumberString intValue] - [secondNumberString intValue];
actualDifferenceAsString = [NSString stringWithFormat:#"%d", actualDifference];
if ([answerTextField.text isEqualToString:actualDifferenceAsString])
{
UIAlertView *correctAlert = [[UIAlertView alloc] initWithTitle:#"matches"
message:#"next value."
delegate:nil
cancelButtonTitle:#"ok"
otherButtonTitles: nil];
[correctAlert show];
[correctAlert release];
}
else
{
UIAlertView *incorrectAlert = [[UIAlertView alloc]
initWithTitle:#"does not match"
message:#"next value."
delegate:nil
cancelButtonTitle:#"ok"
otherButtonTitles: nil];
[incorrectAlert show];
[incorrectAlert release];
}
using zombies pointed to the first statement:
int actualDifference = [firstNumberString intValue] - [secondNumberString intValue];
does anyone know what the problem might be?
If zombies are detected in the first line, that means some other part of your program is releasing firstNumberString or secondNumberString. That's where the problem starts, but it only shows up here, when you later try to access those values. Where else do you work with those strings? Do you ever release them?
For overall safety, they should probably be assigned properties, not member variables.
Change it into
NSInteger actualDifference = [firstNumberString intValue] - [secondNumberString intValue]; //change int to NSInteger
NSString *actualDifferenceAsString = [NSString stringWithFormat:#"%d", actualDifference];
if ([answerTextField.text isEqualToString:actualDifferenceAsString])
{
UIAlertView *correctAlert = [[UIAlertView alloc] initWithTitle:#"matches"
message:#"next value."
delegate:nil
cancelButtonTitle:#"ok"
otherButtonTitles: nil];
[correctAlert show];
[correctAlert release];
}
else
{
UIAlertView *incorrectAlert = [[UIAlertView alloc]
initWithTitle:#"does not match"
message:#"next value."
delegate:nil
cancelButtonTitle:#"ok"
otherButtonTitles: nil];
[incorrectAlert show];
[incorrectAlert release];
}
you get this code. It worked for me...

Reachability Xcode iOS5

i want to add a alter if the user is not connected to the internet and clicks on a webview link.
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Can't connect. Please check your internet Connection" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
Problem is here:
Void (-) gives error:(!)Invalid argument type 'void' to unary expression
Very possibly the problem does not lie with the -(void)webView:didFailLoadWithError method itself; rather, it seems you are using it in an incorrect way, i.e.. within an expression that requires a unary operator (e.g., negation, increment, etc.).
In other words, it seems you are trying to use the method's return value somewhere, but there is no return value from that method.
Check the code where you call -(void)webView:didFailLoadWithError...
This is very simple you dont have to code in any delegate method for check weather the user is connected to internet,for example the there is a login page for you and the user logs in but network is not connectd ,so we have to give an alert to user that the network is not connectd right?just simply add the
if(responce == nil)ie,responce from the url
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Can't connect. Please check your internet Connection" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
} else you code

UIAlertView Pops Up Three Times per Call Instead of Just Once

I am getting odd behavior from an NSAlert in two different parts of my program. The behavior is:
Alert appears and then spontaneously disappears.
Alert reappears and then remains until dismissed by user i.e. normal behavior.
Alert reappears again.
This behavior only occurs the first time the method that displays the alert is called. After that first time, it behaves normally.
Here is the code for the one of the parts in which the behavior occurs:
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:#"You are in the right place." message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[locationAlert show];
[locationAlert release];
Or if you prefer, with a bit more context:
- (IBAction)locateMe {
NSLog(#"About to check location");
locMan = [[CLLocationManager alloc] init];
locMan.delegate = self;
locMan.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
locMan.distanceFilter = 1609; //1 mile
[locMan startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation * )oldLocation {
if (newLocation.horizontalAccuracy >= 0) {
CLLocation *airportLocation = [[[CLLocation alloc] initWithLatitude:51.500148 longitude:-0.204669] autorelease];
CLLocationDistance delta = [airportLocation getDistanceFrom: newLocation];
long miles = (delta * 0.000621371) + 0.5; //metres to rounded mile
if (miles < 3) {
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:#"You are in the right place." message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[locationAlert show];
[locationAlert release];
[locMan stopUpdatingLocation];
} else {
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:#"You are not in the right place." message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[locationAlert show];
[locationAlert release];
[locMan stopUpdatingLocation];
}
}
}
- (void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:#"Error." message:error.code delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[locationAlert show];
[locMan release];
locMan = nil;
}
Any ideas? Thanks.
Edit---------
The other place this happens is:
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
NSString * errorString = [NSString stringWithFormat:#"Unable to download feed from web site (Error code %i )", [parseError code]];
NSLog(#"error parsing XML: %#", errorString);
UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:#"Error loading content" message:errorString delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
For context the first case is in the AppDelegate and the second in the view controller for the 1st tab view. The second problem occurs every time the xml is reloaded when there is no internet connection. The first one only occurs the first time the function is called.
Edit-----
If I move the alert it works. Unfortunatly this is not where I want it!
- (IBAction)locateMe {
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:#"You are in the right place." message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[locationAlert show];
/*
NSLog(#"About to check location");
locMan = [[CLLocationManager alloc] init];
locMan.delegate = self;
locMan.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
locMan.distanceFilter = 1609; //1 mile
[locMan startUpdatingLocation];*/
}
Update:
I set some NSLog entries and discovered that despite the addition of [locMan stopUpdatingLocation] the didUpdateToLocation function was running multiple times.
I guess the spontaneous disappearance happens because the alert view is called again and the programme clears the first instance to make way for the second automatically.
Any ideas as to why [locMan stopUpdatingLocation] doesn't work would be appreciated but in the mean time I just moved the declaration of the locationAlert out of the function (so it is global), set it in the initial locate me function and use the following the first time it is called:
[locationAlert show];
locationAlert = nil;
That way it works perfectly.
You're not turning off your location manager when you first show the alert. As the location is refined by the device (ie, the accuracy is increased), your callback will be (potentially) called multiple times. You should use [locMan stopUpdatingLocation] after your alert display.
I set some NSLog entries and discovered that despite the addition of [locMan stopUpdatingLocation] the didUpdateToLocation function was running multiple times.
I guess the spontaneous disappearance happens because the alert view is called again and the programme clears the first instance to make way for the second automatically.
Any ideas as to why [locMan stopUpdatingLocation] doesn't work would be appreciated but in the mean time I just moved the declaration of the locationAlert out of the function (so it is global), set it in the initial locate me function and use the following the first time it is called:
[locationAlert show];
locationAlert = nil;
That way it works perfectly.
I think the NSAlert disappearing on its own is the key to solving this.
It's simple to explain why an alert displays unexpectedly i.e. it's just been called unexpectedly. However, it's not so common to programmatically dismiss an alert. Whatever is causing it to disappear is most likely triggering the display again.
To debug I suggest:
(1) Looking in your code for the NSAlert – dismissWithClickedButtonIndex:animated: method and see if somehow you're actually dismissing the alert programmatically.
(2) I believe (someone double-check me on this) that an alert view is added as a subview to whichever base view is currently on screen. It might be that the base view is disappearing for some reason and taking the alert view with it. If the view disappears and then reappears rapidly enough, it might not be obvious when the alert is frontmost. (Edit: see Ed Marty's comment below.)
(3) Since this happens in two separate pieces of the app, compare both to find a common element or structure. That common element might be the cause.
An odd problem.
Edit01: Updated for additional info
If locMan isan instance variable, it should be defined as a property and you should access it every time withself.locMan By accessing it directly, you lose your automatic retention management.
I encountered the same exact issue with the alert dialog appearing momentarily, reappearing, and finally appearing again after being dismissed. I was making a string comparison before deciding to show the alert view:
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if([string isEqualToString:#"OK"]) {
NSLog(#"(Settings)Registration Successful");
statusField.text = #"Registration successful!";
[settingsActivity stopAnimating];
}
else {
NSLog(#"(Settings)Registration Failure");
[settingsActivity stopAnimating];
UIAlertView * regFail = [[[UIAlertView alloc] initWithTitle:#"Registration Error!" message:#"Please check your email address and try again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil] autorelease];
[regFail show];
}}
To correct this behavior I simply verified the returned string rather than just showing the alert:
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if([string isEqualToString:#"OK"]) {
NSLog(#"(Settings)Registration Successful");
statusField.text = #"Registration successful!";
[settingsActivity stopAnimating];
}
else if([string isEqualToString:#"Error"]) {
NSLog(#"(Settings)Registration Failure");
[settingsActivity stopAnimating];
UIAlertView * regFail = [[[UIAlertView alloc] initWithTitle:#"Registration Error!" message:#"Please check your email address and try again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil] autorelease];
[regFail show];
}
I also got the Same problem while working on Location Manager. Here i checked with Nslog but it is executing multiple times, finally i fount that i am creating multiple objects and using Sharedinstance for same ViewController that contains Location Manger but i am not releasing the object, so at perticular location how many objects if we create that many times the location detects.So while working on LocationManger check handling objects thoroughly to reduce these type of problems.