Can an Action Extension use SwiftUI for its UI?

I'm trying to update an app of mine to have a more modern look, and the last part of it is the Action Extension in Safari.

My info.plist file has the correct NSExtension details to use a storyboard, but storyboards look so old and I'd like to use a nicer SwiftUI-based look. Is this even possible?

This is the relevant bit from the Info.plist:

<dict>
  <key>NSExtensionAttributes</key>
  <dict>
    <key>NSExtensionActivationRule</key>
    <dict>
      <key>NSExtensionActivationSupportsWebPageWithMaxCount</key>
      <integer>1</integer>
    </dict>
    <key>NSExtensionJavaScriptPreprocessingFile</key>
    <string>GetURL</string>
  </dict>
  <key>NSExtensionPointIdentifier</key>
  <string>com.apple.ui-services</string>
  <key>NSExtensionActionWantsFullScreenPresentation</key>
  <false/>
  <key>NSExtensionMainStoryboard</key>
  <string>MainInterface</string>
</dict>

I see I can use NSExtensionPrincipalClass instead of NSExtensionMainStoryboard but then I get stuck.

If I remove this:

<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>

and replace it with this:

<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).ActionViewController</string>

I get this error when I run the extension:

Rejecting view controller creation request due to invalid extension storyboard or principal class: Error Domain=NSCocoaErrorDomain Code=967223 "(null)" UserInfo={Invalid Configuration=Either NSExtensionMainStoryboard or NSExtensionPrincipalClass must be specified in the extension's Info.plist file but not both.}

According to that error the two keys are mutually-exclusive, which is fine as I'm using just one of them, so why do I get this error?

Is it something to do with the actual code in ActionViewController?

I have this, and nothing here ever runs:

class ActionViewController: UIViewController {
	var theUrl: String = ""

	@objc override func viewDidLoad() {
		super.viewDidLoad()

		if let inputItem = extensionContext!.inputItems.first as? NSExtensionItem {
			if let itemProvider = inputItem.attachments?.first {
				itemProvider.loadItem(forTypeIdentifier: UTType.propertyList.identifier as String) { [unowned self] (dict, error) in
					let itemDictionary = dict as! NSDictionary
					let javaScriptValues = itemDictionary[NSExtensionJavaScriptPreprocessingResultsKey] as! NSDictionary
					self.theUrl = javaScriptValues["URL"] as! String

					// Build the SwiftUI view, wrap it in a UIHostingController then send to the main thread to update the UI
					let contentView = ActionExtensionView(theUrl: self.theUrl, clickedCancel: self.cancel, clickedDone: self.done)
					let childView = UIHostingController(rootView: contentView)
					self.view.addSubview(childView.view)

					// Set the place where your view will be displayed
					let constraints = [
						childView.view.topAnchor.constraint(equalTo: view.topAnchor),
						childView.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
						childView.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
						childView.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
						childView.view.widthAnchor.constraint(equalTo: view.widthAnchor),
						childView.view.heightAnchor.constraint(equalTo: view.heightAnchor)
					]
					childView.view.translatesAutoresizingMaskIntoConstraints = false
					view.addConstraints(constraints)

					DispatchQueue.main.async {
						self.present(childView, animated: true)
					}
				}
			}
		}
	}

Apple really don't make it easy to develop for their platforms, do they?

Answered by darkpaw in 823498022

Ah, it seems to be an issue with Xcode. You have to build and run your app containing the extension, then you can run the extension itself.

Seems a bit daft, and really slows you down.

https://developer.apple.com/forums/thread/748073

Accepted Answer

Ah, it seems to be an issue with Xcode. You have to build and run your app containing the extension, then you can run the extension itself.

Seems a bit daft, and really slows you down.

https://developer.apple.com/forums/thread/748073

Can an Action Extension use SwiftUI for its UI?
 
 
Q