本文介绍了iAd AdBanner内存泄漏问题(应用程序崩溃)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有列表/详细信息视图的简单应用程序.在详细信息视图中,我有1个Web视图,并且还显示了1个iAd.当我在列表/详细视图之间切换时,我的应用有时会崩溃.我的iAd代码似乎有问题.请帮助我修复它.我尝试使用Leaks,但无法完全弄清.

I have a simple app with list/detail view. In the detail view, I have 1 webview and also show 1 iAd. As I toggle between list/detail view, my app crashes sometimes. It seems there is something wrong with my iAd code. Please hlp me fix it.I tried using Leaks, but am unable to figure it out completely.

下面是UPDATED代码;

Below is the UPDATED code;

@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]

推荐答案

您没有发布iAd实例.

You are not releasing your iAd instance.

  1. 为iAd添加实例变量
  2. 确保在卸载视图时将其委托设置为nil.
  3. 确保在卸载视图时将其释放

DetailController接口声明(.h)之内;

Within you DetailController interface declaration (.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实现(.m)之内;

Within you 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

这篇关于iAd AdBanner内存泄漏问题(应用程序崩溃)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-21 20:29
查看更多