iOS | 分化场景下的定期方法

2019-08-16 00:50栏目:IT操作系统

iOS开辟,机械漏刻的行使

在iOS开辟中,大家能够透过三种门路来落到实处定期调用某三个措施的效应。为了方便时期,作者直接在Xcode中写代码以及注释。

先是大家定义二个被定期进行的不二秘技

 

- (void)reloop {
    NSLog(@"循环执行");
}

上面大家分别研讨那三种情势

 

1、使用NSTimer

 

 // 1、使用nstimer创建定时器
    // A.自动加入主循环
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(reloop) userInfo:nil repeats:YES];
    // 激活定时器
    [timer fire];
// 在循环调用时,必须手动释放定时器,否则不必手动释放
    [timer invalidate];



 // B.手动加入主循环
    NSTimer *timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(reloop) userInfo:nil repeats:YES];
    [timer fire];
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

瞩目,由于线程或许会卡住,所以这种方式成立出来的机械漏刻肯呢过会被推移

 

2、使用CADisplayLink

 

// 屏幕刷新时调用
    // CADisplayLink是一个能让我们以和屏幕刷新率同步的频率将特定的内容画到屏幕上的定时器类。CADisplayLink以特定模式注册到runloop后,每当屏幕显示内容刷新结束的时候,runloop就会向CADisplayLink指定的target发送一次指定的selector消息, CADisplayLink类对应的selector就会被调用一次。所以通常情况下,按照iOS设备屏幕的刷新率60次/秒
    // 延迟
    // iOS设备的屏幕刷新频率是固定的,CADisplayLink在正常情况下会在每次刷新结束都被调用,精确度相当高。但如果调用的方法比较耗时,超过了屏幕刷新周期,就会导致跳过若干次回调调用机会。
    // 如果CPU过于繁忙,无法保证屏幕60次/秒的刷新率,就会导致跳过若干次调用回调方法的机会,跳过次数取决CPU的忙碌程度。
    // 使用场景
    // 从原理上可以看出,CADisplayLink适合做界面的不停重绘,比如视频播放的时候需要不停地获取下一帧用于界面渲染。
    // 2.1创建出displaylink对象
    CADisplayLink *displyLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(reloop)];
    // 2.2 将该对象加入循环中
    [displyLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];


    // 2.3再不需要时释放(停止循环)
    [displyLink invalidate];
    displyLink = nil;

3、使用GCD

 

 

// 只执行一次
    double delayInSeconds = 2.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){

        // 执行事件
        [self reloop];
    });


    // 重复执行
    NSTimeInterval period = 1.0; //设置时间间隔
    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), period * NSEC_PER_SEC, 0); //每秒执行
    dispatch_source_set_event_handler(_timer, ^{
        //在这里执行事件
        [self reloop];
    });
    dispatch_resume(_timer);

 

在iOS开采中,大家能够透过两种渠道来促成定期调用某一个主意的效益。为了省事时期,作者一向在Xcode中写代码以及...

在在此之前的支出小说小心NSTimer中的循环引用中介绍了NSTimer会因持有指标对象而孳生内存泄漏以及减轻办法.那篇随笔主要介绍iOS开拓中别的几种达成定期职分的艺术及其优缺点.

公告我们都不生分,其实布告分二种,远程文告和地面公告。

长距离文告是指服务器发出的通报,通过苹果的推送然后达到用户设备。本地布告是指不通过网络,直接设置使用后就足以收到通报了,规范的事例是日历、待办、时钟等利用。

但是就表现模式来讲二者基本均等,都相会世在通报主题,都足以出现在锁屏界面,都能够出今后分界面上部,都得以加上应用上的红点。

ca888会员登录 1

image.png

ca888会员登录 2

image.png

此间小编定期不断发送文告,每趟收到公告都增加到列表中,点击列表能够复制布告内容。

对于本地布告,iOS 10原先和事后分二种完毕格局,这里都放出去。

亟待专注的是,未来在Xcode中使用远程通告功用必要在工程的Targets中的Capabilities标签里展开Push Notification权限,且须求APNS证书,但是本地公告是不必要的,能够平昔测验接收文告。

小说体系
《RACSignal 》
《RACDisposable》
《RACSubject、RACReplaySubject》
《iOS RAC - 基本用法》
《iOS RAC - 定时器》
《iOS RAC - RACMulticastConnection》
《iOS RAC - RACCommand》
《iOS RAC - 宗旨方法bind》
《iOS RAC - 集合RACTuple、RACSequence》
《iOS RAC - rac_leftSelector》
ca888会员登录,《iOS RAC - 映射》
《iOS RAC - 过滤》
《iOS RAC - 登入页面,MVVM》

再谈NSTimer要了然NSTimer专业办法,必要驾驭一下Runloop(这里只是给出描述,后续小说会介绍).Runloop轻松地说就是一个接受管理异步音信事件的循环,该循环中等待事件发生,然后将以那一件事件送到能管理它的地点。

iOS 10之上系统的兑现

iOS 10原先使用UILocalNotification,iOS开首支持叁个新的类库UNUserNotificationCenter,都给了他一定的前缀UN了,可知保养程度。

如上边第一张图所示,要发布告是需求用户同意的,也正是在率先次展开App的时候必须尝尝注册布告,假诺不登记,那么固然用户去设置中找也无从再通报里找到您的App然后打开。

为此大家须要在AppDelegate.m的application: didFinishLaunchingWithOptions:方法中登记通告:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // 注册通知
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert   UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {

        }];


    return YES;
}

如此这般就能够在率先次开发银行App时向用户索取权限。接下来就足以操纵发什么通告以及接受布告后怎么管理了。

我们得以定义几个措施来发文告:

#import <UserNotifications/UserNotifications.h>

……

/**
 iOS 10以后的本地通知
 */
- (void)addlocalNotificationForNewVersion {
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    center.delegate = self;
    UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
    content.title = [NSString localizedUserNotificationStringForKey:@"Hello" arguments:nil];
    content.body = [NSString localizedUserNotificationStringForKey:[NSString stringWithFormat:@"Agent-%d",arc4random()0] arguments:nil];
    content.sound = [UNNotificationSound defaultSound];

    //    UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:alertTime repeats:NO];
    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"OXNotification" content:content trigger:nil];

    [center addNotificationRequest:request withCompletionHandler:^(NSError *_Nullable error) {
        NSLog(@"成功添加推送");
    }];
}

发通报的具备剧情就在此间了,分明可知content是一个通告体,定义通告的片段内容、声音等,然后嵌入request中,增加到通报大旨就能够了。中间注释了一行是用来重新公告的,第一个参数是重新的年月距离,最小60s,第1个参数是是不是再一次。因为60s太长了不方便人民群众测量检验,所以不及在外表写叁个电火花计时器,重复调用那几个点子就足以了。

要抽取通告并拍卖必需要依照 UNUserNotificationCenterDelegate 那几个协议,上边代码中就安装了delegate是self,然后就能够拍卖接收文告:

#pragma mark - UNUserNotificationCenterDelegate
// iOS 10收到通知
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {

    NSDictionary * userInfo = notification.request.content.userInfo;
    UNNotificationRequest *request = notification.request; // 收到推送的请求
    UNNotificationContent *content = request.content; // 收到推送的消息内容
    NSNumber *badge = content.badge;  // 推送消息的角标
    NSString *body = content.body;    // 推送消息体
    UNNotificationSound *sound = content.sound;  // 推送消息的声音
    NSString *subtitle = content.subtitle;  // 推送消息的副标题
    NSString *title = content.title;  // 推送消息的标题

    if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        NSLog(@"iOS10 前台收到远程通知:%@", body);

    } else {
        // 判断为本地通知
        NSLog(@"iOS10 前台收到本地通知:{\\nbody:%@,\\ntitle:%@,\\nsubtitle:%@,\\nbadge:%@,\\nsound:%@,\\nuserInfo:%@\\n}",body,title,subtitle,badge,sound,userInfo);
        [self.dataArray addObject:content];
        [self.timeArray addObject:[self convertNSDateToNSString:[NSDate date]]];
        [self.tableView reloadData];
    }
    completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert); // 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以设置
}

自个儿那边的管理是增添到数组中,而且记录布告的时日,幸亏列表中突显,至于列表怎么显得就不写在那了,供给的同室可以直接看工程代码。

至于iOS 10的公告流程正是那些了。

<br />
整合四个案例去来完结那个意义,达成三个发送验证码的成效。
那边就不研讨普通的做法怎样去完结那几个事情了,直接上RAC代码。

可能你还不是很掌握,未有涉嫌,有个起首概念就不影响你明白NS提姆er了.

iOS 10之前系统的达成

老系统的落到实处其实要素都大约,只可是提供的类库不等同,同样必要在运用一开始的时候注册通告:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // 注册通知,如果已经获得发送通知的授权则创建本地通知,否则请求授权(注意:如果不请求授权在设置中是没有对应的通知设置项的,也就是说如果从来没有发送过请求,即使通过设置也打不开消息允许设置)
    if ([[UIApplication sharedApplication] currentUserNotificationSettings].types != UIUserNotificationTypeNone) {
        [self addLocalNotificationForOldVersion];
    } else {
        [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound  categories:nil]];
    }


    return YES;
}

丰裕通报大家也置于二个主意中:

/**
 iOS 10以前版本添加本地通知
 */
- (void)addLocalNotificationForOldVersion {

    //定义本地通知对象
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    //设置调用时间
    notification.timeZone = [NSTimeZone localTimeZone];
    notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:2.0];//通知触发的时间,10s以后
    notification.repeatInterval = 2;//通知重复次数
    notification.repeatCalendar=[NSCalendar currentCalendar];//当前日历,使用前最好设置时区等信息以便能够自动同步时间

    //设置通知属性
    notification.alertBody = [NSString stringWithFormat:@"Agent-%d",arc4random()0]; //通知主体
    notification.applicationIconBadgeNumber  = 1;//应用程序图标右上角显示的消息数
    notification.alertAction = @"打开应用"; //待机界面的滑动动作提示
    notification.alertLaunchImage = @"Default";//通过点击通知打开应用时的启动图片,这里使用程序启动图片
    notification.soundName = UILocalNotificationDefaultSoundName;//收到通知时播放的声音,默认消息声音
//    notification.soundName=@"msg.caf";//通知声音(需要真机才能听到声音)

    //设置用户信息
    notification.userInfo = @{@"id": @1, @"user": @"cloudox"};//绑定到通知上的其他附加信息

    //调用通知
    [[UIApplication sharedApplication] scheduleLocalNotification:notification];
}

能够看来能够设置的东西依旧蛮多的。

除此以外还恐怕有几个大概用取得的代理方法:

/**
 应用注册通知后

 @param application 应用
 @param notificationSettings 通知设置
 */
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    if (notificationSettings.types != UIUserNotificationTypeNone) {
        [self addLocalNotificationForOldVersion];
    }
}

/**
 应用进入前台时调用

 @param application 应用
 */
- (void)applicationWillEnterForeground:(UIApplication *)application {
    [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];//进入前台取消应用消息图标
}

/**
 收到通知后回调

 @param application 应用
 @param notification 通知
 */
- (void)application:(UIApplication *)application didReceiveLocalNotification:(nonnull UILocalNotification *)notification {
    NSLog(@"%@", notification.alertBody);
}

可是自个儿用这几个老方法在iOS 10的无绳电话机上测验收不到文告,不精晓是否在新系统必定要用新的库。

效能分析:UI下边会有一个button,点击button出殡验证码,並且起首倒计时,在分明时期内不允许在此发送验证码(也正是不容许点击button

NSTimer注册到Runloop中后,Runloop会周期性地触发注册的风浪.然而这里的周期并不要命准确.Timer的属性Tolerance告诉系统能够允许的小运测量误差.一旦有大型的任务,错失那一个周期要求实行的年月点±Tolerance,职分不会延后施行而是跳跃过去,下个周期继续.

没什么好结的,以上。


演示工程:https://github.com/Cloudox/OXNotificationTest
翻开作者首页

1、搭建UI

NSObject的定期方法此处不会介绍NSObject的具有办法,重假若介绍其应该小心的地点.在介绍从前补充一句:主线程会自动创造Runloop,子线程不会创制.

ca888会员登录 3

- performSelector:withObject:afterDelay:

UI

版权声明:本文由ca888发布于IT操作系统,转载请注明出处:iOS | 分化场景下的定期方法