6

我想为 watchOS 3 创建一个复杂功能,它只会启动我的应用程序。我使用 XCode 创建了 ComplicationController:

class ComplicationController: NSObject, CLKComplicationDataSource
{

    // MARK: - Timeline Configuration

    func getSupportedTimeTravelDirections(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimeTravelDirections) -> Void) {
        handler([.forward, .backward])
    }

    func getTimelineStartDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) {
        handler(nil)
    }

    func getTimelineEndDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) {
        handler(nil)
    }

    func getPrivacyBehavior(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationPrivacyBehavior) -> Void) {
        handler(.showOnLockScreen)
    }

    // MARK: - Timeline Population

    func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
        // Call the handler with the current timeline entry
        handler(nil)
    }

    func getTimelineEntries(for complication: CLKComplication, before date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) {
        // Call the handler with the timeline entries prior to the given date
        handler(nil)
    }

    func getTimelineEntries(for complication: CLKComplication, after date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) {
        // Call the handler with the timeline entries after to the given date
        handler(nil)
    }

    // MARK: - Placeholder Templates

    func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) {
        // This method will be called once per supported complication, and the results will be cached
        handler(nil)
    }

}

并为循环、模块化和实用资产添加了图像。但是当我运行 Watch 应用程序时,我无法为表盘选择我的复杂功能。我还需要做什么?

谢谢

格雷格

4

4 回答 4

13

这些代码更改是必需的:

func getSupportedTimeTravelDirections(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimeTravelDirections) -> Void)
{
    handler([])
}


func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void)
{
    if complication.family == .circularSmall
    {

        let template = CLKComplicationTemplateCircularSmallRingImage()
        template.imageProvider = CLKImageProvider(onePieceImage: UIImage(named: "Circular")!)
        let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
        handler(timelineEntry)

    } else if complication.family == .utilitarianSmall
    {

        let template = CLKComplicationTemplateUtilitarianSmallRingImage()
        template.imageProvider = CLKImageProvider(onePieceImage: UIImage(named: "Utilitarian")!)
        let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
        handler(timelineEntry)

    } else if complication.family == .modularSmall
    {

        let template = CLKComplicationTemplateModularSmallRingImage()
        template.imageProvider = CLKImageProvider(onePieceImage: UIImage(named: "Modular")!)
        let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
        handler(timelineEntry)

    } else {

        handler(nil)

    }

}


func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void)
{        
    switch complication.family
    {
        case .circularSmall:
            let image: UIImage = UIImage(named: "Circular")!
            let template = CLKComplicationTemplateCircularSmallSimpleImage()
            template.imageProvider = CLKImageProvider(onePieceImage: image)
            handler(template)
        case .utilitarianSmall:
            let image: UIImage = UIImage(named: "Utilitarian")!
            let template = CLKComplicationTemplateUtilitarianSmallSquare()
            template.imageProvider = CLKImageProvider(onePieceImage: image)
            handler(template)
        case .modularSmall:
            let image: UIImage = UIImage(named: "Modular")!
            let template = CLKComplicationTemplateModularSmallSimpleImage()
            template.imageProvider = CLKImageProvider(onePieceImage: image)
            handler(template)
        default:
            handler(nil)
    }
}

另外,您需要在扩展程序中提供图像作为资产。

于 2016-09-26T22:27:25.243 回答
2

Apple Watch 4 新的图形复杂功能如下所示:

func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
    // Call the handler with the current timeline entry
    switch complication.family {
    case .graphicCorner:
        if #available(watchOSApplicationExtension 5.0, *) {
            let template = CLKComplicationTemplateGraphicCornerCircularImage()
            let image = UIImage(named: "Complication/Graphic Corner")!
            template.imageProvider = CLKFullColorImageProvider(fullColorImage: image)
            let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
            handler(timelineEntry)
        } else {
            handler(nil)
        }
    case .graphicCircular:
        if #available(watchOSApplicationExtension 5.0, *) {
            let template = CLKComplicationTemplateGraphicCircularImage()
            let image = UIImage(named: "Complication/Graphic Circular")!
            template.imageProvider = CLKFullColorImageProvider(fullColorImage: image)
            let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
            handler(timelineEntry)
        } else {
            handler(nil)
        }
    default:
        handler(nil)
    }
}

func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) {
    // This method will be called once per supported complication, and the results will be cached
    switch complication.family {
    case .graphicCorner:
        if #available(watchOSApplicationExtension 5.0, *) {
            let template = CLKComplicationTemplateGraphicCornerCircularImage()
            let image = UIImage(named: "Complication/Graphic Corner")!
            template.imageProvider = CLKFullColorImageProvider(fullColorImage: image)
            handler(template)
        } else {
            handler(nil)
        }
    case .graphicCircular:
        if #available(watchOSApplicationExtension 5.0, *) {
            let template = CLKComplicationTemplateGraphicCircularImage()
            let image = UIImage(named: "Complication/Graphic Circular")!
            template.imageProvider = CLKFullColorImageProvider(fullColorImage: image)
            handler(template)
        } else {
            handler(nil)
        }
    default:
        handler(nil)
    }
}
于 2019-08-26T06:53:24.367 回答
1

添加 Apple Watch 4 新的图形复杂功能(watchOS 5.0+)并防止Apple Watch Series 1、2 和 3 崩溃。

重要提示:来自 Zoltan 的代码将在 Apple Watch 系列 3 或更低版本上崩溃。

根据Apple 文档,新的图形复杂功能需要 watchOS 5.0 或更高版本以及Watch Series 4 或更高版本:

注意支持图形模板的表盘仅适用于 Apple Watch Series 4 或更新机型。

这意味着带有 watchOS 5 或 6 的 Watch Series 3(由于if #available(watchOSApplicationExtension 5.0, *))将尝试从资产目录加载复杂功能图像。但是,由于默认情况下启用了App Thinning,Watch Series 3 的二进制文件中没有图像,因此以下行将使应用程序崩溃

let image = UIImage(named: "Complication/Graphic Corner")!

当我们在 Xcode 中发现数以千计的崩溃报告时,我们发现了这一点:

  1. 打开 Xcode
  2. 窗口 -> 组织者
  3. 选择选项卡“崩溃”
  4. 选择 App Store 版本

我们为我们支持的 2 种图形并发症中的每一种都找到了崩溃报告,所有这些都与 watchOS 5 或 6 以及 Watch Series 2 或 3 一起使用,例如:

在此处输入图像描述

解决方案

在 IF 语句中嵌入图形资源的加载并nil作为模板返回,因此它不会在没有资源的设备上崩溃。

上面来自 Zoltan的示例将是:

case .graphicCorner:
        if #available(watchOSApplicationExtension 5.0, *) {
            let template = CLKComplicationTemplateGraphicCornerCircularImage()
            if let image = UIImage(named: "Complication/Graphic Corner") {
                template.imageProvider = CLKFullColorImageProvider(fullColorImage: image)
                let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
                handler(timelineEntry)
            } else {
                handler(nil)
            }
        } else {
            handler(nil)
        }

为了高效且可维护的代码,我们创建了一个可重用的函数templateForComplication(),用于所有 3 个强制委托函数:

class ComplicationController: NSObject, CLKComplicationDataSource {
    
    // MARK: Mandatory Delegate Methods
    
    func getSupportedTimeTravelDirections(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimeTravelDirections) -> Void) {
        // Turn off time travelling:
        handler([])
    }
    
    func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
        let template = templateForComplication(complication: complication)
        let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template!)
        handler(timelineEntry)
    }
    
    func getPlaceholderTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) {
        // This method will be called once per supported complication, and the results will be cached
        handler(templateForComplication(complication: complication))
    }
    
    func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) {
        handler(templateForComplication(complication: complication))
    }
    
    
    // MARK: Helper Methods
    
    private func templateForComplication(complication: CLKComplication) -> CLKComplicationTemplate? {
        // Init default output:
        var template: CLKComplicationTemplate? = nil
        
        // Graphic Complications are only availably since watchOS 5.0:
        if #available(watchOSApplicationExtension 5.0, *) {
            // NOTE: Watch faces that support graphic templates are available only on Apple Watch Series 4 or later. So the binary on older devices (e.g. Watch Series 3) will not contain the images.
            if complication.family == .graphicCircular {
                let imageTemplate = CLKComplicationTemplateGraphicCircularImage()
                // Check if asset exists, to prevent crash on non-supported devices:
                if let fullColorImage = UIImage(named: "Complication/Graphic Circular") {
                    let imageProvider = CLKFullColorImageProvider.init(fullColorImage: fullColorImage)
                    imageTemplate.imageProvider = imageProvider
                    template = imageTemplate
                }
            }
            else if complication.family == .graphicCorner {
                let imageTemplate = CLKComplicationTemplateGraphicCornerCircularImage()
                // Check if asset exists, to prevent crash on non-supported devices:
                if let fullColorImage = UIImage(named: "Complication/Graphic Corner") {
                    let imageProvider = CLKFullColorImageProvider.init(fullColorImage: fullColorImage)
                    imageTemplate.imageProvider = imageProvider
                    template = imageTemplate
                }
            }
        }
        
        // For all watchOS versions:
        if complication.family == .circularSmall {
            let imageTemplate = CLKComplicationTemplateCircularSmallSimpleImage()
            let imageProvider = CLKImageProvider(onePieceImage: UIImage(named: "Complication/Circular")!)
            imageProvider.tintColor = UIColor.blue
            imageTemplate.imageProvider = imageProvider
            template = imageTemplate
        }
        else if complication.family == .modularSmall {
            let imageTemplate = CLKComplicationTemplateModularSmallSimpleImage()
            let imageProvider = CLKImageProvider(onePieceImage: UIImage(named: "Complication/Modular")!)
            imageProvider.tintColor = UIColor.blue
            imageTemplate.imageProvider = imageProvider
            template = imageTemplate
        }
        else if complication.family == .utilitarianSmall {
            let imageTemplate = CLKComplicationTemplateUtilitarianSmallSquare()
            let imageProvider = CLKImageProvider(onePieceImage: UIImage(named: "Complication/Utilitarian")!)
            imageProvider.tintColor = UIColor.blue
            imageTemplate.imageProvider = imageProvider
            template = imageTemplate
        }
        
        return template
    }
}
于 2020-09-03T07:12:46.700 回答
0

@zoltan-vinkler 对 Apple Watch 7 的回答

func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
    // Call the handler with the current timeline entry
    switch complication.family {
        case .graphicCircular:
            let image = UIImage(named: "Complication/Graphic Circular")!
            let template = CLKComplicationTemplateGraphicCircularImage(imageProvider: CLKFullColorImageProvider(fullColorImage: image))
            let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
            handler(timelineEntry)
        default:
            handler(nil)
    }
}

func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
    // Call the handler with the current timeline entry
    switch complication.family {
        case .graphicCircular:
            let image = UIImage(named: "Complication/Graphic Circular")!
            let template = CLKComplicationTemplateGraphicCircularImage(imageProvider: CLKFullColorImageProvider(fullColorImage: image))
            let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
            handler(timelineEntry)
        default:
            handler(nil)
    }
}
于 2021-08-29T13:46:52.033 回答