2011-12-17 93 views
1

我有一個簡單的應用程序清單/詳細信息視圖。在詳細視圖中,我有1個webview,也顯示1個iAd。當我在列表/詳細視圖之間切換時,我的應用程序有時會崩潰。看來我的iAd代碼有問題。請讓我修復它。 我試過使用泄漏,但無法完全弄清楚。iAd AdBanner內存泄漏問題(應用程序崩潰)

以下是UPDATED代碼;

@interface DetailController : UIViewController <UIWebViewDelegate,ADBannerViewDelegate> { 
    NSString *selectedTxt; 
    IBOutlet UIWebView* webView; 
    ADBannerView *adView_; 
    BOOL bannerIsVisible; 
} 

@property(nonatomic,retain) NSString *selectedTxt; 

@property(nonatomic,retain) UIWebView* webView; 

@property (nonatomic,retain) ADBannerView *adView; 
@property (nonatomic,assign) BOOL bannerIsVisible; 

@end 

實施

@implementation DetailController 

@synthesize selectedTxt; 
@synthesize webView,bannerIsVisible; 
@synthesize adView = adView_; 

/* 
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad. 
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { 
     // Custom initialization 
    } 
    return self; 
} 
*/ 

- (void) viewWillAppear:(BOOL)animated { 

    bannerIsVisible = YES; 
    adView_ = [[ADBannerView alloc] initWithFrame:CGRectZero]; 

    float origin_y; 
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) 
     origin_y = 360.0; 
    else 
     origin_y = self.view.frame.size.height; 

    adView_.frame = CGRectMake(0.0,origin_y, adView_.frame.size.width, adView_.frame.size.height); 

    if (&ADBannerContentSizeIdentifierPortrait != NULL) { 
     adView_.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifierPortrait]; 
     adView_.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait; 
    } else { 
     adView_.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifier320x50]; 
     adView_.currentContentSizeIdentifier = ADBannerContentSizeIdentifier320x50; 
    } 

    adView_.delegate = self; 

    [webView addSubview:adView_]; 

    [self.view bringSubviewToFront:adView_]; 
    self.bannerIsVisible=NO; 

    [super viewWillAppear: animated]; 
} 

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 
- (void)viewDidLoad { 

    //Set the title of the navigation bar 
    //self.navigationItem.title = @"Selected Country"; 
    [super viewDidLoad]; 
} 

/* 
// Override to allow orientations other than the default portrait orientation. 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    // Return YES for supported orientations 
    return YES; 
} 
*/ 

- (void)didReceiveMemoryWarning { 
    // Releases the view if it doesn't have a superview. 
    [super didReceiveMemoryWarning]; 

    // Release any cached data, images, etc that aren't in use. 
} 

- (void)viewDidUnload { 
    [super viewDidUnload]; 
    // Release any retained subviews of the main view. 
    // e.g. self.myOutlet = nil; 
    adView_.delegate = nil; 
    self.adView = nil; 
} 


- (void)dealloc { 
    adView_.delegate = nil; 
    [adView_ release]; 
    [super dealloc]; 
} 



- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error 
{ 
    if (bannerIsVisible) 
    { 
     [UIView beginAnimations:@"animateAdBannerOff" context:NULL]; 
     // assumes the banner view is at the bottom of the screen. 
     banner.frame = CGRectOffset(banner.frame, 0, 50); // if the banner is on top of the screen use -50 
     [UIView commitAnimations]; 
     bannerIsVisible = NO; 
    } 
} 

- (void)bannerViewDidLoadAd:(ADBannerView *)banner 
{ 
    if (!bannerIsVisible) 
    { 
     [UIView beginAnimations:@"animateAdBannerOn" context:NULL]; 
     // assumes the banner view is offset -50 pixels so that it is not visible. 
     banner.frame = CGRectOffset(banner.frame, 0, -50); // if the banner is on top of the screen use 50 
     [UIView commitAnimations]; 
     bannerIsVisible = YES; 
    } 
} 

- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave 
{ 
    NSLog(@"Banner view is beginning an ad action"); 
    BOOL shouldExecuteAction = YES; // your application implements this method if you want it not fixed 
    if (!willLeave && shouldExecuteAction) 
    { 
     // insert code here to suspend any services that might conflict with the advertisement 
    } 
    return shouldExecuteAction; 
} 



@end 

錯誤日誌

2011-12-17 20:33:23.142 MyApp[4382:207] ADBannerView: WARNING A banner view (0x6236190) has an ad but may be obscured. This message is only printed once per banner view. 
[Switching to process 4382 thread 0x920f] 
2011-12-17 20:34:14.154 MyApp[4382:207] -[__NSCFType bannerViewDidLoadAd:]: unrecognized selector sent to instance 0x62542f0 
2011-12-17 20:34:14.195 MyApp[4382:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType bannerViewDidLoadAd:]: unrecognized selector sent to instance 0x62542f0' 
*** Call stack at first throw: 
(
    0 CoreFoundation      0x00e025a9 __exceptionPreprocess + 185 
    1 libobjc.A.dylib      0x00f56313 objc_exception_throw + 44 
    2 CoreFoundation      0x00e040bb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187 
    3 CoreFoundation      0x00d73966 ___forwarding___ + 966 
    4 CoreFoundation      0x00d73522 _CF_forwarding_prep_0 + 50 
    5 CoreFoundation      0x00d72c7d __invoking___ + 29 
    6 CoreFoundation      0x00d72b51 -[NSInvocation invoke] + 145 
    7 CoreFoundation      0x00d73a04 ___forwarding___ + 1124 
    8 CoreFoundation      0x00d73522 _CF_forwarding_prep_0 + 50 
    9 iAd         0x000149f9 -[ADDistributedMessagingCenter messagePort:receivedMessage:withData:] + 251 
    10 iAd         0x00015012 ADMessagePortCallBack + 75 
    11 CoreFoundation      0x00db9f4c __CFMessagePortPerform + 396 
    12 CoreFoundation      0x00de3944 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52 
    13 CoreFoundation      0x00d43cf7 __CFRunLoopDoSource1 + 215 
    14 CoreFoundation      0x00d40f83 __CFRunLoopRun + 979 
    15 CoreFoundation      0x00d40840 CFRunLoopRunSpecific + 208 
    16 CoreFoundation      0x00d40761 CFRunLoopRunInMode + 97 
    17 GraphicsServices     0x033ff1c4 GSEventRunModal + 217 
    18 GraphicsServices     0x033ff289 GSEventRun + 115 
    19 UIKit        0x00300c93 UIApplicationMain + 1160 
    20 MyApp      0x00002440 main + 102 
    21 MyApp      0x000023d1 start + 53 
) 
terminate called after throwing an instance of 'NSException' 
[Switching to process 4382 thread 0x207] 
+0

在gdb命令行(注意,這是試圖爲該委派調用的地址)中執行`po 0x62542f0`。 – Till 2011-12-17 21:22:51

回答

0

您還沒有釋放你的iAd的實例。

  1. 添加一個實例變量的iAd的
  2. 確保卸載視圖時其委託設爲零。
  3. 卸載視圖

當在你DetailController接口聲明確保它被釋放(.H);

@interface DetailController ... 
{ 
    ... 
    //note, we are using an instance variable with the trailing underscore 
    ADBannerView *adView_; 
} 
//note, we are using an accessor without that trailing underscore - those are 
//glued together using the synthesize mechanics within the implementation 
@property (nonatomic,retain) ADBannerView *adView; 
... 
@end 

您內部DetailController implementation(.m);

@implementation DetailController 

//this will glue the instance variable with our property accessor 
@sythesize adView = adView_; 
... 

-(void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    //retained by alloc/init, hence no need for using the retain by the accessor 
    adView_ = [[ADBannerView alloc] initWithFrame:CGRectZero]; 

    //note, in case you want this adbanner to be initialized at a different point, 
    //like for example in viewWillAppear that you have to consider its former instance. 
    //to be on the safe side, you could prefix the above init with a [adView release]; 
    ... 
} 

-(void)viewDidUnload 
{ 
    [super viewDidUnload]; 
    //as always, make sure the delegate is invalidated 
    adView_.delegate = nil; 
    //use accessor mechanics to release and invalidate for convenience 
    self.adView = nil; 
} 

-(void)dealloc 
{ 
    //to be on the safe side, make sure the adview is released even if 
    //viewDidUnload was not called 
    //e.g. nested viewControllers omitting viewDidUnload pass on 

    //as always, make sure the delegate is invalidated 
    adView_.delegate = nil; 
    //do NOT use accessor mechanics within init or dealloc for safety reasons 
    [adView_ release]; 
    [super dealloc]; 
} 
@end 
+0

Thx很多..但我有幾個問題..當你說爲iAd添加一個實例變量,我想你指的是adView ......也間接要求我創建一個屬性併合成它..我也有我的接口聲明爲.... @界面DetailController:UIViewController {...} 那麼我該怎麼辦dealloc或viewDidUnload委託? – testndtv 2011-12-17 12:46:05