PDA

View Full Version : ADBannerView in UINavigation's RootController



boboc
03-26-2011, 08:29 PM
Am si eu o mica/mare problema.
Vreau sa folosesc un ADBannerView in root controller-ul unei aplicatii navigation based.
Am luat proiectul iAdSample de la Apple iar acolo se recomanda ca banner-ul sa fie pus in app delegate,lucru facut si de mine.
Aplicatia mea are un root controller si inca 5 custom controlere (Inbox,Today,Scheduled,Someday si Logbook).
Implementarea folosita atat in root controller cat si in celelalte controlere este aceasi,ce-a atasata.
Problema mea este urmatoarea:

Cand aplicatia porneste prima data,root controller-ul afisaza banner-ul corect.
Daca selectez orice sectiune,ex Inbox se apeleaza didSelectRowAtIndexPath: iar Inbox Controller este afisat,iar aici banner-ul este tot ok.
Problema apare cand ma intorc in root controller,baner-ul nu mai apare,am verificat cu NSLog si banner-ul este nil. (vedeti imaginile 1,2 si 3).

Partea ce-a mai ciudata este ca,daca fac acelasi lucru din Inbox controller selectand un rand, se apeleaza didSelectRowAtIndexPath iar Edit task controller este afisat iar cand ma intorc inapoi in Inbox controller baner-ul apare si nu este nil ca in root Controller,lucru verificat din nou cu NSLog. (vedeti imaginile 4,5 si 6).



#define SharedAdBannerView ((myAppDelegate *)[[UIApplication sharedApplication] delegate]).adBanner


- (void)viewDidLoad {
[super viewDidLoad];

NSLog(@"viewDidLoad called");
[self createADBannerView];

[self layoutBanner: NO];
}


- (void) viewWillAppear:(BOOL)animated
{
NSLog(@"viewWillAppear called");

ADBannerView *theBanner = (ADBannerView *)[self.view viewWithTag: 1000];
NSLog(@"theBanner value: %@",theBanner);

[self layoutBanner: NO];
}


- (void) viewDidUnload
{
[super viewDidUnload];

ADBannerView *adBanner = SharedAdBannerView;
adBanner.delegate = nil;
[adBanner removeFromSuperview];
}


- (void)dealloc {

ADBannerView *adBanner = SharedAdBannerView;
adBanner.delegate = nil;
[adBanner removeFromSuperview];

[super dealloc];
}


#pragma mark -
#pragma mark ADBanner Methods


- (void)createADBannerView
{
ADBannerView *adBanner = SharedAdBannerView;

NSString *contentSize = ADBannerContentSizeIdentifierPortrait;

CGRect frame;
frame.size = [ADBannerView sizeFromBannerContentSizeIdentifier:contentSize];
frame.origin = CGPointMake(0.0f, CGRectGetMaxY(self.view.bounds));
adBanner.frame = frame;
adBanner.delegate = self;
adBanner.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleTopMargin;
adBanner.requiredContentSizeIdentifiers = [NSSet setWithObjects:ADBannerContentSizeIdentifierPortra it,nil];

// added a tag to check with NSLog in the viewWillAppear method if the banner is nil when i pop back
adBanner.tag = 1000;
[self.view addSubview:adBanner];
}


- (void)layoutBanner:(BOOL)animated
{
ADBannerView *adBanner = SharedAdBannerView;

CGFloat animationDuration = animated ? 0.5f : 0.0f;
adBanner.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;

CGPoint bannerOrigin = CGPointMake(CGRectGetMinX(self.view.bounds), CGRectGetMaxY(self.view.bounds));
CGFloat bannerHeight = adBanner.bounds.size.height;

if (adBanner.bannerLoaded)
{
bannerOrigin.y -= bannerHeight+44;
}
else
{
bannerOrigin.y += bannerHeight+44;
}

[UIView animateWithDuration: animationDuration animations:^{
adBanner.frame = CGRectMake(bannerOrigin.x, bannerOrigin.y, adBanner.frame.size.width, adBanner.frame.size.height);
}];
}


- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
NSLog(@"bannerViewDidLoadAd called");
[self layoutBanner:YES];
}


- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
NSLog(@"didFailToReceiveAdWithError called");
[self layoutBanner:YES];
}

253
- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave
{
return YES;
}

boboc
03-26-2011, 08:31 PM
imaginile 4 5 si 6 sunt urmatoarele

257258259

StaS
03-28-2011, 02:44 PM
E normal,

In dealoc ii faci un release banerului , desi nu'ti apartine.
Cand un controller este eliminat din navigation stack , primeshte un release (si eventual dealoc) , tu in dealoc faci un release banerului din AppDelegate (nu'i apartine controlerului actual)

Sau nu faci release, sau iti creezi un baner nou in fiecare controller.

boboc
03-28-2011, 02:55 PM
Unde ai vazut ca am apelat release pe banner? :)
In dealloc doar am setat delegate = nil pentru ca nu vreau acest controller sa apeleze metodele delegate cand banner-ul se incarca si cand da eroare.
Dupa mine as fi creat cate un baner separat in fiecare controller dar apple nu recomanda asta pentru ca dureaza ceva pana se incarca,ei recomand ca banerul sa fie creat in app delegate.

StaS
03-28-2011, 02:58 PM
Unde ai vazut ca am apelat release pe banner? :)

AdBanner inherits from UIView , daca nui faci retain la banner , removeFromSuperview duce la releas'ul acestuia.

boboc
03-28-2011, 03:08 PM
Asta stiu,cand folosesc addSubview: retainCount-ul va fi +1 iar la removeFromSuperview: retainCount-ul va fi -1.baner-ul in sine este alocat in appDelegate,deci el exista tot timpul nh este dealocat.
Problema este ca viewDidLoad in root controller se apeleaza doar o singura data,iar in inbox controller viewDidLoad se apeleaza de cate ori il accesez.
Ce nu inteleg eu e urmatorul lucru,de ce doar in rootController banner-ul dispare si cu aceasi implementare in inbox controller nu dispare ?
Si in inbox apelez removeFromSuperview: si daca selectez alt cell (edit task controller) iar apoi revin in inbox baner-ul e acolo,inca odata,cu aceasi implementare.
Poate imi scapa ceva legat de modul cum functioneaza navigation controller dar eu stiu ca atata timp cat un controller creaza alt controller acesta va sta in memorie garantat atata timp cat controller-ul creat ulterior pentru ca il detine.

StaS
03-28-2011, 03:21 PM
pai atunci de ce nu pui [self createADBannerView]; in viewWillAppear?

controller creaza alt controller acesta va sta in memorie garantat atata timp cat controller-ul creat ulterior pentru ca il detine. - nu'l detine cel care la creat , il detine navigationController'u, si oricare dintre ele pot primi un unload in conditii de insufucienta de memorie

boboc
03-28-2011, 03:28 PM
Ah,chiar acum mi-am amintit,nav controller-ul are un root controller iar root-ul devine controller-ul pozitionat cel mai sus pe stack,restul primesc unload.
Chestia cu parent-child controller e valabila pentru un controller simplu.
O varianta cred ca as putea in root sa atribui un tag la banner cand il pun ca subview la self.view apoi in viewWillAppear sa verific if([self.view viewWithTag: 100] == nil) su sa creez banerul.

boboc
03-28-2011, 09:57 PM
Daca pun in viewWillAppear urmatorul cod merge totul ok:


if([self.view viewWithTag: 1000] == nil)
[self createADBannerView];


Singura faza care nu o inteleg este de ce in rootController baner-ul dispare si in inbox nu? Mai ales ca dealloc nu este apelat(verificat cu NSLog) si nici viewDidUnload(aceasta stiu ca se apeleaza automat cand apare un memory warning).

boboc
03-28-2011, 10:38 PM
Ah,aici raspunsul e simplu,cum un view nu poate avea decat un singur superView din cauza asta dispare din rootController :)