基于Swift实现仿IOS闹钟

news/2025/2/15 7:30:03/

仿 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.ppmy.cn/news/1572179.html

相关文章

Java 大视界 -- 人工智能驱动下 Java 大数据的技术革新与应用突破(83)

💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…

KVM和OpenVZ的区别以及如何选择

KVM 和 OpenVZ 是目前市面上最为常见的两种虚拟化技术,两者各有其优缺点。了解这两者的区别能够帮助您挑选更加适合自身需求的VPS,本文中,我们就来从各个角度对比一下这两种技术,并提供一些选择上的建议。 什么是虚拟化&#xff…

DeepSeek本地化部署【window下安装】【linux下安装】

一、window 本地安装指导 1.1、下载window安装包 https://ollama.com/download/OllamaSetup.exe 1.2、点击下载好的安装包进行安装 检测安装是否成功: C:\Users\admin>ollama -v ollama version is 0.5.7有上面的输出,则证明已经安装成功。 配置…

物联网(IoT)如何与人工智能(AI)的结合

物联网(IoT)与人工智能(AI)的结合是当前技术发展的重要趋势,通常被称为 AIoT(人工智能物联网)。这种结合通过将AI的计算能力和数据分析能力与物联网的海量设备连接能力相结合,实现了…

从VGG到Transformer:深度神经网络层级演进对模型性能的深度解析与技术实践指南

一、技术原理(数学公式示意图) 1. 层深与模型容量关系 数学表达:根据Universal Approximation Theorem,深度网络可表达复杂函数: f ( x ) f L ( f L − 1 ( ⋯ f 1 ( x ) ) ) f(x) f_L(f_{L-1}(\cdots f_1(x))) f…

微软AutoGen高级功能——Memory

介绍 大家好,博主又来给大家分享知识了。这次又要给大家分享什么呢?哈哈。这次要给大家分享的是微软AutoGen框架的高级且重要的功能:Memory。在微软AutoGen中,Memory(记忆)是一个重要概念,它主要用于存储和管理智能体…

fastadmin图片前台导出

参考 https://github.com/hhurz/tableExport.jquery.plugin#options define([jquery, bootstrap, backend, table, form], function ($, undefined, Backend, Table, Form) {$(document).ready(function(){$(#table).bootstrapTable(refreshOptions, {exportOptions: {onMsoNu…

DeepSeek 可视化部署手册:环境配置与运维指南

DeepSeek 可视化部署详细步骤 DeepSeek 可视化部署涉及前端、后端、数据库等多个组件的配置与集成。以下是详细的部署步骤,帮助您完成从环境准备到生产环境部署的全过程。 1. 环境准备 在开始部署之前,确保您的系统满足以下要求: 操作系统…