A widget using Button(intent:) { } will crash on macOS 13, even after restricting the button to macOS 14 using if #available(macOS 14, *) { }

I have a widget with a button that prints "Hello" to the console when tapped. This button is shown only on iOS 17.x and macOS 14.x, and is supposed to be hidden on lower versions.

Platform versions tested: iOS 16.6, iOS 17 beta 7 (21A5319a), macOS 13.4.1

Xcode version used: 15.0 beta 7 (15A5229h).

Expected behaviour: The button is hidden on iOS 16.x and macOS 13.x, and shown only on iOS 17 and macOS 14.

Observed behaviour: The button is hidden on iOS 16.6. However, on macOS 13.4.1, the widget crashes with this error:

dyld[5266]: Symbol not found: _$s7SwiftUI6ButtonV012_AppIntents_aB0E6intent5labelACyxGqd___xyXEtc0dE00D6IntentRd__lufC Referenced from: <3EB03A2B-BF9A-31EC-88B9-B4CF015DD35D> /Users/user/Library/Developer/Xcode/DerivedData/WidgetIntentTest-hfjndspaaxqvyuhgdzlznjikilce/Build/Products/Debug/WidgetIntentTest.app/Contents/PlugIns/WidgetExtension.appex/Contents/MacOS/WidgetExtension Expected in: <0A9F8825-DAF1-39A5-953C-C5ECACDC1B0B> /System/Library/Frameworks/_AppIntents_SwiftUI.framework/Versions/A/_AppIntents_SwiftUI

Here's the code:

The widget code with the button:

import WidgetKit
import SwiftUI

struct WidgetsEntryView: View {
    var entry: Provider.Entry
    
    @available(iOS 17, macOS 14, *)
    var button: some View {
        Button(intent: SayHelloIntent()) {
            Text("Say hello")
        }
    }
    
    var body: some View {
        VStack {
            Text("Hello there")
            #if os(iOS)
            if #available(iOS 17, *) {
                button
            }
            #elseif os(macOS)
            if #available(macOS 14, *) {
                button
            }
            #endif
        }
        //ignore this if on iOS 16 or macOS 13
         .widgetBackground(backgroundView: Color.clear)
    }
}

The rest of the widget code

struct Provider: TimelineProvider {
    func placeholder(in context: Context) -> SimpleEntry {
        SimpleEntry(date: Date())
    }
    
    func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
        completion(SimpleEntry(date: Date()))
    }
    
    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        let timeline = Timeline(entries: [SimpleEntry(date: Date())], policy: .atEnd)
        completion(timeline)
    }
}

struct SimpleEntry: TimelineEntry {
    let date: Date
}


struct Widgets: Widget {
    let kind: String = "Widgets"
    
    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider()) { entry in
            WidgetsEntryView(entry: entry)
        }
        .configurationDisplayName("My Widget")
        .description("This is an example widget.")
    }
}

@main
struct WidgetIntentTestBundle: WidgetBundle {
    var body: some Widget {
        Widgets()
    }
}

//ignore this if on iOS 16 or macOS 13
extension View {
    func widgetBackground(backgroundView: some View) -> some View {
        #if os(iOS)
        if #available(iOSApplicationExtension 17.0, *) {
            return containerBackground(for: .widget) {
                backgroundView
            }
        } else {
            return background(backgroundView)
        }
        #elseif os(macOS)
        return background(backgroundView)
        #endif
    }
}

App Intent

import AppIntents
import WidgetKit

struct SayHelloIntent: AppIntent {
    static var title: LocalizedStringResource = "Say Hello"
    static var description = IntentDescription("prints hello to the console.")
    
    func perform() async throws -> some IntentResult {
        print("Hello")
        return .result()
    }
}

The app's ContentView

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Hello World")
        }
        .padding()
    }
}

Is anyone else experiencing this issue? The Button initialiser I'm using is marked as available on macOS 13, so I don't see a reason why the widget would crash with that error (which I understand is because it can't find the Button code in SwiftUI on macOS 13.

For what it's worth the widget doesn't crash and works as expected when built using Mac catalyst 16.

Any help is welcome!

Answered by stxrk in 763263022

Updating to Xcode 15 beta 8 fixes this issue.

Accepted Answer

Updating to Xcode 15 beta 8 fixes this issue.

It still doednt work even on production version of Xcode 15. The same situation with ios16/17. If I do not add the widget with Button(intent) to widget bundle then all is fine, otherwise not. App is compiled with ios 16.

A widget using Button(intent:) { } will crash on macOS 13, even after restricting the button to macOS 14 using if #available(macOS 14, *) { }
 
 
Q