Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'NSApp' is unavailable in UIKit for Mac: How to embed Mac only framework in iOS app on macOS?

UIKit for Mac

I’m exploring the new possibilities with Xcode 11 and macOS Catalina to create a Mac version of an iPad app using UIKit. Generally works as expected.

What’s the best way to customize the NSWindow in an iOS app on macOS?


Go Beyond the Checkbox

https://developer.apple.com/documentation/uikit/creating_a_mac_version_of_your_ipad_app

You can use these same approaches to include a framework and code that are available only in macOS. For a framework, select macOS for the platform setting, and enclose the code with a #if targetEnvironment(UIKitForMac) statement.

As a starting point, I created a basic macOS framework (e.g.MacMan.framework) to configure Mac specific behaviors.

Despite my best attempts, I run into errors:

  • 'NSApp' is unavailable in UIKit for Mac
  • 'NSWindow' is unavailable in UIKit for Mac
  • Building for UIKit for Mac, but the linked framework 'MacMan.framework' is building for macOS. You may need to configure 'MacMan.framework' to build for UIKit for Mac or restrict the platforms for which this framework should be linked in the target editor.

The opposite seems true (easy to exclude code)

#if !targetEnvironment(UIKitForMac)

override var prefersHomeIndicatorAutoHidden: Bool {
    return true
}

#endif

References:

https://www.highcaffeinecontent.com/blog/20190607-Beyond-the-Checkbox-with-Catalyst-and-AppKit

like image 535
Zelko Avatar asked Jun 30 '19 22:06

Zelko


People also ask

Does UIKit work on macOS?

Mac Catalyst, also refereed to as "UIKit for Mac", allows you to build [iOS and iPadOD](iOS projects to run natively on the Mac, while still being utilizing the UIKit and other iOS specific APIs and design paradigms.

Is UIKit a framework?

Overview. The UIKit framework provides the core objects that you need to build apps for iOS and tvOS. You use these objects to display your content onscreen, to interact with that content, and to manage interactions with the system.

How do you use Mac catalyst?

With the Xcode project set up to use Mac Catalyst, build and run the Recipes app on your Mac, and take a look at the features the new version supports. Choose Product > Destination > My Mac. Setting the Build destination to My Mac builds a local version of the Recipes app. Check for build errors before running the app.


1 Answers

According to Apple, if your app depends on a framework that is built for the macOS, you will need to either exclude it from any iOS builds, or you will need to rebuild it for iOS and macOS, so that you can conditionalize code that is only available in either iOS or macOS. For that, Apple recommends that you transform that into an xcframework. Because the framework that you depend on points to NSApp and NSWindow, which are symbols not available on iOS, you are getting the errors that you mention.

Therefore, if you have the source code for the MacMan.framework, you need to work on it to transform it into an xcframework by conditionalizing code that has a dependency on a specific platform, because they refer to frameworks that are unavailable on the other platform.

If you do not own the source code, then you need to talk to the vendor of the framework to provide you with such a binary. If that is not possible, then you will have to exclude the MacMan.framework, which was specifically built for the macOS platform.

All this is explained in the WWDC 2019 video called "Introducing iPad apps for Mac".

Moreover, I also recommend that you check the related videos on the same page to know what to do. Finally, to learn how to build an xcframework watch the video "Binary Frameworks in Swift". Don't be fooled by the latter video's title: you can also build xcframeworks in Objective-C, in case that you need it.

If you need to customize a window background, you cannot do that via NSWindow; as I explained above this API is not available, but you need to use its iOS counterpart: UIWindow. In this case, you can change a window background like this:

self.view.window.backgroundColor = .red

self being your UIViewController.

Another possible customization is to add a toolbar, as NSToolbar is now exported via:

let toolbar = UIWindowScene.titlebar.toolbar

A fuller explanation and the caveats of adding and customizing an NSToolbar in a UIKit app for Mac is explained here.

like image 156
jvarela Avatar answered Nov 08 '22 16:11

jvarela