Complications not rendering in Watch Series 9

I just got my new Apple Watch series 9 - woo! But I loaded a couple of my test apps onto it - and the complications are not rendering. They work fine on my "old" series 6 (both are on WatchOS 10).

I tried resizing them. They run and render fine in the simulator. But this is how it looks on my actual watch (the upper 2 complications are mine).

Answered by darkpaw in 765691022

You need to implement .containerBackground() - which is new in watchOS 10. It doesn't work on watchOS 9, so simply adding it will bring compile errors.

To get it to work I have a 'backport' extension, as per Dave DeLong's blog here: https://davedelong.com/blog/2021/10/09/simplifying-backwards-compatibility-in-swift/

Here's how to implement it:

// MARK: - Backports

public struct Backport<Content> {
	public let content: Content

	public init(_ content: Content) {
		self.content = content
	}
}

extension View {
	var backport: Backport<Self> { Backport(self) }
}

extension Backport where Content: View {
	@ViewBuilder func containerBackground(_ backgroundView: some View) -> some View {
		if #available(watchOS 10.0, iOSApplicationExtension 17.0, iOS 17.0, macOSApplicationExtension 14.0, *) {
			content.containerBackground(for: .widget) {
				backgroundView
			}

		} else {
			backgroundView
		}
	}

	@ViewBuilder func widgetCurvesContent() -> some View {
		if #available(watchOS 10.0, iOSApplicationExtension 17.0, iOS 17.0, macOSApplicationExtension 14.0, *) {
			content.widgetCurvesContent()

		} else {
			content
		}
	}
}

I've also added a widgetCurvesContent function so you can see how to use it for other, simpler cases. As the blog says, naming these functions the same as the one they're implementing means it's easy to move forward when you no longer have to support a backport. You would just delete the function from the extension, let Xcode's errors tell you where you were using it, and remove the .backport bit, i.e. .backport.containerBackground(...) -> .containerBackground(...).

Now, to use it:

.backport.containerBackground(
	Circle()
		.fill(.red.gradient)
		.opacity(0.75)
)

Here, you're passing in a Circle object as the backgroundView to the backport.containerBackground function. If you're using watchOS 10 it will apply the containerBackground function with your backgroundView. If you're on watchOS 9 it falls back to just applying the backgroundView.

For the simpler case of applying a modifier to something like the text in a corner widget to make it curved, you can use .widgetCurvesContent(). Again, this is only available in watchOS 10+, so you can use the backport function .backport.widgetCurvesContent().

Hope this helps.

Accepted Answer

You need to implement .containerBackground() - which is new in watchOS 10. It doesn't work on watchOS 9, so simply adding it will bring compile errors.

To get it to work I have a 'backport' extension, as per Dave DeLong's blog here: https://davedelong.com/blog/2021/10/09/simplifying-backwards-compatibility-in-swift/

Here's how to implement it:

// MARK: - Backports

public struct Backport<Content> {
	public let content: Content

	public init(_ content: Content) {
		self.content = content
	}
}

extension View {
	var backport: Backport<Self> { Backport(self) }
}

extension Backport where Content: View {
	@ViewBuilder func containerBackground(_ backgroundView: some View) -> some View {
		if #available(watchOS 10.0, iOSApplicationExtension 17.0, iOS 17.0, macOSApplicationExtension 14.0, *) {
			content.containerBackground(for: .widget) {
				backgroundView
			}

		} else {
			backgroundView
		}
	}

	@ViewBuilder func widgetCurvesContent() -> some View {
		if #available(watchOS 10.0, iOSApplicationExtension 17.0, iOS 17.0, macOSApplicationExtension 14.0, *) {
			content.widgetCurvesContent()

		} else {
			content
		}
	}
}

I've also added a widgetCurvesContent function so you can see how to use it for other, simpler cases. As the blog says, naming these functions the same as the one they're implementing means it's easy to move forward when you no longer have to support a backport. You would just delete the function from the extension, let Xcode's errors tell you where you were using it, and remove the .backport bit, i.e. .backport.containerBackground(...) -> .containerBackground(...).

Now, to use it:

.backport.containerBackground(
	Circle()
		.fill(.red.gradient)
		.opacity(0.75)
)

Here, you're passing in a Circle object as the backgroundView to the backport.containerBackground function. If you're using watchOS 10 it will apply the containerBackground function with your backgroundView. If you're on watchOS 9 it falls back to just applying the backgroundView.

For the simpler case of applying a modifier to something like the text in a corner widget to make it curved, you can use .widgetCurvesContent(). Again, this is only available in watchOS 10+, so you can use the backport function .backport.widgetCurvesContent().

Hope this helps.

Thanks for your reply and code sample! Works for me!

Complications not rendering in Watch Series 9
 
 
Q