闹钟(TSAlarmClock)
闹钟模块提供了设备闹钟的管理功能,包括获取、添加、更新、删除闹钟,以及监听闹钟变化等操作。支持多个闹钟配置、重复设置、贪睡功能等。
前提条件
- 设备已配对并连接到 iOS 应用
- 设备支持闹钟功能(可通过
supportMaxAlarmCount验证) - 已导入
TSAlarmClockInterface.h和TSAlarmClockModel.h
数据模型
TSAlarmClockModel
闹钟模型类,表示设备上的闹钟信息。
| 属性名 | 类型 | 说明 |
|---|---|---|
alarmId | UInt8 | 设备端闹钟的唯一标识符,有效范围 [0, supportMaxAlarmCount)。添加时无需设置,SDK 自动分配;更新/删除时必须设置为有效 ID |
identifier | NSString * | APP 端生成的闹钟唯一标识符,用于追踪和管理闹钟 |
label | NSString * | 闹钟标签(显示名称),最大字节长度由 supportMaxAlarmLabelLength 决定 |
time | NSDateComponents * | 闹钟时间,包含小时(0-23)和分钟(0-59) |
enable | BOOL | 闹钟开关状态,YES 表示启用,NO 表示禁用 |
snoozeEnable | BOOL | 是否开启贪睡功能(设备支持时有效) |
snoozeInterval | NSUInteger | 贪睡间隔,单位为分钟(仅在 snoozeEnable 为 YES 时有效) |
snoozeRepeatCount | NSUInteger | 贪睡重复次数(仅在 snoozeEnable 且设备支持时有效) |
repeatOptions | TSAlarmRepeat | 闹钟重复选项,使用位掩码表示周一至周日及组合选项 |
枚举与常量
TSAlarmRepeat
闹钟重复选项枚举,使用位掩码表示,可组合使用。例如:TSAlarmRepeatMonday | TSAlarmRepeatWednesday 表示周一和周三重复。
| 枚举值 | 说明 |
|---|---|
TSAlarmRepeatNone | 不重复 |
TSAlarmRepeatMonday | 周一重复 |
TSAlarmRepeatTuesday | 周二重复 |
TSAlarmRepeatWednesday | 周三重复 |
TSAlarmRepeatThursday | 周四重复 |
TSAlarmRepeatFriday | 周五重复 |
TSAlarmRepeatSaturday | 周六重复 |
TSAlarmRepeatSunday | 周日重复 |
TSAlarmRepeatWorkday | 工作日重复(周一至周五) |
TSAlarmRepeatWeekend | 周末重复(周六至周日) |
TSAlarmRepeatEveryday | 每天重复 |
回调类型
TSAlarmClockResultBlock
闹钟操作回调块类型。
| 参数名 | 类型 | 说明 |
|---|---|---|
allAlarmClocks | NSArray<TSAlarmClockModel *> * | 闹钟数组,包含当前所有闹钟设置;若返回 nil 表示操作中出现错误 |
error | NSError * | 操作失败时的错误对象,成功时为 nil |
用于获取所有闹钟、设置闹钟、监听闹钟变化等多种操作。
TSCompletionBlock
通用完成回调块类型。
| 参数名 | 类型 | 说明 |
|---|---|---|
error | NSError * | 操作失败时的错误对象,成功时为 nil |
接口方法
获取设备支持的最大闹钟数量
- (NSInteger)supportMaxAlarmCount;
返回设备支持的最大闹钟数。不同设备型号可能有不同限制。
| 参数 | 类型 | 说明 |
|---|---|---|
| 返回值 | NSInteger | 最大闹钟数;若返回 0 表示设备不支持闹钟功能 |
代码示例:
id<TSAlarmClockInterface> alarmInterface = ...;
NSInteger maxCount = [alarmInterface supportMaxAlarmCount];
TSLog(@"Device supports max %ld alarms", (long)maxCount);
if (maxCount == 0) {
TSLog(@"Device does not support alarm function");
}
获取闹钟标签的最大字节长度
- (NSInteger)supportMaxAlarmLabelLength;
返回闹钟标签允许的最大字节长度。一个中文字符通常占 3 字节(UTF-8 编码)。
| 参数 | 类型 | 说明 |
|---|---|---|
| 返回值 | NSInteger | 最大字节长度;若返回 0 表示设备不支持标签 |
代码示例:
id<TSAlarmClockInterface> alarmInterface = ...;
NSInteger maxLabelLength = [alarmInterface supportMaxAlarmLabelLength];
TSLog(@"Max label length: %ld bytes", (long)maxLabelLength);
// 验证标签长度
NSString *label = @"起床闹钟";
NSData *labelData = [label dataUsingEncoding:NSUTF8StringEncoding];
if (labelData.length > maxLabelLength) {
TSLog(@"Label is too long!");
}
检查设备是否支持闹钟贪睡
- (BOOL)supportAlarmSnooze;
查询设备是否支持闹钟贪睡功能。
| 参数 | 类型 | 说明 |
|---|---|---|
| 返回值 | BOOL | YES 表示支持贪睡,NO 表示不支持 |
代码示例:
id<TSAlarmClockInterface> alarmInterface = ...;
if ([alarmInterface supportAlarmSnooze]) {
TSLog(@"Device supports snooze feature");
TSAlarmClockModel *alarm = [[TSAlarmClockModel alloc] init];
alarm.snoozeEnable = YES;
alarm.snoozeInterval = 5; // 5 分钟间隔
alarm.snoozeRepeatCount = 3; // 重复 3 次
} else {
TSLog(@"Device does not support snooze");
}
从设备获取所有闹钟
- (void)getAllAlarmClocksCompletion:(_Nullable TSAlarmClockResultBlock)completion;
从设备获取所有闹钟设置。
| 参数名 | 类型 | 说明 |
|---|---|---|
completion | TSAlarmClockResultBlock | 返回所有闹钟数组或错误信息的回调块 |
代码示例:
id<TSAlarmClockInterface> alarmInterface = ...;
[alarmInterface getAllAlarmClocksCompletion:^(NSArray<TSAlarmClockModel *> *allAlarmClocks, NSError *error) {
if (error) {
TSLog(@"Failed to get alarms: %@", error.localizedDescription);
return;
}
TSLog(@"Total alarms: %lu", (unsigned long)allAlarmClocks.count);
for (TSAlarmClockModel *alarm in allAlarmClocks) {
TSLog(@"Alarm ID: %d, Time: %02ld:%02ld, Enabled: %@",
alarm.alarmId, (long)alarm.hour, (long)alarm.minute,
alarm.isEnabled ? @"YES" : @"NO");
}
}];
设置所有闹钟到设备
- (void)setAllAlarmClocks:(NSArray<TSAlarmClockModel *> *_Nullable)allAlarmClocks
completion:(TSCompletionBlock)completion;
同步所有闹钟设置到设备,覆盖现有的所有闹钟。
| 参数名 | 类型 | 说明 |
|---|---|---|
allAlarmClocks | NSArray<TSAlarmClockModel *> * | 要设置的闹钟数组;传 nil 或空数组等价于删除所有闹钟 |
completion | TSCompletionBlock | 操作完成回调块 |
代码示例:
id<TSAlarmClockInterface> alarmInterface = ...;
// 创建闹钟
TSAlarmClockModel *alarm1 = [[TSAlarmClockModel alloc] init];
[alarm1 setHour:7 minute:30];
alarm1.label = @"起床";
alarm1.enable = YES;
alarm1.repeatOptions = TSAlarmRepeatWorkday; // 工作日重复
alarm1.identifier = [TSAlarmClockModel newClockIdentifier];
TSAlarmClockModel *alarm2 = [[TSAlarmClockModel alloc] init];
[alarm2 setHour:22 minute:0];
alarm2.label = @"睡眠提醒";
alarm2.enable = YES;
alarm2.repeatOptions = TSAlarmRepeatEveryday;
alarm2.identifier = [TSAlarmClockModel newClockIdentifier];
// 设置到设备
[alarmInterface setAllAlarmClocks:@[alarm1, alarm2] completion:^(NSError *error) {
if (error) {
TSLog(@"Failed to set alarms: %@", error.localizedDescription);
} else {
TSLog(@"Alarms set successfully");
}
}];
添加单个闹钟
- (void)addAlarmClock:(TSAlarmClockModel *)alarm
completion:(_Nullable TSCompletionBlock)completion;
向设备添加单个闹钟,不影响现有闹钟。SDK 自动分配 alarmId。
| 参数名 | 类型 | 说明 |
|---|---|---|
alarm | TSAlarmClockModel * | 要添加的闹钟模型;无需设置 alarmId,SDK 会自动分配 |
completion | TSCompletionBlock | 操作完成回调块 |
代码示例:
id<TSAlarmClockInterface> alarmInterface = ...;
TSAlarmClockModel *alarm = [[TSAlarmClockModel alloc] init];
[alarm setHour:9 minute:0];
alarm.label = @"工作提醒";
alarm.enable = YES;
alarm.repeatOptions = TSAlarmRepeatMonday | TSAlarmRepeatFriday;
alarm.identifier = [TSAlarmClockModel newClockIdentifier];
// 不要设置 alarmId,SDK 会自动分配
// alarm.alarmId = ...; // 不需要
[alarmInterface addAlarmClock:alarm completion:^(NSError *error) {
if (error) {
TSLog(@"Failed to add alarm: %@", error.localizedDescription);
} else {
TSLog(@"Alarm added successfully");
}
}];
更新单个闹钟
- (void)updateAlarmClock:(TSAlarmClockModel *)alarm
completion:(_Nullable TSCompletionBlock)completion;
更新指定 alarmId 的闹钟。其他闹钟保持不变。
| 参数名 | 类型 | 说明 |
|---|---|---|
alarm | TSAlarmClockModel * | 要更新的闹钟模型;必须设置有效的 alarmId |
completion | TSCompletionBlock | 操作完成回调块 |
代码示例:
id<TSAlarmClockInterface> alarmInterface = ...;
// 先获取现有闹钟
[alarmInterface getAllAlarmClocksCompletion:^(NSArray<TSAlarmClockModel *> *allAlarmClocks, NSError *error) {
if (error) return;
// 获取第一个闹钟并更新
if (allAlarmClocks.count > 0) {
TSAlarmClockModel *alarm = allAlarmClocks[0];
// 修改时间
[alarm setHour:8 minute:0];
alarm.label = @"更新的提醒";
alarm.enable = YES;
// 必须保留原始的 alarmId
// alarm.alarmId 已经有值,无需修改
[alarmInterface updateAlarmClock:alarm completion:^(NSError *error) {
if (error) {
TSLog(@"Failed to update alarm: %@", error.localizedDescription);
} else {
TSLog(@"Alarm updated successfully");
}
}];
}
}];
删除单个闹钟
- (void)deleteAlarmClockWithId:(UInt8)alarmId
completion:(_Nullable TSCompletionBlock)completion;
通过 alarmId 删除指定的闹钟。其他闹钟保持不变。
| 参数名 | 类型 | 说明 |
|---|---|---|
alarmId | UInt8 | 要删除的闹钟 ID,必须是有效的 ID(从 getAllAlarmClocksCompletion: 返回列表中获取) |
completion | TSCompletionBlock | 操作完成回调块 |
代码示例:
id<TSAlarmClockInterface> alarmInterface = ...;
// 删除 alarmId 为 0 的闹钟
[alarmInterface deleteAlarmClockWithId:0 completion:^(NSError *error) {
if (error) {
TSLog(@"Failed to delete alarm: %@", error.localizedDescription);
} else {
TSLog(@"Alarm deleted successfully");
}
}];
删除所有闹钟
- (void)deleteAllAlarmClocksWithCompletion:(_Nullable TSCompletionBlock)completion;
一次性删除设备上的所有闹钟。
| 参数名 | 类型 | 说明 |
|---|---|---|
completion | TSCompletionBlock | 操作完成回调块 |
代码示例:
id<TSAlarmClockInterface> alarmInterface = ...;
[alarmInterface deleteAllAlarmClocksWithCompletion:^(NSError *error) {
if (error) {
TSLog(@"Failed to delete all alarms: %@", error.localizedDescription);
} else {
TSLog(@"All alarms deleted successfully");
}
}];
监听闹钟变化
- (void)registerAlarmClocksDidChangedBlock:(_Nullable TSAlarmClockResultBlock)completion;
注册闹钟变化监听。同一时间只允许一个监听者,新注册会替换旧监听。
| 参数名 | 类型 | 说明 |
|---|---|---|
completion | TSAlarmClockResultBlock | 闹钟发生变化时触发的回调块,返回更新后的所有闹钟 |
代码示例:
id<TSAlarmClockInterface> alarmInterface = ...;
[alarmInterface registerAlarmClocksDidChangedBlock:^(NSArray<TSAlarmClockModel *> *allAlarmClocks, NSError *error) {
if (error) {
TSLog(@"Monitoring failed: %@", error.localizedDescription);
return;
}
TSLog(@"Alarms changed! Current count: %lu", (unsigned long)allAlarmClocks.count);
for (TSAlarmClockModel *alarm in allAlarmClocks) {
TSLog(@"Alarm ID: %d, Label: %@, Time: %02ld:%02ld",
alarm.alarmId, alarm.label, (long)alarm.hour, (long)alarm.minute);
}
}];
设置闹钟时间
- (void)setHour:(NSInteger)hour minute:(NSInteger)minute;
设置 TSAlarmClockModel 的闹钟时间。无效值会被自动限制在有效范围内。
| 参数名 | 类型 | 说明 |
|---|---|---|
hour | NSInteger | 小时值(0-23,24 小时制);超出范围会被限制 |
minute | NSInteger | 分钟值(0-59);超出范围会被限制 |
代码示例:
TSAlarmClockModel *alarm = [[TSAlarmClockModel alloc] init];
[alarm setHour:7 minute:30];
TSLog(@"Hour: %ld, Minute: %ld", (long)alarm.hour, (long)alarm.minute);
// 超出范围的值会被自动限制
[alarm setHour:25 minute:70];
TSLog(@"Hour: %ld, Minute: %ld", (long)alarm.hour, (long)alarm.minute); // 输出: Hour: 23, Minute: 59
获取闹钟小时值
- (NSInteger)hour;
获取 TSAlarmClockModel 的小时值。
| 参数 | 类型 | 说明 |
|---|---|---|
| 返回值 | NSInteger | 小时值(0-23,24 小时制) |
获取闹钟分钟值
- (NSInteger)minute;
获取 TSAlarmClockModel 的分钟值。
| 参数 | 类型 | 说明 |
|---|---|---|
| 返回值 | NSInteger | 分钟值(0-59) |
校验闹钟模型数组
+ (NSError * _Nullable)validateAlarmClocks:(NSArray<TSAlarmClockModel *> *)alarmClocks
maxLabelLength:(NSInteger)maxLabelLength
maxAlarmCount:(NSInteger)maxAlarmCount;
验证闹钟模型数组的合法性。
| 参数名 | 类型 | 说明 |
|---|---|---|
alarmClocks | NSArray<TSAlarmClockModel *> * | 要校验的闹钟数组 |
maxLabelLength | NSInteger | 标签最大字节长度;传 0 跳过长度校验 |
maxAlarmCount | NSInteger | 设备支持的最大闹钟数(alarmId 有效范围 [0, maxAlarmCount));传 0 跳过校验 |
| 返回值 | NSError * | 任一模型校验失败返回错误对象,全部通过返回 nil |
代码示例:
NSArray<TSAlarmClockModel *> *alarms = @[ /* ... */ ];
NSError *error = [TSAlarmClockModel validateAlarmClocks:alarms
maxLabelLength:64
maxAlarmCount:5];
if (error) {
TSLog(@"Validation failed: %@", error.localizedDescription);
} else {
TSLog(@"All alarms are valid");
}
生成全局唯一闹钟标识符
+ (NSString *)newClockIdentifier;
生成一个形如 alarmItem + base36(随机数) 的全局唯一标识符。
| 参数 | 类型 | 说明 |
|---|---|---|
| 返回值 | NSString * | 唯一标识符字符串;SDK 内部在添加闹钟时自动分配,一般无需手动调用 |
代码示例:
// SDK 内部会自动生成,但也可以手动调用
NSString *identifier = [TSAlarmClockModel newClockIdentifier];
TSLog(@"Generated identifier: %@", identifier);
// 在创建闹钟时使用
TSAlarmClockModel *alarm = [[TSAlarmClockModel alloc] init];
alarm.identifier = [TSAlarmClockModel newClockIdentifier];
注意事项
-
alarmId 管理:
- 调用
addAlarmClock:时,不要手动设置alarmId,SDK 会自动分配第一个可用 ID - 调用
updateAlarmClock:或deleteAlarmClockWithId:时,必须使用从getAllAlarmClocksCompletion:返回的有效alarmId alarmId有效范围为[0, supportMaxAlarmCount)
- 调用
-
标签长度验证:
- 必须先调用
supportMaxAlarmLabelLength获取设备限制 - 使用
NSData的 UTF-8 编码计算字节长度,而非字符长度 - 一个中文字符通常占 3 字节,英文字符占 1 字节
- 必须先调用
-
贪睡功能支持:
- 使用
supportAlarmSnooze检查设备是否支持贪睡 - 设备不支持时,
snoozeEnable、snoozeInterval、snoozeRepeatCount等属性无效
- 使用
-
重复选项:
repeatOptions使用位掩码表示,可组合多个值- 例如:
TSAlarmRepeatMonday | TSAlarmRepeatWednesday | TSAlarmRepeatFriday表示周一、三、五 - 常用组合:
TSAlarmRepeatWorkday(工作日)、TSAlarmRepeatWeekend(周末)、TSAlarmRepeatEveryday(每天)
-
闹钟监听:
- 同一时间只允许一个监听者,新注册会替换旧监听
- 监听块在闹钟被添加、修改或删除时触发
- 传 nil 可取消监听
-
批量操作:
setAllAlarmClocks:会覆盖所有现有闹钟,谨慎使用- 若需增删单个闹钟,优先使用
addAlarmClock:、updateAlarmClock:、deleteAlarmClockWithId:等方法 - 使用
validateAlarmClocks:maxLabelLength:maxAlarmCount:验证数据合法性
-
错误处理:
- 所有异步操作均需检查
error参数 - 常见错误:超出最大闹钟数限制、标签过长、无效的
alarmId等
- 所有异步操作均需检查
-
时间格式:
- 使用 24 小时制(0-23),无需转换为 12 小时制
NSDateComponents只需设置hour和minute属性