At present, many apps in the market (such as Taobao, Meituan, Weibo, UC) will display advertisements for several seconds after the loading of the launch picture. There is a skip button in the upper right corner to skip the advertisement immediately. Some apps will enter an advertisement page after clicking the advertisement page. They are never tired of playing, and the product wang will not let go of this effect:

Here’s the idea:

  1. Encapsulate the AD page and display the skip button to realize the countdown function. 2. Determine whether the AD page is updated. Asynchronously download the new picture and delete the old picture 3. Display the AD page 4. Display the AD page after clicking

Without further ado, here is the core code:

Encapsulate the AD page and display the skip button to realize the countdown function

Zladvertview. h: Encapsulate the advertising page first, exposing the method of displaying the advertising page and the picture path

#import <UIKit/UIKit.h>

#define kscreenWidth [UIScreen mainScreen].bounds.size.width
#define kscreenHeight [UIScreen mainScreen].bounds.size.height
#define kUserDefaults [NSUserDefaults standardUserDefaults]
static NSString *const adImageName = @"adImageName";
static NSString *const adUrl = @"adUrl"; @interface ZLAdvertView: UIView /** * - (void)show; / / @property (nonatomic, copy) NSString *filePath; @endCopy the code

ZLAdvertView.m:

The core code is shown in the following code block:

#import "ZLAdvertView.h"@interface ZLAdvertView () @property (nonatomic, strong) UIImageView *adView; @property (nonatomic, strong) UIButton *countBtn; @property (nonatomic, strong) NSTimer *countTimer; @property (nonatomic, assign) int count; Static int const showtime = 3;Copy the code

1. Add a click gesture to the AD page to jump to the AD page.

@implementation ZLAdvertView

- (NSTimer *)countTimer {
    
    if(! _countTimer) {_countTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target: self selector: @ the selector (countDown) userInfo:nil repeats:YES]; }return _countTimer;
}

- (instancetype)initWithFrame:(CGRect)frame {
    
    if(self = [super initWithFrame:frame]) { // 1. Adview = [[UIImageView alloc] initWithFrame:frame]; _adView.userInteractionEnabled = YES; _adView.contentMode = UIViewContentModeScaleAspectFill; _adView.clipsToBounds = YES; // Add a click gesture to the AD page, UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self Action :@selector(pushToAd)]; [_adView addGestureRecognizer:tap]; // 2. Skip button CGFloat btnW = 60; CGFloat btnH = 30; _countBtn = [[UIButton alloc] initWithFrame:CGRectMake(kscreenWidth - btnW - 24, btnH, btnW, btnH)]; [_countBtn addTarget:self action:@selector(removeAdvertView)forControlEvents:UIControlEventTouchUpInside];
        [_countBtn setTitle:[NSString stringWithFormat:@"Skip % d", showtime] forState:UIControlStateNormal];
        _countBtn.titleLabel.font = [UIFont systemFontOfSize:15];
        [_countBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; _countbtn. backgroundColor = [UIColor colorWithRed: 38/255.0 green: 38/255.0 blue: 38/255.0 alpha:0.6]; _countBtn.layer.cornerRadius = 4; [self addSubview:_adView]; [self addSubview:_countBtn]; }return self;
}

- (void)setFilePath:(NSString *)filePath {
    
    _filePath = filePath;
    _adView.image = [UIImage imageWithContentsOfFile:filePath];
}

- (void)pushToAd {
    
    [self removeAdvertView];
    
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ZLPushToAdvert" object:nil userInfo:nil];
}
Copy the code

2. The countdown function of the skip button on the AD page can be realized by timer or GCD (here is an example of 3s countdown AD)

- (void)countDown {
    
    _count --;
    [_countBtn setTitle:[NSString stringWithFormat:@"Skip % d",_count] forState:UIControlStateNormal];
    if(_count == 0) { [self removeAdvertView]; }} // the countdown function can be done by timer or GCD - (void)show {// countdown method 1: GCD // [self startCoundown]; // Countdown method 2: timer [self startTimer]; UIWindow *window = [UIApplication sharedApplication].keyWindow; [window addSubview:self]; } // Timer countdown - (void)startTimer {_count = showtime; [[NSRunLoop mainRunLoop] addTimer:self.countTimerforMode:NSRunLoopCommonModes]; } // GCD countdown - (void)startCoundown {__weak __typeof(self) weakSelf = self; __block int timeout = showtime + 1; Dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue); Dispatch_source_set_timer (_timer,dispatch_walltime(NULL, 0),1.0 * NSEC_PER_SEC, 0); // Dispatch_source_set_event_handler (_timer, ^{if(timeout <= 0){// Countdown ends, close dispatch_source_cancel(_timer); dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf removeAdvertView]; }); }else{
            
            dispatch_async(dispatch_get_main_queue(), ^{
                [_countBtn setTitle:[NSString stringWithFormat:@"Skip % d",timeout] forState:UIControlStateNormal]; }); timeout--; }}); dispatch_resume(_timer); } // removeAdvertView - (void)removeAdvertView {// stop timer [self.countTimer invalidate]; self.countTimer = nil; [UIView animateWithDuration:0.3f animations:^{self.alpha = 0.f;  } completion:^(BOOL finished) { [self removeFromSuperview]; }]; } @endCopy the code

### 2. Determine whether the AD page is updated. Asynchronously download the new picture, delete the old picture because the content of the AD page should be displayed in real time, in no network state or slow network speed can not be delayed loading, or wait until the home page appears to load the AD page. Therefore, instead of using the network advertising interface to obtain the image address and then load the image, the image is asynchronously downloaded to the local, and the image name is saved. Every time you open the APP, you will find whether the image exists in the sandbox according to the image name stored locally. If so, the advertisement page will be displayed. In the AppDelegate. M:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[HomeViewController alloc] init]]; [self.window makeKeyAndVisible]; [self setupAdvert];return YES;
}
Copy the code

1. Check whether there is an advertisement image in the sandbox. If so, display it directly

/** * setupAdvert {// 1. To determine whether a sandbox is advertising pictures, if present, directly display nsstrings * filePath = [self getFilePathWithImageName: [kUserDefaults valueForKey: adImageName]]. BOOL isExist = [self isFileExistWithFilePath:filePath];if(isExist) {/ / picture there ZLAdvertView * advertView = [[ZLAdvertView alloc] initWithFrame: self. Window. The bounds]; advertView.filePath = filePath; [advertView show]; } // 2. Call the advertising interface again regardless of whether there is an advertising image in the sandbox and check whether the AD is updated [self getAdvertisingImage]; } /** * checks whether the file exists */ - (BOOL)isFileExistWithFilePath:(NSString *)filePath {NSFileManager *fileManager = [NSFileManager defaultManager]; BOOL isDirectory = FALSE;return [fileManager fileExistsAtPath:filePath isDirectory:&isDirectory];
}
Copy the code

2. No matter whether there is an advertisement image in the sandbox, you need to call the interface to get the advertisement again to check whether the advertisement is updated

/** * initialize advertising page */ - (void)getAdvertisingImage {// TODO request advertising interface // This should have used advertising interface, Now use some fixed web image URL instead of NSArray *imageArray = @[@"https://ss2.baidu.com/-vo3dSag_xI4khGko9WTAnF6hhy/super/whfpf%3D425%2C260%2C50/sign=a4b3d7085dee3d6d2293d48b252b5910/0e 2442a7d933c89524cd5cd4d51373f0830200ea.jpg"The @"https://ss0.baidu.com/-Po3dSag_xI4khGko9WTAnF6hhy/super/whfpf%3D425%2C260%2C50/sign=a41eb338dd33c895a62bcb3bb72e47c2/5f df8db1cb134954a2192ccb524e9258d1094a1e.jpg"The @"http://c.hiphotos.baidu.com/image/w%3D400/sign=c2318ff84334970a4773112fa5c8d1c0/b7fd5266d0160924c1fae5ccd60735fae7cd340 d.jpg"]; NSString *imageUrl = imageArray[arc4random() % imageArray.count]; / / get photo name: p5122z60 43-130-50. JPG NSArray * stringArr = [imageUrl componentsSeparatedByString: @"/"]; NSString *imageName = stringArr.lastObject; / / stitching sandbox path nsstrings * filePath = [self getFilePathWithImageName: imageName]; BOOL isExist = [self isFileExistWithFilePath:filePath];if(! IsExist) {/ / if the picture does not exist, then delete the old pictures, download new images [self downloadAdImageWithUrl: imageUrl imageName: imageName]; }}Copy the code

3. Asynchronously download new images and delete old ones

/** * download new image */ - (void)downloadAdImageWithUrl:(NSString *)imageUrl imageName:(NSString *)imageName { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]]; UIImage *image = [UIImage imageWithData:data]; NSString *filePath = [self getFilePathWithImageName:imageName]; // Save the name of the fileif([UIImagePNGRepresentation(image) writeToFile:filePath atomically:YES]) {// Save successfully NSLog(@"Saved successfully");
            [self deleteOldImage];
            [kUserDefaults setValue:imageName forKey:adImageName]; [kUserDefaults synchronize]; // If there is an AD link, save the AD link as well.else{
            NSLog(@"Save failed"); }}); } /** * deleteOldImage */ - (void)deleteOldImage {NSString *imageName = [kUserDefaults valueForKey:adImageName];if(imageName) { NSString *filePath = [self getFilePathWithImageName:imageName]; NSFileManager *fileManager = [NSFileManager defaultManager]; [fileManager removeItemAtPath:filePath error:nil]; }} / * * * according to the pictures of joining together the file path * / - (nsstrings *) getFilePathWithImageName: (imageName nsstrings *) {if (imageName) {
        
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask, YES);
        NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:imageName];
        
        return filePath;
    }
    
    return nil;
}
Copy the code

### 3. AD page display. The display code for the AD page can be placed in AppDeleate or in the controller on the front page. If the code is in an AppDelegate, you can push the home page to the AD detail page by sending notifications.

Home controller HomeViewController.m:

#import "HomeViewController.h"
#import "ZLAdvertViewController.h"

@interface HomeViewController ()

@end

@implementation HomeViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.title = @"Home page";
    
    self.view.backgroundColor = [UIColor greenColor];
    
   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pushToAd) name:@"ZLPushToAdvert"object:nil]; } - (void)pushToAd {ZLAdvertViewController *adVc = [[ZLAdvertViewController alloc] init]; [self.navigationController pushViewController:adVc animated:YES]; } @endCopy the code

Display the page after clicking on the AD page. If clicking on an AD leads to the AD details page, then the AD link address also needs to be stored in NSUserDefaults. Note: zladvertViewController.h:

// AD link page#import <UIKit/UIKit.h>

@interface ZLAdvertViewController : UIViewController

@property (nonatomic, copy) NSString *adUrl;

@end
Copy the code

ZLAdvertViewController.m :

#import "ZLAdvertViewController.h"

@interface ZLAdvertViewController ()

@property (nonatomic, strong) UIWebView *webView;

@end

@implementation ZLAdvertViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.title = @"Click on the AD link";
    _webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
    _webView.backgroundColor = [UIColor whiteColor];
    
    if(! self.adUrl) { self.adUrl = @"http://www.baidu.com";
    }
    
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:self.adUrl]];
    [_webView loadRequest:request];
    [self.view addSubview:_webView];
}

- (void)setAdUrl:(NSString *)adUrl {
    _adUrl = adUrl;
}
@end
Copy the code

Note: The bottom of the AD page is usually the same as the bottom of the launch image, giving the user the illusion that the AD image is placed on the launch image after the launch image is loaded, and there is no deviation. So we need to remind the artists to pay attention to the advertising art when we develop the key image.

If you need to start the dynamic page skip, please go to: iOS- start the dynamic page skip design ideas