iPhone app crashes with admob? - iphone

I am having an iphone app with admob on two screens's viewdidLoad
My code is:
AbMob =[[GADBannerView alloc]initWithFrame:CGRectMake(0.0,self.view.frame.size.height-195, 320, 50)];
AbMob.adUnitID = AdMob_ID;
AbMob.rootViewController = self;
[self.view addSubview:AbMob];
GADRequest *r = [[GADRequest alloc] init];
r.testing = NO;
[AbMob loadRequest:r];
Problem is this code works fine on one screen but crashes on other screen with error
* -[GADOpener didOpen]: message sent to deallocated instance
0x6074750
Can anybody tell me what could be the problem

You have a retain/release problem somewhere in your code. You say it works in one view, but not another - this makes me believe that you are storing this instance outside of your view controllers. The message sent to deallocated instance issue is due to you trying to use a variable that has been removed from memory somewhere in the code before this error pops up. You need to ensure that the view controller that is creating this object is properly retaining it so that it does not get deallocated before you need to use it again with:
GADBannerView *_adMobBannerView;
#property(nonatomic,retain) GADBannerView *adMobBannerView; //view controller retains object when using self.adMobBannerView = bla
It sounds like you may need to brush up on your memory management documentation, but the gist of it is that anywhere you are calling alloc, you are managing that memory and need to call release when you are done with it. If you need a variable to stick around for longer than an autoreleased object is living for, then you need to create an instance variable and retain the object yourself with ivar properties #property (nonatomic, retain).

Related

iphone - Message sent to deallocated instance in a block

I have this property called mySegmented, declared like this
.h
#property (retain) UISegmentedControl *mySegmented;
.m
#synthesize mySegmented = _mySegmented;
then, it was created like this:
self.mySegmented = [self createSegmented];
// createSegmented creates an autoreleased segmented control
My app has 3 different segmented controls. Just one appears at a given time.
At some point of my app, I have to hide one particular segmented control, so, what I do is to build an array of all segmented controls and iterate... this is inside a block.
[UIView animateWithDuration:0.8
animations:^{
NSArray *list = [NSArray arrayWithObjects:
self.mySegmented1,
self.mySegmented2,
self.mySegmented3,
nil];
for (UISegmentedControl *oneSeg in list) {
[oneSeg setAlpha:0.0f];
}
}];
what happens is: after some time, the app crashes while trying to build this array. I suppose one of the segmented controls is deallocated somehow. No deallocation that I can see in code.
My question is: this array being created is autoreleased. What happens when the block finishes the animation? is a release sent to each member of the array?
If I retain the segmented control after creating it, Xcode complains it will leak.
any clues?
thanks.
Please retain like you tried, but make sure to release them in the dealloc method, Xcode should not complain that way.
Your array is also autoreleased inside the block but that's fine, the array doesn't own the references inside of it, the real problem is the segmented controls not being retained by your view controller.
Let me know how it goes.

Why assign nil to IBOutlets in viewDidUnload?

I have a UIViewController that has an IBOutlet for a UILabel with the label wired up in the XIB.
#import <Foundation/Foundation.h>
#interface MyViewController : UIViewController {
IBOutlet UILabel *aLabel;
}
#end
According to iOS Programming: The Big Nerd Ranch Guide (2nd Edition) chapter 7
When [MyViewController] reloads its view, a new UILabel instance is created from the XIB file.
Thus it recommends releasing the label in viewDidUnload.
- (void)viewDidUnload {
[super viewDidUnload];
[aLabel release];
aLabel = nil;
}
Being a C# programmer, I've had it drummed into me that assigning nil/null to things is pointless. While I can see it makes more sense in Objective-C, it still grates my sense of code aesthetic slightly*. I removed it and it all worked fine.
However, when I tried to do a similar thing with MKMapView the application errors EXC_BAD_ACCESS while trying to load the NIB.
#import <Foundation/Foundation.h>
#interface MyViewController : UIViewController {
IBOutlet MKMapView *mapView;
}
#end
- (void)viewDidUnload {
[super viewDidUnload];
[mapView release];
mapView = nil; // Without this line an exception is thrown.
}
Why is there an error when mapView is not set to nil, but not when aLabel is not set to nil?
* I realise I need to adjust my sense of code aesthetic for the new language, but it takes time.
It turns out I was just flat out wrong about aLabel not being referenced. Not sure what made me think it wasn't.
However, that still leaves the question of why they're being referenced while the NIB is being loaded.
When the field or property is set, a release message is sent to the old value (either the synthesized properties set method sends the release message, or setValue:forKey: sends the message if it's a field). Because the old value has already been released, this results in EXC_BAD_ACCESS.
It's because of memory management, specifically the lack of garbage collection.
In C# (as you know) objects that are no longer in scope are removed. In objective-c, that doesn't happen. You have to rely on retain/release to tell the object when you are done with it.
There's a drawback to the objective-c reference counting method that your mapView bug exhibits. Calling release on an object might result in it being deallocated. However, your pointer to the object will still point to the same place - your object just won't be there anymore.
For example
// We create an object.
MyObject *object = [[MyObject alloc] init];
// At this point, `object` points to the memory location of a MyObject instance
// (the one we created earlier). We can output that if we want :
NSLog(#"0x%08X", (int)myObject);
// You should see a number appear in the console - that's the memory address that
// myObject points to.
// It should look something like 0x8f3e4f04
// What happens if we release myObject?
[myObject release];
// Now, myObject no longer exists - it's been deallocated and it's memory has been
// marked as free
// The myObject pointer doesn't know that it's gone - see :
NSLog(#"0x%08X", (int)myObject);
// This outputs the same number as before. However, if we call a method on myObject
// it will crash :
NSLog(#"%#", myObject);
In objective-c, if you try to call a message on nil, nothing happens. So if each time you are finished with an object and call release on it, you should also set it to nil - this means that if you try to use that pointer again, it won't crash!
viewDidUnload is usually called when the device receives a memory warning.
In the View stack there may be situations where the device can free up memory by releasing objects that aren't in use. Imagine you have a navigation stack with a number of view controllers. The interface view controllers lower on the stack are not accessible but are still using up memory. So its usually a good idea to nil out any interface elements that can't be accessed. These will then be reloaded with viewDidLoad when needed.
Generally in ViewDidUnload you should release any view objects that are created from a Nib file or allocated in your ViewDidLoad method
Your mapView is throwing an exception because your view controller is trying to access to MapView but the mapView has been released. When you set the outlet to nil any messages sent to it are ignored.

several questions about obj-c (delegate, viewController, simulator)

i had several questions about objective-c, could you help me understand it? Here they are :
why do we use sometimes :
self.myView.delegate = self; ?
There is the same thing with the Ipad and Splitview : why do we use the delegate explicitly like this :
uisplitviewController *svc = ...
svc.delegate = pvc.otherViewController;
For now, i understand the "appDelegate", but what about this delegate method?
2.I saw several times the use of another "viewController" as below, instead of "allocating" directly the "mainViewControler", why do we use this intermediate?
MainViewController *viewController = [[MainViewController alloc] initWithNibName:#"MainView" bundle:nil];
self.mainViewController = viewController;
[viewController release];
3.Following some tutorials from appsmuck.com, i saw that they use :
"(void)loadFlipsideViewController "
but no "loadView", so, can we replace the "View" with the controller view?
4.Finally, i can switch from "iphone" Simulator to "ipad" simulator, but i always get the ipad simulator each time i build the projet, is there a way to always let the "iphone" simulator to be the simulator by default?
And that's it. :) Thanks for your help
Paul
1 . Delegation Design Pattern
The delegation design pattern is a way
of modifying complex objects without
subclassing them. Instead of
subclassing, you use the complex
object as is and put any custom code
for modifying the behavior of that
object inside a separate object, which
is referred to as the delegate object.
At predefined times, the complex
object then calls the methods of the
delegate object to give it a chance to
run its custom code.
2 . The reason for creating another viewController is for memory management. It can be done in one line but then you will be needlessly adding an object to the autorelease pool.
//Now the autorelease pool has to track this object
self.mainViewController = [[[MainViewController alloc] initWithNibName:#"MainView" bundle:nil] autorelease];
3 . -(void)loadView is inherited from UIViewController so no you can not just change it to loadViewController because that will just create a custom method. That is exactly what (void)loadFlipsideViewController is trying to accomplish and by the name of it it should load a new view controller and display it using a flip animation.
4 . In XCode 4 you need to set the scheme to the correct simulator.
First of all, it's going to me MUCH easier to get answers if you break all these queries up into separate questions. You're going to have a hard time picking an answer that answers them all best.
That said, I'll give #1 a shot.
Many types of objects in Cocoa (and Cocoa Touch) send messages. Some, like NSFetchedResultsController send messages when their contents change. Some, like UITableViewController, send a message when a table cell is touched. These messages have to GO somewhere. They can't be sent just "out there" or nothing will ever hear them. These messages need a destination. In Cocoa, the destination for these messages is called the "delegate." As in, "I designate this object to be my delegate, and receive my messages."
If you are in a viewController that is controlling a UITableView, very often is makes sense to simply specify "self" as the delegate. That is saying, in effect, hey, Mr. UITableView, just send your messages to me, I'll handle them. In turn, your viewController must declare (in the .h) that they conform to the UITableViewDelegate protocol, and then the required methods in that protocol must be implemented in your .m.
This is a VERY common pattern in Cocoa. Don't proceed until your understand it.
For delegate you can check use of Delegate in iphone sdk. I have a long answer there.
#property (nonatomic, retain) MyClass *obj;
MyClass *tmpObj = [[MyClass alloc] init];
self.obj = tmpObj;
[tmpObj release];
Let's see what happens here. [MyClass alloc] allocates an object and you have retain count of 1. In the next line you are calling the setter which also retains. So you are increasing the retain count. Naturally you will release this property later, may be in dealloc. So now you are owner of this object 2 times. To match the first ownership via alloc you release in the 3rd line.
Now see what happens if you do this in one line:
self.obj = [[MyClass alloc] init];
You have gained ownership here two times, one through alloc and one through retain property. So you need to write [obj release] twice. Otherwise you will have a memory leak. But releasing twice is confusing and easier to create bug and you should never do this. Or you need to autorelease this in the same line which is also confusing.
So the summary is if you have retain property, then write three lines of code to handle with double ownership.
Sorry, can't help with other parts.

Facebook FBConnect fbDialogLogin method in Facebook.m hits EXC_BAD_ACCESS on FBSessionDelegate object _sessionDelegate

using facebook-facebook-ios-sdk-cf1c2c3, the _sessionDelegate object is being deallocated before my app is moved to the background.
This means when the app comes to the foreground after the authentication/authorization callback, this method in Facebook.m hits causes a EXC_BAD_ACCESS:
- (void)fbDialogLogin:(NSString *)token expirationDate:(NSDate *)expirationDate
The offending line in that method being this one:
if ([self.sessionDelegate respondsToSelector:#selector(fbDidLogin)]) {
[_sessionDelegate fbDidLogin];
}
I think this is because in Facebook.h, _sessionDelegate is being assigned not retained. Therefore at some point it is deallocated:
#property(nonatomic, assign) id<FBSessionDelegate> sessionDelegate;
Changing it to retain appears to resolve the problem:
#property(nonatomic, retain) id<FBSessionDelegate> sessionDelegate;
Seems like too obvious a thing to me. Therefore I must be missing something!
Any ideas?
Many thanks,
xj
Changing the delegate to a retain method in this case is probably a more stable solution than anything else. However somewhere your delegate is being released before you want it to be released and you may need to look into what would cause it to be released early. However if you do this make sure you edit the Facebook.m dealloc() method to release your delegate
I had same EXC_BAD_ACCESS problem.i resolved it by removing other allocated instance of rootViewController.
RootViewController *rootViewController = [[RootViewController alloc] init]; <--------
facebook = [[Facebook alloc] initWithAppId:kAppId andDelegate:rootViewController];
it should be allocated only once.
that means if you are again allocating your rootViewController and pushing/adding it another viewController it retains its previous instance.
Hope it helps to resolve EXC_BAD_ACCESS.
In calling page you must disable ARC!

addSubview of UIViewController, view gets over released

EDIT:
Solved the problem myself. Turned out it was a leftover in the dealloc method that caused a UIButton to be released twice...
I'm trying to display a UIViewController on top of another UIViewController like a popup. Problem is that the view seems to be getting overreleased. With NSZombieEnabled, I get the following error:
[CALayer release]: message sent to deallocated instance 0x784bf40
I use this code to add the view:
//self.someViewController is declared as (nonatomic, retain)
self.someViewController = [[[SomeViewController alloc] initWithDelegate:self] autorelease];
[self.view addSubview:self.someViewController.view];
Then later on, I remove the view like this:
[self.someViewController.view removeFromSuperview];
self.someViewController = nil;
Should earlier comments not solve this perhaps this may help. I'm assumning you've created your someViewController property like this
#property (nonatomic, retain) NSViewController* someViewController;
in which case I believe your code is correct (at least I can see how it should work) and you might be seeing a secondary crash here.
I.e. when you're calling
self.someViewController = nil;
this should be freeing the memory up immediately (assuming a frame has gone by where the VC exists so the autoreleased count has already been decreased). Therefore if you have ANOTHER object being used in that someViewController VC who still exists and has a delegate set to your someViewController object and is doing a background task it will cause a crash when it trys to call back to your now deallocated object. (If you don't free your VC you wouldn't see this crash)
For example if you have a MKMapKit being displayed in someViewController and the delegate is set to someViewController... if you have implemented the method in someViewController
mapViewDidFinishLoadingMap:(MKMapView*)mapView
the MKMapKit may still be calling this from another thread if you haven't destroyed MKMapView object before yours.
I would always set other object delegates pointing to your VC (like MKMapView) to nil before destroying the said VC it uses to avoid this risk. For PDF rendering (CALayer?) you may find you need to explicitly release the object too given this uses a different memory alloc/free paradigm.
Solved the problem myself. Turned out it was a leftover in the dealloc method that caused a UIButton to be released twice...