当前位置: 首页 > news >正文

基于Swift实现仿IOS闹钟

仿 iOS 系统闹钟

  • 添加闹钟效果图

  • 收到通知效果图

更新日志

2018.09.12  由于 iOS 系统限制了注册本地推送的数量,最大的注册量为 64 条,且一旦超出 64 条,所有的推送都将失效,故而在添加推送的时候做了一个判断,超过 64 条后,将不添加,以免影响已经添加的推送。

前言

最近项目中涉及到了本地通知的功能,索性就模仿系统闹钟写了个 demo,对于 iOS 系统闹钟,应该都比较熟悉,该 demo,基本实现了系统闹钟的全部功能。该 demo 本地通知使用的是 iOS10 推出的 UserNotifications, 关于 UserNotifications 的介绍和使用,网上已有诸多文章,在此就不多做赘述。

UNNotificationsManager

关于闹钟所使用到的 UserNotifications 库 做了一个简单的封装, 包含了注册通知,添加通知,以及 一些通知组件的 实现方法,同时提供了可供 外部使用的收到推送的通知

extern NSString * const UNDidReciveRemoteNotifationKey;//收到远程通知时调用
extern NSString * const UNDidReciveLocalNotifationKey; //收到本地通知时
extern NSString * const UNNotifationInfoIdentiferKey;  //本地通知userinfo 里 Identifer的key值

一些其他方法,以 demo 为准

//注册本地通知
  + (void)registerLocalNotification;
  
  #pragma mark -- AddNotification

  /* 添加通知
  * identifer 标识符
  * body  主体
  * title 标题
  * subTitle 子标题
  * weekDay  周几
  * date 日期
  * repeat   是否重复
  * music 音乐
  */
  + (void)addNotificationWithBody:(NSString *)body
                        title:(NSString *)title
                     subTitle:(NSString *)subTitle
                      weekDay:(NSInteger)weekDay
                         date:(NSDate *)date
                        music:(NSString *)music
                    identifer:(NSString *)identifer
                     isRepeat:(BOOL)repeat
             completionHanler:(void (^)(NSError *))handler;
             
  #pragma mark -- NotificationManage
  /*
   * identifer 标识符
   * 根据标识符 移除 本地通知
   */
  + (void)removeNotificationWithIdentifer:(NSString *)identifer;

  #pragma mark -- NSDateComponents
  /*
   * return 日期组件 时分秒
   * ex 每天重复
   */
  + (NSDateComponents *)componentsEveryDayWithDate:(NSDate *)date;

  #pragma mark -- UNNotificationContent
  /* UNMutableNotificationContent 通知内容
   * title  标题
   * subTitle 子标题
   * body 主体
   */
  + (UNMutableNotificationContent *)contentWithTitle:(NSString *)title
                                 subTitle:(NSString *)subTitle
                                     body:(NSString *)body;

  #pragma mark -- UNNotificationTrigger
  /* UNNotificationTrigger 通知触发器
  * interval  通知间隔
  * repeats 是否重复
   */
  + (UNNotificationTrigger *)triggerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats;

添加闹钟

普通闹钟

   [UNNotificationsManager addNotificationWithContent:[UNNotificationsManager contentWithTitle:@"时钟" subTitle:nil body:nil sound:[UNNotificationSound soundNamed:self.music]] dateComponents:[UNNotificationsManager componentsWithDate:self.date] identifer:self.identifer isRepeat:self.repeats completionHanler:^(NSError *error) {
        NSLog(@"add error %@", error);
    }];

每天重复

[UNNotificationsManager addNotificationWithContent:[UNNotificationsManager contentWithTitle:@"时钟" subTitle:nil body:nil sound:[UNNotificationSound soundNamed:self.music]] dateComponents:[UNNotificationsManager componentsEveryDayWithDate:self.date] identifer:self.identifer isRepeat:self.repeats completionHanler:^(NSError *error) {
            NSLog(@"add error %@", error);
}];

每周重复(周一,周二等)

[self.repeatStrs enumerateObjectsUsingBlock:^(NSString *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSInteger week = 0;
        if ([obj containsString:@"周日"]) {
            week = 1;
        }else if([obj containsString:@"周一"]){
            week = 2;
        }else if([obj containsString:@"周二"]){
            week = 3;
        }else if([obj containsString:@"周三"]){
            week = 4;
        }else if([obj containsString:@"周四"]){
            week = 5;
        }else if([obj containsString:@"周五"]){
            week = 6;
        }else if([obj containsString:@"周六"]){
            week = 7;
        }
        [UNNotificationsManager addNotificationWithContent:[UNNotificationsManager contentWithTitle:@"闹钟" subTitle:nil body:nil sound:[UNNotificationSound soundNamed:self.music]] weekDay:week date:self.date identifer:self.identifer isRepeat:YES completionHanler:^(NSError *error) {
            NSLog(@"add error %@", error);
        }];
    }];
}

铃声

这里无法获取系统铃声和震动类型,自己在网上找了点铃声素材。 系统铃声需要 caf 格式,MP3 和 caf 格式相互转化方法如下

    //控制台输入
    afconvert xxx.mp3 xxx.caf -d ima4 -f caff -v

通知栏选项

首先注册通知的时候需要 UNNotificationCategory 以及 UNNotificationAction

UNNotificationAction *action1 = [UNNotificationAction actionWithIdentifier:actionFiveMin title:@"5分钟后" options:UNNotificationActionOptionNone];

UNNotificationAction *action2 = [UNNotificationAction actionWithIdentifier:actionHalfAnHour title:@"半小时后" options:UNNotificationActionOptionNone];

UNNotificationAction *action3 = [UNNotificationAction actionWithIdentifier:actionOneHour title:@"1小时后" options:UNNotificationActionOptionNone];

UNNotificationAction *action4 = [UNNotificationAction actionWithIdentifier:actionStop title:@"停止" options:UNNotificationActionOptionNone];

UNNotificationCategory *category = [UNNotificationCategory categoryWithIdentifier:identiferStr actions:@[action1, action2,action3, action4] intentIdentifiers:@[] options:UNNotificationCategoryOptionNone];

UNNotificationCategory *stopCategory = [UNNotificationCategory categoryWithIdentifier:categryStopIdf actions:@[action4] intentIdentifiers:@[] options:UNNotificationCategoryOptionNone];

[center setNotificationCategories:[NSSet setWithArray:@[category,stopCategory]]];

然后在设置 UNMutableNotificationContent 的时候需要设置对应的 categoryIdentifier   这里区分了是否设置了稍候提醒

+ (void)addNotificationWithContent:(UNNotificationContent *)content identifer:(NSString *)identifer trigger:(UNNotificationTrigger *)trigger completionHanler:(void (^)(NSError *))handler {

    //设置 category
    UNMutableNotificationContent *aContent = [content mutableCopy];
    if ([identifer hasPrefix:@"isLater"]) {
        aContent.categoryIdentifier = categryLaterIdf;
    }else {
        aContent.categoryIdentifier = categryStopIdf;
    }
    [self addNotificationWithRequest:[UNNotificationRequest requestWithIdentifier:identifer content:aContent trigger:trigger] completionHanler:handler];
}

最后在用户点击导航栏控件的时候,根据 identifier 处理相应事件

//与导航控件交互的时候会调用
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
    NSLog(@"%s", __func__);
    [self handCommnet:response];
    completionHandler();
} 
-(void)handCommnet:(UNNotificationResponse *)response
{
    NSString *actionIdef = response.actionIdentifier;
    NSDate *date;
    if ([actionIdef isEqualToString:actionStop]) {
        return;
    }else if ([actionIdef isEqualToString:actionFiveMin]) {
        date = [NSDate dateWithTimeIntervalSinceNow:5 * 60];
    }else if ([actionIdef isEqualToString:actionHalfAnHour]) {
        date = [NSDate dateWithTimeIntervalSinceNow:30 * 60];
    }else if ([actionIdef isEqualToString:actionOneHour]) {
        date = [NSDate dateWithTimeIntervalSinceNow:60 * 60];
    }
    
    if (date) {
        [UNNotificationsManager addNotificationWithContent:response.notification.request.content identifer:response.notification.request.identifier trigger:[UNNotificationsManager triggerWithDateComponents:[UNNotificationsManager componentsWithDate:date] repeats:NO] completionHanler:^(NSError *error) {
            NSLog(@"delay11111 %@", error);
        }];
    }
}

持续推送

本地铃声 时长小于 30s。当手机处于后台,息屏的时候,铃声音乐是可以放完的的,手机处于活跃状态,只会持续到推送消失,想要在活跃状态持续推送本地闹钟,需要用户在    设置-通知-横幅风格    选择持续。

相关文章:

  • .Net使用EF Core框架如何连接Oracle
  • Django 创建表 choices的妙用:get_<field_name>_display()
  • 2025年智慧城市解决方案下载:AI-超脑中台,体系架构整体设计
  • CodeGPT + IDEA + DeepSeek,在IDEA中引入DeepSeek实现AI智能开发
  • Office hour 1
  • 对比 LVS 负载均衡群集的 NAT 模式和 DR 模式,其各自的优势
  • java八股---java基础03(包、IO流、反射、String、包装类)
  • zola + github page,用 workflows 部署
  • python中的抽象类在项目中的实际应用
  • webassembly009 transformers.js 网页端侧推理 NLLB翻译模型
  • 【Unity】 HTFramework框架(六十)Assistant助手(在Unity中接入DeepSeek等AI语言大模型)
  • 蓝桥杯---N字形变换(leetcode第6题)题解
  • 蓝桥杯备赛 Day13.1走出迷宫
  • 以SpringBoot+Vue分布式架构商城系统为例,讲解订单生命周期的管理
  • 分卷压缩怎么操作?分卷压缩怎么解压?
  • Python----PyQt开发(PyQt高级:手搓一个简单的记事本)
  • 腾讯混元hunyuan3d生成模型,本地搭建和使用
  • singleTaskAndroid的Activity启动模式知识点总结
  • 374_C++_升级等其他类型标签,使用将4字节字符串转换为无符号整数的定义方式
  • Managed Lustre 和 WEKA:高性能文件系统的对比与应用
  • 摩根士丹利:对冲基金已加码,八成投资者有意近期增配中国
  • 新华时评:中美经贸会谈为全球经济纾压增信
  • 《广州大典研究》集刊发展座谈会:“广州学”的传承与创新
  • 来伊份:已下架涉事批次蜜枣粽产品,消费者可获额外补偿,取得实物后进一步分析
  • 石家庄推动城市能级与民生福祉并进
  • 4月国产新能源,降价潮迈入拐点