当前位置: 首页 > 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 *)bodytitle:(NSString *)titlesubTitle:(NSString *)subTitleweekDay:(NSInteger)weekDaydate:(NSDate *)datemusic:(NSString *)musicidentifer:(NSString *)identiferisRepeat:(BOOL)repeatcompletionHanler:(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 *)titlesubTitle:(NSString *)subTitlebody:(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 {//设置 categoryUNMutableNotificationContent *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。当手机处于后台,息屏的时候,铃声音乐是可以放完的的,手机处于活跃状态,只会持续到推送消失,想要在活跃状态持续推送本地闹钟,需要用户在    设置-通知-横幅风格    选择持续。

http://www.lryc.cn/news/536638.html

相关文章:

  • Threadlocal的实现原理
  • 线程池处理异常
  • RabbitMQ配置SSL证书
  • .NET 9.0 的 Blazor Web App 项目,进度条 <progress> 组件使用注意事项
  • 第J7周:对于ResNeXt-50算法的思考
  • 【第2章:神经网络基础与实现——2.3 多层感知机(MLP)的构建与调优技巧】
  • 【Elasticsearch】keyword分析器
  • 重生之我在异世界学编程之C语言:深入预处理篇(上)目录)
  • MySQL数据库误删恢复_mysql 数据 误删
  • SpringAI集成DeepSeek实战
  • 解决 THC/THC.h: No such file or directory 报错
  • S4D480 S4HANA 基于PDF的表单打印
  • 数组_移除元素
  • Vue2/Vue3分别如何使用Watch
  • C++从入门到实战(四)C++引用与inline,nullptr
  • Linux库制作与原理:【静态库】【动态库】【目标文件】【ELF文件】【ELF从形成到假造轮廓】【理解链接和加载】
  • 项目BUG
  • wordpress部署nginx版的
  • 【鸿蒙Next】优秀鸿蒙博客集锦
  • 【第2章:神经网络基础与实现——2.1 前馈神经网络的结构与工作原理】
  • python-leetcode-阶乘后的零
  • Python:学生管理系统(继承性、多态性)。
  • 网络安全RSA加密
  • Vue学习笔记4
  • mariadb数据库的安装与部署
  • 单调队列与栈
  • Matlab 多项式曲线拟合(三维)
  • 机器翻译同样的文本,是从英语翻译成日语更准确还是中文翻译成日语更准确
  • MAC 系统关屏幕后电量消耗极快 Wake Requests
  • golangAPI调用deepseek