我编写了Singleton类来管理iAd。用户闲置5秒钟后,iAd会弹出。 idleTimerExceeded 调用会生成一个通知,以显示iAd。这段代码可以很好地满足我的要求,但是由于我不熟悉iOS开发,因此在集成了此代码后,我的应用程序有时会意外挂起。该代码会导致许多警告等。我想在内存和性能方面优化我的代码。

非常感谢您的建议和评论。

下面是我的代码:

iAdSingleton.h

#import <Foundation/Foundation.h>
#import "AppDelegate.h"
#import "iAd/iAd.h"

@interface iAdSingleton : UIViewController<ADBannerViewDelegate> {
    ADBannerView *adView;
    UIViewController *displayVC;
    NSTimer *idleTimer;
    BOOL isItFirstTime;
}
@property (nonatomic, retain) ADBannerView *adView;
@property (nonatomic, retain) UIViewController *displayVC;
@property (nonatomic) BOOL isItFirstTime;

+ (id) shareAdSingleton;
- (void) resetIdleTimer;
- (void) idleTimerExceeded;

@end

iAdSingleton.m
#import "iAdSingleton.h"

@implementation iAdSingleton

static iAdSingleton* _sharedAdSingleton = nil;

BOOL bannerVisible = NO;
BOOL controlAccessBannerVisibility = NO;
@synthesize adView, displayVC;
@synthesize isItFirstTime;

#define kMaxIdleTimeSeconds 5.0

+(id)sharedAdSingleton
{
    @synchronized(self)
    {
        if(!_sharedAdSingleton)
            _sharedAdSingleton = [[self alloc] init];
        return _sharedAdSingleton;
    }
    return nil;
}

+(id)alloc
{
    @synchronized([iAdSingleton class])
    {
        NSAssert(_sharedAdSingleton == nil, @"Attempted to allocate a second instance of a singleton.");
        _sharedAdSingleton = [super alloc];
        return _sharedAdSingleton;
    }

    return nil;
}

-(id)init
{
    self = [super init];
    if (self != nil) {

    /*                  Initialize The Parameters Over Here                  */

        //adView = [[ADBannerView alloc] initWithFrame:CGRectMake(0, 480, 0, 0)];
        adView = [[ADBannerView alloc] init];
        adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
        self.adView.delegate=self;
        [self resetIdleTimer];
    }
    return self;
}

-(void)dealloc
{
    displayVC = nil;
    if (adView) {
        [adView removeFromSuperview]; //Remove ad view from superview
        [adView setDelegate:nil];
        adView = nil;
    }
    [super dealloc];
}

-(UIViewController *)viewControllerForPresentingModalView
{
    return displayVC;
}

- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
    banner.hidden = NO;
    if(!bannerVisible){
        NSLog(@"Banner Changes 1 - Purpose: Visibility");
        // [UIView beginAnimations:@"bannerAppear" context:NULL];
        // banner.frame = CGRectOffset(banner.frame, 0, -100);
        // [UIView commitAnimations];
        bannerVisible = YES;
        controlAccessBannerVisibility = YES;

    }
}

- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
    //NSLog(@"Unable to receive Ad.");
    NSLog(@"Banner Changes 2 - Purpose: Unable to Receive Ad.");
    banner.hidden = YES;
    if(bannerVisible){
        [UIView beginAnimations:@"bannerDisappear" context:NULL];
        banner.frame = CGRectOffset(banner.frame, 0, 100);
        [UIView commitAnimations];
        bannerVisible = NO;
    }
}

- (BOOL) bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave
{
    NSLog(@"Pause anything necessary");
    return YES;
}

- (void) bannerViewActionDidFinish:(ADBannerView *)banner
{
    NSLog(@"We now resume to normal operations");
}

- (void)resetIdleTimer {

    if (!idleTimer) {
        idleTimer = [[NSTimer scheduledTimerWithTimeInterval:kMaxIdleTimeSeconds
                                                      target:self
                                                    selector:@selector(idleTimerExceeded)
                                                    userInfo:nil
                                                     repeats:NO] retain];
    }
    else {
        if (fabs([idleTimer.fireDate timeIntervalSinceNow]) < kMaxIdleTimeSeconds-1.0) {
            [idleTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:kMaxIdleTimeSeconds]];
            /*
             Notification: HideAd
             */

            NSLog(@"Notification Generated For HideAd");
            [[NSNotificationCenter defaultCenter] postNotificationName:@"HideAdBanner" object:nil userInfo:nil];

        }
    }
}

- (void)idleTimerExceeded {

    AppDelegate *appDel = (AppDelegate *)[[UIApplication sharedApplication] delegate];

    if (appDel.adVisible == NO) {
        NSLog(@"Notification Generated For ShowAd");

        /*
         Notification: ShowAd
         */

        if (controlAccessBannerVisibility == YES) {
            [[NSNotificationCenter defaultCenter] postNotificationName:@"ShowAdBanner" object:nil userInfo:nil];
        }
    }
}

@end

最佳答案

这就是你所需要的。该代码是线程安全的,并且不会有任何内存问题和警告。

+ (iAdSingleton *) sharedInstance
{
    static dispatch_once_t onceToken;
    static iAdSingleton * __sharedInstance = nil;

    dispatch_once(&onceToken, ^{
        __sharedInstance = [[self alloc] init];
    });

    return __sharedInstance;
}

10-08 05:24