跳到主要内容

表盘 (TSDial)

表盘模块提供完整的外设表盘管理功能,包括表盘信息获取、推送、删除、切换以及变化监听。支持内置表盘、云端表盘和自定义表盘的全生命周期管理。

前提条件

  • 设备已连接并处于可用状态
  • 获取 TSPeripheralDialInterface 协议实例
  • 对于自定义表盘操作,需要获取设备屏幕信息(TSPeripheralScreen)以确保图片尺寸正确

数据模型

TSDialModel(表盘信息模型)

属性名类型说明
dialIdNSString *表盘唯一标识符
dialNameNSString *表盘显示名称
dialTypeTSDialType表盘类型(内置/自定义/云端)
isCurrentBOOL是否为当前表盘
locationIndexUInt8表盘在设备上的位置索引
versionNSString *表盘版本号
filePathNSString *表盘资源本地路径

TSCustomDial(自定义表盘模型)

属性名类型说明
dialIdNSString *自定义表盘唯一标识符
dialNameNSString *自定义表盘名称
dialTypeTSCustomDialType自定义表盘类型(单图/多图/视频)
templateFilePathNSString *表盘模板bin文件本地路径
previewImageItemTSCustomDialItem *预览图片项
resourceItemsNSArray<TSCustomDialItem *> *背景图片项数组

TSCustomDialItem(表盘项模型)

属性名类型说明
dialTypeTSCustomDialType表盘项类型(单图/多图/视频)
videoLocalPathNSString *视频文件本地路径
resourceImageUIImage *表盘背景图片
dialTimeTSCustomDialTime *时间显示配置

TSCustomDialTime(时间配置模型)

属性名类型说明
timeImageUIImage *时间样式图片
timeImagePathNSString *时间样式图片文件路径
timePositionTSDialTimePosition时间显示位置
timeRectCGRect时间显示区域矩形
timeColorUIColor *时间显示颜色
styleTSDialTimeStyle时间显示样式

枚举与常量

TSDialType(表盘类型)

说明
eTSDialTypeBuiltIn (0)设备自带的内置表盘
eTSDialTypeCustomer (1)用户创建的自定义表盘
eTSDialTypeCloud (2)从云服务器下载的表盘

TSCustomDialType(自定义表盘类型)

说明
eTSCustomDialSingleImage (1)单图片自定义表盘
eTSCustomDialMultipleImage (2)多图片自定义表盘
eTSCustomDialVideo (3)视频自定义表盘

TSDialTimePosition(时间显示位置)

说明
eTSDialTimePositionTop (0)上方
eTSDialTimePositionBottom (1)下方
eTSDialTimePositionLeft (2)左方
eTSDialTimePositionRight (3)右方
eTSDialTimePositionTopLeft (4)左上
eTSDialTimePositionBottomLeft (5)左下
eTSDialTimePositionTopRight (6)右上
eTSDialTimePositionBottomRight (7)右下
eTSDialTimePositionCenter (8)中间

TSDialTimeStyle(时间显示样式)

说明
eTSDialTimeStyleNone (0)无样式
eTSDialTimeStyle1 (1)时间样式1
eTSDialTimeStyle2 (2)时间样式2
eTSDialTimeStyle3 (3)时间样式3
eTSDialTimeStyle4 (4)时间样式4
eTSDialTimeStyle5 (5)时间样式5
eTSDialTimeStyle6 (6)时间样式6
eTSDialTimeStyle7 (7)时间样式7

TSDialPushResult(表盘推送结果)

说明
eTSDialPushResultStart (0)开始
eTSDialPushResultProgress (0)推送中
eTSDialPushResultSuccess推送成功
eTSDialPushResultFailed推送失败

回调类型

回调类型说明
void (^)(TSDialPushResult result, NSError *error)表盘操作完成回调
void (^)(TSDialPushResult result, NSInteger progress)表盘推送进度回调
void (^)(NSArray<TSDialModel *> *dials, NSError *error)表盘列表回调
void (^)(NSInteger remainSpace, NSError *error)表盘空间信息回调
void (^)(NSDictionary *widgets, NSError *error)挂件列表回调

接口方法

获取当前表盘

- (void)fetchCurrentDial:(void (^)(TSDialModel *_Nullable dial,
NSError *_Nullable error))completion;
参数类型说明
completionvoid (^)(TSDialModel *, NSError *)完成回调,返回当前表盘模型
id<TSPeripheralDialInterface> dialInterface = [peripheral getInterface:@protocol(TSPeripheralDialInterface)];

[dialInterface fetchCurrentDial:^(TSDialModel * _Nullable dial, NSError * _Nullable error) {
if (error) {
TSLog(@"获取当前表盘失败: %@", error.localizedDescription);
return;
}
TSLog(@"当前表盘: %@, 类型: %lu", dial.dialName, (unsigned long)dial.dialType);
}];

获取所有表盘

- (void)fetchAllDials:(TSDialListBlock)completion;
参数类型说明
completionvoid (^)(NSArray<TSDialModel *> *, NSError *)完成回调,返回所有表盘模型数组
[dialInterface fetchAllDials:^(NSArray<TSDialModel *> * _Nullable dials, NSError * _Nullable error) {
if (error) {
TSLog(@"获取表盘列表失败: %@", error.localizedDescription);
return;
}
TSLog(@"设备上共有 %lu 个表盘", (unsigned long)dials.count);
for (TSDialModel *dial in dials) {
TSLog(@"表盘: %@, 类型: %lu, 当前: %@", dial.dialName, (unsigned long)dial.dialType, dial.isCurrent ? @"是" : @"否");
}
}];

切换表盘

- (void)switchToDial:(TSDialModel *)dial
completion:(nullable void(^)(BOOL isSuccess, NSError *_Nullable error))completion;
参数类型说明
dialTSDialModel *要切换的表盘模型
completionvoid (^)(BOOL, NSError *)完成回调
TSDialModel *targetDial = [[TSDialModel alloc] init];
targetDial.dialId = @"dial_001";

[dialInterface switchToDial:targetDial completion:^(BOOL isSuccess, NSError * _Nullable error) {
if (isSuccess) {
TSLog(@"表盘切换成功");
} else {
TSLog(@"表盘切换失败: %@", error.localizedDescription);
}
}];

生成自定义表盘ID

- (nonnull NSString *)generateCustomDialIdWithType:(TSCustomDialType)dialType;
参数类型说明
dialTypeTSCustomDialType自定义表盘类型
返回值类型说明
NSString *生成的唯一表盘ID字符串
NSString *customDialId = [dialInterface generateCustomDialIdWithType:eTSCustomDialSingleImage];
TSLog(@"生成的自定义表盘ID: %@", customDialId);

推送云端表盘

- (void)installDownloadedCloudDial:(TSDialModel *)dial
progressBlock:(nullable TSDialProgressBlock)progressBlock
completion:(nullable TSDialCompletionBlock)completion;
参数类型说明
dialTSDialModel *云端表盘模型
progressBlockvoid (^)(TSDialPushResult, NSInteger)进度回调
completionvoid (^)(TSDialPushResult, NSError *)完成回调
TSDialModel *cloudDial = [[TSDialModel alloc] init];
cloudDial.dialId = @"cloud_dial_001";
cloudDial.dialType = eTSDialTypeCloud;

[dialInterface installDownloadedCloudDial:cloudDial
progressBlock:^(TSDialPushResult result, NSInteger progress) {
TSLog(@"推送进度: %ld%%", (long)progress);
} completion:^(TSDialPushResult result, NSError * _Nullable error) {
if (result == eTSDialPushResultSuccess) {
TSLog(@"云端表盘推送成功");
} else if (result == eTSDialPushResultFailed) {
TSLog(@"云端表盘推送失败: %@", error.localizedDescription);
}
}];

推送自定义表盘

- (void)installCustomDial:(TSCustomDial *)customDial
progressBlock:(nullable TSDialProgressBlock)progressBlock
completion:(nullable TSDialCompletionBlock)completion;
参数类型说明
customDialTSCustomDial *自定义表盘模型
progressBlockvoid (^)(TSDialPushResult, NSInteger)进度回调
completionvoid (^)(TSDialPushResult, NSError *)完成回调
TSCustomDial *customDial = [[TSCustomDial alloc] init];
customDial.dialId = [dialInterface generateCustomDialIdWithType:eTSCustomDialSingleImage];
customDial.dialName = @"我的自定义表盘";
customDial.dialType = eTSCustomDialSingleImage;
customDial.templateFilePath = @"/path/to/template.bin";

TSCustomDialItem *item = [[TSCustomDialItem alloc] init];
item.dialType = eTSCustomDialSingleImage;
item.resourceImage = [UIImage imageNamed:@"dial_background"];
item.dialTime = [[TSCustomDialTime alloc] init];
item.dialTime.timePosition = eTSDialTimePositionTop;

customDial.resourceItems = @[item];

[dialInterface installCustomDial:customDial
progressBlock:^(TSDialPushResult result, NSInteger progress) {
TSLog(@"自定义表盘推送进度: %ld%%", (long)progress);
} completion:^(TSDialPushResult result, NSError * _Nullable error) {
if (result == eTSDialPushResultSuccess) {
TSLog(@"自定义表盘推送成功");
} else if (result == eTSDialPushResultFailed) {
TSLog(@"自定义表盘推送失败: %@", error.localizedDescription);
}
}];

删除表盘

- (void)deleteDial:(TSDialModel *)dial
completion:(nullable void(^)(BOOL isSuccess, NSError *_Nullable error))completion;
参数类型说明
dialTSDialModel *要删除的表盘模型
completionvoid (^)(BOOL, NSError *)完成回调
TSDialModel *dialToDelete = [[TSDialModel alloc] init];
dialToDelete.dialId = @"custom_dial_001";

[dialInterface deleteDial:dialToDelete completion:^(BOOL isSuccess, NSError * _Nullable error) {
if (isSuccess) {
TSLog(@"表盘删除成功");
} else {
TSLog(@"表盘删除失败: %@", error.localizedDescription);
}
}];

获取表盘剩余存储空间

- (void)fetchWatchFaceRemainingStorageSpace:(nullable TSDialSpaceBlock)completion;
参数类型说明
completionvoid (^)(NSInteger, NSError *)完成回调,返回剩余空间(字节)
[dialInterface fetchWatchFaceRemainingStorageSpace:^(NSInteger remainSpace, NSError * _Nullable error) {
if (error) {
TSLog(@"获取剩余空间失败: %@", error.localizedDescription);
return;
}
TSLog(@"表盘剩余空间: %ld 字节", (long)remainSpace);
}];

注册表盘变化监听

- (void)registerDialDidChangedBlock:(void (^)(NSArray<TSDialModel *> *_Nullable allDials))completion;
参数类型说明
completionvoid (^)(NSArray<TSDialModel *> *)表盘变化回调
[dialInterface registerDialDidChangedBlock:^(NSArray<TSDialModel *> * _Nullable allDials) {
if (allDials == nil) {
TSLog(@"无法获取表盘信息");
return;
}
TSLog(@"表盘已变化,当前共有 %lu 个表盘", (unsigned long)allDials.count);
for (TSDialModel *dial in allDials) {
if (dial.isCurrent) {
TSLog(@"当前表盘: %@", dial.dialName);
}
}
}];

取消表盘推送

- (void)cancelPushDial:(TSCompletionBlock)completion;
参数类型说明
completionvoid (^)(BOOL, NSError *)完成回调
[dialInterface cancelPushDial:^(BOOL isSuccess, NSError * _Nullable error) {
if (isSuccess) {
TSLog(@"表盘推送已取消");
} else {
TSLog(@"取消表盘推送失败: %@", error.localizedDescription);
}
}];

获取内置表盘最大数量

- (NSInteger)maxInnerDialCount;
返回值类型说明
NSInteger设备支持的内置表盘最大数量
NSInteger maxCount = [dialInterface maxInnerDialCount];
TSLog(@"设备支持的内置表盘最大数量: %ld", (long)maxCount);

获取可推送表盘最大数量

- (NSInteger)maxCanPushDialCount;
返回值类型说明
NSInteger设备可以存储的表盘最大数量
NSInteger maxPushCount = [dialInterface maxCanPushDialCount];
TSLog(@"设备可推送的表盘最大数量: %ld", (long)maxPushCount);

检查幻灯片表盘支持

- (BOOL)isSupportSlideshowDial;
返回值类型说明
BOOL是否支持幻灯片表盘
if ([dialInterface isSupportSlideshowDial]) {
TSLog(@"设备支持幻灯片表盘");
} else {
TSLog(@"设备不支持幻灯片表盘");
}

检查视频表盘支持

- (BOOL)isSupportVideoDial;
返回值类型说明
BOOL是否支持视频表盘
if ([dialInterface isSupportVideoDial]) {
TSLog(@"设备支持视频表盘");
} else {
TSLog(@"设备不支持视频表盘");
}

检查表盘组件支持

- (BOOL)isSupportDialComponent;
返回值类型说明
BOOL是否支持表盘组件
if ([dialInterface isSupportDialComponent]) {
TSLog(@"设备支持表盘组件");
}

获取视频表盘最大时长

- (NSInteger)maxVideoDialDuration;
返回值类型说明
NSInteger最大视频时长(秒)
NSInteger maxDuration = [dialInterface maxVideoDialDuration];
TSLog(@"视频表盘最大时长: %ld 秒", (long)maxDuration);

获取设备支持的挂件列表

- (void)requestSupportWidgetsFromPeripheralCompletion:(TSDialWidgetsBlock)completion;
参数类型说明
completionvoid (^)(NSDictionary *, NSError *)完成回调,返回挂件信息字典
[dialInterface requestSupportWidgetsFromPeripheralCompletion:^(NSDictionary * _Nullable widgets, NSError * _Nullable error) {
if (error) {
TSLog(@"获取挂件列表失败: %@", error.localizedDescription);
return;
}
if (widgets) {
TSLog(@"设备支持的挂件: %@", widgets);
}
}];

生成表盘预览图

- (void)previewImageWith:(UIImage *)originImage 
timeImage:(UIImage *)timeImage
timePosition:(TSDialTimePosition)timePosition
maxKBSize:(CGFloat)maxKBSize
completion:(void (^)(UIImage *_Nullable, NSError *_Nullable))completion;
参数类型说明
originImageUIImage *背景图片
timeImageUIImage *时间显示图片
timePositionTSDialTimePosition时间位置
maxKBSizeCGFloat最大文件大小(KB)
completionvoid (^)(UIImage *, NSError *)完成回调
UIImage *background = [UIImage imageNamed:@"dial_bg"];
UIImage *timeImg = [UIImage imageNamed:@"time_style"];

[dialInterface previewImageWith:background
timeImage:timeImg
timePosition:eTSDialTimePositionTop
maxKBSize:300
completion:^(UIImage * _Nullable previewImage, NSError * _Nullable error) {
if (error) {
TSLog(@"生成预览图失败: %@", error.localizedDescription);
return;
}
TSLog(@"预览图生成成功");
}];

根据表盘项生成预览图

- (void)previewImageWithDialItem:(TSCustomDialItem *)dialItem 
maxKBSize:(CGFloat)maxKBSize
completion:(void (^)(UIImage *_Nullable, NSError *_Nullable))completion;
参数类型说明
dialItemTSCustomDialItem *自定义表盘项
maxKBSizeCGFloat最大文件大小(KB)
completionvoid (^)(UIImage *, NSError *)完成回调
TSCustomDialItem *item = [[TSCustomDialItem alloc] init];
item.dialType = eTSCustomDialSingleImage;
item.resourceImage = [UIImage imageNamed:@"dial_background"];
item.dialTime = [[TSCustomDialTime alloc] init];
item.dialTime.timeImage = [UIImage imageNamed:@"time_style"];
item.dialTime.timePosition = eTSDialTimePositionTop;

[dialInterface previewImageWithDialItem:item
maxKBSize:300
completion:^(UIImage * _Nullable previewImage, NSError * _Nullable error) {
if (error) {
TSLog(@"生成预览图失败: %@", error.localizedDescription);
return;
}
TSLog(@"预览图生成成功");
}];

注意事项

  1. 表盘模型区分:使用 TSDialModel 处理设备表盘信息和云端表盘操作,使用 TSCustomDial 创建和推送自定义表盘。

  2. 图片尺寸要求严格:背景图片必须与设备屏幕尺寸完全匹配(通过 TSPeripheralScreen.screenSize 获取),预览图片必须与预览尺寸匹配(通过 TSPeripheralScreen.dialPreviewSize 获取)。

  3. 内置表盘不可删除:只能删除自定义表盘和云端表盘,内置表盘无法通过接口删除。

  4. 推送操作异步执行:表盘推送是异步操作,完成回调会被多次调用,需要根据 TSDialPushResult 判断推送状态。

  5. 表盘变化监听:同时只能注册一个表盘变化回调,新的注册会替换之前的回调。

  6. 存储空间检查:推送新表盘前应检查剩余存储空间,确保有足够空间。

  7. 视频表盘限制:视频表盘有最大时长限制,需先检查设备是否支持视频表盘。

  8. 时间位置优先级:timeRect 优先于 timePosition 使用,如果设置了有效的 timeRect 则忽略 timePosition