memory bad access? - iphone

How can this statement ever give me bad access?
myWebView = [[NewsWebViewController alloc] initWithNibName:#"NewsWebViewController" bundle:nil];
[[self.view.superview superview] addSubview:myWebView.view];
if(myWebView!=nil) {
[myWebView release];
myWebView = nil;
}
Ive ran it through instruments and it crashes every time. myWebView is an ivar in my header file.
Any thoughts? Many thanks
Jules

ok here is the actual issue. When I removed the webview it gets dealloc'd but I didnt set its delegate to nil. Therefore webViewDidFinishLoading etc was trying to access it and giving me bad access.
Thanks to all for your input.

You should check that myWebView is nil before you add it's view to a subview. You do not need to set myWebView to nil after you release it.

You are setting mywebview to nil after releasing so it crashes as the object no longer exists. Do it in this order:
if(myWebView!=nil) {
myWebView = nil;
[myWebView release];
}

Related

presentModalViewController memory leak or EXC_BAD_ACCESS

-(void) addBookmarkTapped:(id)sender {
BookmarkAddViewController *bookmarkAddViewController =
[[BookmarkAddViewController alloc] initWithName:currTitle link:self.addressBar.text];
[self presentModalViewController:bookmarkAddViewController animated:YES];
[bookmarkAddViewController release];
}
code above cause 'EXC_BAD_ACCESS' when back to the main controller. Same error if I make bookmarkAddViewController 'autorelease'.
It will not crash if I remove the release, but it will cause memory leak?
[bookmarkAddViewController release];
I see many examples doing the same way, why it doesn't work in my case?
It might have to do with your init method in bookmarkAddViewController.(Please post.) Make sure you dismiss the controller properly with [self dismissModalViewControllerAnimated:YES];.

UIActivityIndicatorView nillify makes it crash

For the code below if I nillify the indicator by "self" it crashes if dont use self than no crash.
Isnt it the rule that I should always use "self" to access ivars created and retained by #property ?
#property(nonatomic,retain) UIActivityIndicatorView* activityIndicator;
if(activityIndicator!=nil){
[activityIndicator removeFromSuperview];
//self.activityIndicator = nil; //crashes!
activityIndicator = nil; //does not crash
}
Generally speaking:
self.activityIndicator = nil; //crashes!
will release the activityIndicator, so this is possibly related to the crash.
activityIndicator = nil; //does not crash
will not release the activity indicator, you don't have a crash, you have a memory leak.
In your concrete case, possibly the crash depends on the fact that when you execute this:
[activityIndicator removeFromSuperview];
the activity indicator is released; now, if it also happens that retain count goes to 0, the object is also deallocated, but the property is not updated to reflect the fact that the object has been deallocated. SO, when you set it to nil, the setter tries to release it, but the obejct dos not exist anymore and hence the crash.
This is a guess. It should not happen if you retained correctly the activity indicator in your class. So, either you review the code where you create the activity indicator and the places in your code where you use activityIndicator or you post it for more help...

EXC_BAD_ACCESS and Zombies, Yet not really sure why it keeps coming up

I don't know what's going wrong here. The crash happens when switching back and forth between views.
Here's what instruments gives me:
Clicking into it references this code with the first action :
-(IBAction)pushnews; {
NewsViewController *news = [[[NewsViewController alloc]init]autorelease];
news.title =#"Page";
[self.navigationController pushViewController:news animated:YES]; }
I use autorelease sometimes but usually I just release it my self. Should I get rid of autorelease and add [news retain]
What am I doing wrong?
Edit based on answers:
Following EmptyStack's Advice: ViewWillDisappear Code looks like this:
- (void)viewWillDisappear:(BOOL)animated {
webView.delegate = nil; }
This seems to resolve issues (pending more testing)
In viewdidload I said: webView.delegate = self;, which may have been the issue!
My guess is that, there is a UIWebView in NewsViewController, and it is causing the crash. It is possible that, a delegate method of web view is called after the web view is released. If so, try to setwebView.delegate = nil; in NewsViewController's viewWillDisappear: method.
try this instead :
-(IBAction)viewcontroller;
{
NewsViewController *news = [[NewsViewController alloc]init];
news.title =#"Page";
[self.navigationController pushViewController:news animated:YES];
[news release];
}

presentModalViewController in viewDidLoad on first launch

I've been searching around but unfortunately have had no luck.
My app requires the user to sign in/sign up the first time he or she launches the app. I know how to determine first launch (using NSUserDefaults) but whenever I try to present the modal containing the sign in/ sign up controls, nothing happens.
Here's what I have:
-(void)viewDidLoad {
[self showLogin];
[super viewDidLoad];
}
-(void)showLogin {
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"AccountView" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:controller animated:YES];
[controller release];
}
However, nothing happens. The main view just loads as normal. Any help is greatly appreciated.
-Giles
[UPDATE]
Fixed simply by using..
-(void)viewDidAppear:(BOOL)animated
{
}
instead of
-(void)viewDidLoad
{
}
Thanks anyway!
/idiocy
I had the same issue and ended up using viewDidAppear as well. The only problem with the viewDidAppear approach is that if you load other UIViewControllers on top, then reshow the base, then your setup code gets called over and over. I ended up having to add a boolean value (initialised to YES) to this view controller and check that value before deciding what to do. Hope this helps someone...
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:(BOOL)animated];
if(justLaunched)
{
justLaunched = NO;
if(settingsFileExists)
{
[self displayMainView];
}
else
{
[self displaySetupView];
}
}
}
How about using performSelector:withObject:afterDelay in the viewDidLoad function? That's how I do it, with a short delay of 0.1s.
And invoking this in the viewDidLoad isn't very safe : the sequence viewDidLoad / viewDidUnload can occur at runtime when the iPhone needs to release some views in order to get back some free memory.
The side effect of such sequence would be that your login controller would be shown...
As you said the viewDidAppear looks better but not simply put it at the end of the appDidFinishedLaunching the delegate of your UIApplication?

Do I need to set these variables to nil in viewDidLoad as I have in this code?

- (void)viewDidUnload {
self.GPSArray = nil;
self.accelerometerArray = nil;
self.headingArray = nil;
self.managedObjectContext = nil;
self.locationManager = nil;
self.pointLabel = nil;
self.accelerometerLabel= nil;
self.headingLabel= nil;
self.startStop = nil;
self.lastAccelerometerReading = nil;
self.lastGPSReading = nil;
self.lastHeadingReading = nil;
}
- (void)dealloc {
[GPSArray release];
[accelerometerArray release];
[headingArray release];
[managedObjectContext release];
[locationManager release];
[pointLabel release];
[accelerometerLabel release];
[headingLabel release];
[startStop release];
[lastAccelerometerReading release];
[lastGPSReading release];
[lastHeadingReading release];
[super dealloc];
}
The reason viewDidUnload is called, is that your view is being released and any view resources should be freed.
So, you only need to free view related items.
In your case it looks like you'd only need to free the UILabels that are probably in your view. If they were marked as IBOutlets and not in assign properties, you'd want to release the memory used by them:
self.pointLabel = nil;
self.accelerometerLabel= nil;
self.headingLabel= nil;
That also means, that in viewDidLoad if you are setting up the other properties you want to make sure they are not being allocated again if they are there already as it can be called again if the view is unloaded and then reloaded again.
The reason this would be called is if the view controller received a memory warning. You can test this memory warning in the simulator to see how viewDidUnload and viewDidLoad are called.
You don't have to, and if you run this, you'll be wasting some substantial execution time. Using the property method to set a property to nil is the same thing as releasing the property, with the caveat that some extra stuff may or may not happen, depending on how you've set up the setter methods.
So let's walk through this code. At the end of your viewDidUnload method, all of your properties are now nil. The object is then deallocated, and your object attempts to release a dozen nil objects or so. Now, the Objective-C runtime is pretty smart, and if you send a message to nil, (surprise surprise) nothing will happen.
So you've basically got a dozen lines that do absolutely nothing.
no, you shouldn't.
if you do as if the above code, you are wasting effort.
By setting them to nil in viewDidUnload, they will be going thru a process of release and retain automatically, which means, by the time the code get to dealloc, they are actually released and nil, and you are doing another release there for the nil.
Releasing nil object might be erratic.
So, ignore those in viewDidUnload.