Watch开发:Complications教程

Complications 是 watchOS 2 新加入的特性,它是表盘上的小界面元素,用于自定义表盘,可以支持直接从表盘唤起自己的App。

1240
Paste_Image.png

苹果提供了一个新的FrameWork ClockKit, ClockKit 会提供一些模板CLKComplicationTemplate给我们,我们选择样式、填充自己想要展示的数据,ClockKit会在某时间点向我们请求数据, 并负责将其渲染在表盘上。

新建项目

  1. watchOS > Application > iOS App with WatchKit App
1240
Paste_Image.png

2.配置,勾选Include Complication

1240
Paste_Image.png

3.如果项目已经创建,打开Target -> WatchKit Extension.你会看到Complications Configuration配置项。Supported Families 底下的五项代表着app要支持的complication families

1240
Paste_Image.png

这是这些Families成员对应的在表盘上的风格

1240
Paste_Image.png

4.创建complication
打开ClockKit Introduction WatchKit Extension中的ComplicationController,这个文件是勾选了Include Complication后Xcode自动为我们生成的。它包含一个ComplicationController类,实现了CLKComplicationDataSource协议. CLKComplicationDataSource中的方法决定了你向ClockKit提供数据的方式,这些方法里都有个handler的参数,你需要在自己的实现中回调 handle,并把自己的数据作为handler回传给ClockKit. 这是我们和ClockKit通信的方式:

1240
Paste_Image.png

数据模版 Template:

Template是ClockKit为开发者定义的数据模型,但是它并不单纯是数据模型,不同的模版有不同视图布局的风格

比如,对5种Complication类型,类型和布局:

typedef NS_ENUM(NSInteger, CLKComplicationFamily) {
    CLKComplicationFamilyModularSmall                                                         = 0,
    CLKComplicationFamilyModularLarge                                                         = 1,
    CLKComplicationFamilyUtilitarianSmall                                                     = 2,
    CLKComplicationFamilyUtilitarianSmallFlat   /* subset of UtilitarianSmall */              = 6,
    CLKComplicationFamilyUtilitarianLarge                                                     = 3,
    CLKComplicationFamilyCircularSmall                                                        = 4,
    CLKComplicationFamilyExtraLarge                                                           = 7,
};
1240
Paste_Image.png
1240
Paste_Image.png

比如,对于CLKComplicationTemplateModularLargeStandardBody
这个类,它的属性和布局对应如下:

1240
Paste_Image.png
ImageProviders|CLKTextProvider

在 WWDC中说,这里用ImageProvider而不是UIImage, 用TextProvider而不是NSString,是因为在watch表盘的complication视图尺寸很小,防止出现文本截断等一些不好的体验,开发者使用Provider可以更好说明自己的意图 , 同时ClockKit会为我们做布局和显示的其他工作。

1240
Paste_Image.png
@interface Show : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *shortName;
@property (nonatomic, strong) NSString *genre;
@property (nonatomic, strong) NSDate *startDate;
@property (nonatomic, assign) NSTimeInterval length;
@end

@implementation Show

- (instancetype)initWithName:(NSString *)name
                   shortName:(NSString *)shortName
                       genre:(NSString *)genre
                   startDate:(NSDate *)startDate
                      length:(NSTimeInterval)length
{
    self = [super init];
    _name = name;
    _shortName = shortName;
    _genre = genre;
    _startDate = startDate;
    _length = length;
    return self;
}

//  App第一次启动时,ClockKit会调用这个方法来获取一个complications 模版,作为placeHolder模版展示。
- (void)getPlaceholderTemplateForComplication:(CLKComplication *)complication withHandler:(void (^)(CLKComplicationTemplate * _Nullable))handler
{
    Show *s = [[Show alloc] initWithName:@"Intdo the Wild" shortName: @"Into Wild" genre:@"Documentary" startDate:[NSDate date] length:hour*1.5];
    Show *s2 = [[Show alloc] initWithName:@"24/7" shortName: nil genre:@"Drama" startDate:[NSDate dateWithTimeIntervalSinceNow:hour*1.5] length:hour];
    Show *s3 = [[Show alloc] initWithName:@"How to become rich" shortName: @"Become Rich" genre:@"Documentary" startDate:[NSDate dateWithTimeIntervalSinceNow:hour*2.5] length:hour];
    _shows = @[s, s2, s3];

    CLKComplicationTemplateModularLargeStandardBody *template = [[CLKComplicationTemplateModularLargeStandardBody alloc] init];
    template.headerTextProvider = [CLKTimeIntervalTextProvider textProviderWithStartDate:[NSDate date] endDate:[NSDate dateWithTimeIntervalSinceNow:60*60*1.5]];
    template.body1TextProvider = [CLKSimpleTextProvider textProviderWithText:@"Short Name" shortText:@"Name"];
    template.body2TextProvider = [CLKSimpleTextProvider textProviderWithText:@"Show Genre" shortText:nil];

    handler(template);
}

TimeLines

TimeLine是ClockKit抽象出来的一个时间轴。开发者的数据单元用CLKComplicationTimelineEntry 模型包装,绑定在timeline上某一点时刻. 当时间走到那一刻,ClockKit会自动将我们传给的数据内容展示在表盘。在某个时间段中,ClockKit 会一直展示上一刻展示的数据, 直到下一刻数据更新点。如下图:

1240
Paste_Image.png

在[11, 12) 这个域,表盘上的温度展示的是11am的时候绑定的数据55。12PM这一刻,又更新为56.
再比如说日历应用需要提前提醒用户"4:00-5:00要剪头发",开发者就需要把"4:00-5:00要剪头发"这个提示绑定在1PM这个时刻上,而不是直接绑在4PM这个时间点上。 如下图:

1240
Paste_Image.png
CLKComplicationDataSource协议类中跟timeline相关的方法
// 时间前进的方向,如果是回忆的时间轴,可以选CLKComplicationTimeTravelDirectionBackward
- (void)getSupportedTimeTravelDirectionsForComplication:(CLKComplication *)complication withHandler:(void(^)(CLKComplicationTimeTravelDirections directions))handler {
   handler(CLKComplicationTimeTravelDirectionForward);
}
​
// 时间轴的起始点,ClockKit回调这个方法获取最早一个时刻,我们在实现中调用hander这个Block来给ClockKit传递
// 那一刻需要展示的数据,因为不需要展示过去的数据,这里我们用当前时间
- (void)getTimelineStartDateForComplication:(CLKComplication *)complication withHandler:(void(^)(NSDate * __nullable date))handler {
   handler([NSDate date]);
}

​
- (void)getTimelineEndDateForComplication:(CLKComplication *)complication withHandler:(void(^)(NSDate * __nullable date))handler {
   handler([NSDate dateWithTimeIntervalSinceNow:60*60*24]);
}
CLKComplicationTimelineEntry

在代码实现中,CLKComplicationTimelineEntry这个类,包含一个date属性,可以将Template数据绑定在时间轴的某一个时刻上。

1240
Paste_Image.png
1240
Paste_Image.png
获取当前时刻的单条数据
- (void)getCurrentTimelineEntryForComplication:(CLKComplication *)complication withHandler:(void(^)(CLKComplicationTimelineEntry * __nullable))handler
{
    // Call the handler with the current timeline entry
    Show *s = _shows[0];
    CLKComplicationTemplateModularLargeStandardBody *template = [[CLKComplicationTemplateModularLargeStandardBody alloc] init];
    template.headerTextProvider = [CLKTimeIntervalTextProvider textProviderWithStartDate:s.startDate
                                                                                 endDate:[NSDate dateWithTimeInterval:s.length sinceDate:s.startDate]
                                                                                timeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT+0900"]];
    template.body1TextProvider = [CLKSimpleTextProvider textProviderWithText:s.name shortText:s.shortName];
    template.body2TextProvider = [CLKSimpleTextProvider textProviderWithText:s.genre shortText:nil];
    // 数据绑定的时间为当前时间
    CLKComplicationTimelineEntry *entry = [CLKComplicationTimelineEntry entryWithDate:[NSDate date] complicationTemplate:template];

    handler(entry);
}

ClockKit会回调这个方法,Extension通过调用handler,向ClockKit回传数据

1240
Paste_Image.png
绑定多条数据

那么如果我想给ClockKit提供其他时刻的数据呢? 这里,我们在时间轴上每15分钟绑定一条数据,我们需要用到- (void)getTimelineEntriesForComplication:(CLKComplication *)complication afterDate:(NSDate *)date limit:(NSUInteger)limit withHandler:(void(^)(NSArray<CLKComplicationTimelineEntry *> * __nullable entries))handler方法。

- (void)getTimelineEntriesForComplication:(CLKComplication *)complication afterDate:(NSDate *)date limit:(NSUInteger)limit withHandler:(void(^)(NSArray<CLKComplicationTimelineEntry *> * __nullable entries))handler
{
    // Call the handler with the timeline entries after to the given date
    NSMutableArray *entries = [[NSMutableArray alloc] init];
    for (Show *s in _shows)
    {
        // ClockKit有个数限制
        if (entries.count < limit && [s.startDate timeIntervalSinceDate:date] >0)
        {
            CLKComplicationTemplateModularLargeStandardBody *template = [[CLKComplicationTemplateModularLargeStandardBody alloc] init];
            template.headerTextProvider = [CLKTimeIntervalTextProvider textProviderWithStartDate:s.startDate
                                                                                         endDate:[NSDate dateWithTimeInterval:s.length sinceDate:s.startDate]
                                                                                        timeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT+0900"]];
            template.body1TextProvider = [CLKSimpleTextProvider textProviderWithText:s.name shortText:s.shortName];
            template.body2TextProvider = [CLKSimpleTextProvider textProviderWithText:s.genre shortText:nil];
            // 数据绑定在时间轴不同的时刻上
            CLKComplicationTimelineEntry *entry = [CLKComplicationTimelineEntry entryWithDate:[NSDate dateWithTimeInterval:s.length sinceDate:s.startDate] complicationTemplate:template];
            [entries addObject:entry];
        }
    }

    // 数组回传给ClockKit
    handler(entries);
}

如图

1240
Paste_Image.png


如果要绑定在当前时间之前的数据实现另一个方法

1240
Paste_Image.png

现在进行真机调试,Xcode schema中选择Complication,手机和watch提前配置好,run

调试

  1. 按下 Digital Crown 以前往表盘。
  1. 用力按压显示屏。模拟器 Command+Shift+2
    1240
    Paste_Image.png
  2. 向左或向右轻扫以选取某个表盘,然后轻点“自定”。 模拟器 Command+Shift+1
1240
Paste_Image.png
  1. 向左或向右轻扫以选择某个功能,然后转动 Digital Crown 对其进行更改。例如,您可以更改秒针的颜色或表盘上的标记。
1240
Paste_Image.png
  1. 向左轻扫至最左边,以编辑功能栏。轻点某个功能栏以将其选中,然后转动 Digital Crown 对其进行更改。您也可以添加来自其他应用的功能栏。

  2. 完成后,按下 Digital Crown 以存储您的更改。

文字没显示出来,呃,先到这儿,明天看看。

Demo


参考文章
https://developer.apple.com/library/content/documentation/General/Conceptual/WatchKitProgrammingGuide/ComplicationEssentials.html#//apple_ref/doc/uid/TP40014969-CH27-SW1
https://code.tutsplus.com/tutorials/an-introduction-to-clockkit--cms-24247
http://www.informit.com/articles/article.aspx?p=2429818
Templates 和Provider https://www.bignerdranch.com/blog/watchkit-2-complications/
http://www.sneakycrab.com/blog/2015/6/10/writing-your-own-watchkit-complications



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Untracked files are those in a Git repository that are not yet being version-controlled. When you try to merge or rebase branches, Git may warn you about uncommitted changes or untracked files that could conflict with the target branch or create an inconsistent state. The warning "Untracked Files Prevent Merge: Move or commit them before merge" suggests that you should address these files before proceeding with the merge operation to ensure a clean and smooth merge. Here's what you should do: 1. **List untracked files:** Use `git status` to see which files are untracked. This will help you identify which files need to be added to the staging area or committed first. 2. **Add untracked files:** If the files are meant to be part of your repository, use `git add <file>` to stage them for commit. Or if they're temporary or unrelated, you might choose to exclude them. 3. **Commit changes:** If there are staged changes, use `git commit -m "Commit message"` to save the changes to a new commit. 4. **Resolve conflicts (if any):** If there are tracked changes that conflict with the untracked files, you'll need to manually resolve the conflicts using tools like `git mergetool`. 5. **Clean up**: After resolving conflicts and committing changes, run `git status` again to verify that there are no uncommitted changes left. 6. **Merge or rebase**: Once the files are either committed or excluded, you can safely proceed with the merge or rebase operation. Remember that keeping your Git history clean is essential for collaboration and understanding the project's development history. By managing untracked files appropriately, you avoid introducing unnecessary complications in the merge process.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值