Добавьте новые графические расширения 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 или новее.
Это означает, что Watch Series 3 с watchOS 5 или 6 (из-за if #available(watchOSApplicationExtension 5.0, *)
) попытаются загрузить изображение сложности из каталога активов. Однако, поскольку истончение приложений включено по умолчанию, Watch Series 3 не не имеет изображения в двоичном виде, поэтому следующая строка приведет к краху приложения:
let image = UIImage(named: "Complication/Graphic Corner")!
Мы обнаружили это, когда нашли тысячи отчетов о сбоях в Xcode:
- Откройте Xcode
- Окно -> Органайзер
- Выберите вкладку Сбои
- Выберите версию App Store
Мы нашли отчет о сбое для каждого из двух поддерживаемых графических расширений, все они были с 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()
, которая используется во всех трех обязательных функциях делегата:
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
}
}
person
Martijn
schedule
03.09.2020