The situation gets even worse if you need to triple-check to support, for example, older widgets without interaction, iOS 17 widgets with interaction, and the new iOS 18 control widgets.
If you use the above workaround with three versions, it will result in an error: Function declares an opaque return type 'some Widget', but the return statements in its body do not have matching underlying types
Code with error:
var body: some Widget {
if #available(iOS 18.0, *) {
return body_iOS18
} else if #available(iOS 17.0, *) {
return body_iOS17
} else {
return body_old
}
}
So you have to create ugly things like:
var body: some Widget {
if #available(iOS 17.0, *) {
return body_new
} else {
return body_old
}
}
@available(iOSApplicationExtension 17.0, *)
var body_new: some Widget {
if #available(iOS 18.0, *) {
return body_iOS18
} else {
return body_iOS17
}
}