Bringing my iPad app to Mac Catalyst as iPad idiom. Primary interface is a UISplitViewController. Two things I think are bugs unless someone replies with a fix.
SplitViewController is setup in two column with left column as sidebar:
split.setViewController(primary, for: .primary)
split.setViewController(secondary, for: .secondary)
split.preferredDisplayMode = .oneBesideSecondary
split.preferredSplitBehavior = .tile
split.presentsWithGesture = true
#if targetEnvironment(macCatalyst)
split.primaryBackgroundStyle = .sidebar
split.displayModeButtonVisibility = .never
#endif
The displayMode button aligns vertically with the navigation bar and below the 3 window control buttons (close, minimize, full screen), whereas on other macOS apps using SplitViewController such as Apple Notes app, the displayMode button aligns vertically and just to the right of the the 3 window control buttons (close, minimize, full screen). I downloaded the Apple Example app called Menus that is supposed to be a prime example of a Mac Catalyst app, and I see author must have faced the same bug and instead created their own displayMode button and placed it on the UITitlebar's toolBar.
In my secondary ViewController which is a subclass of a UITableViewController, tapping a row, calls show and in a SplitViewController, that pushes another detailVC onto the Nav stack as expected. The UIWindowScene's UITitlebar which appears over the top of the secondary VC looks correct.
This detailVC is a subclass of a UITableViewController. Finally, tapping a row in the table of the detailVC calls show but this time, the ViewController is actually a UIHostingViewController wrapping a SwiftUI View. At this point the UIWindowScene's UITitlebar changes appearance and takes on the same lightened color similar to the sidebar (primary) appearance.
With UITitlebarTitleVisibility set to hidden and if I set the titlebar.toolbar to nil, (which removes the UITitlebar, there is no appearance issue.
Running on iPad, with no UITitlebar, there is no odd lightening experienced when the UIHostingController is shown. I think this has something to do with the UIHostingController within Mac Catalyst.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Posting here for wider visibility...
All over the internet, apple discussions, etc. Seems that this is affecting thousands of people but apparently not millions...othewise we'd have a fix by now. This started showing up in iOS 18 beta and then continued into 18.0, 18.1, and now 18.2
Symptoms are unable to retrieve emails from IMAP mail server. Some have mentioned Dovecot IMAP server. This author happens to have Dovecot IMAP and yes, once iOS 18.0, 18.x was installed, email sync no longer works.
Topic:
App & System Services
SubTopic:
General
I'm trying to implement a Help Window from Help Menu in macOS (Mac Catalyst). I have SceneConfiguration in Info.plist and multi-window enabled. Tapping Help menu opens a new Help Window on macOS. I thought it was working great!
Unfortunately, tapping Help menu again opens a new Help Window. I only want one Help window to be shown.
I expected UIApplication.shared.activateSceneSession(for: request) to use an existing UIScene if one was already present. In my experience I always get a new Scene and thus a new Window. What am I missing?
AppDelegate.swift
func application(_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// It's important that each UISceneConfiguration have a unique configuration name.
var configurationName: String!
switch options.userActivities.first?.activityType {
case UserActivity.HelpMenuActivityType:
configurationName = SceneConfiguration.helpWindowConfiguration
default:
configurationName = SceneConfiguration.defaultConfiguration
}
return UISceneConfiguration(name: configurationName, sessionRole: connectingSceneSession.role)
}
override func buildMenu(with builder: UIMenuBuilder) {
super.buildMenu(with: builder)
...
builder.remove(menu: .help)
builder.insertSibling(helpMenu(), afterMenu: .window)
}
func helpMenu() -> UIMenu {
let children: [UIAction] = [
UIAction(...
) { [weak self] action in
self?.helpMenuTappedHandler(action)
}
]
....
}
func helpMenuTappedHandler(_ action: UIAction) {
let userActivity: NSUserActivity = ...
userActivity.targetContentIdentifier = ...
let options: UIScene.ActivationRequestOptions = .init()
options.requestingScene = ...
let request: UISceneSessionActivationRequest = .init(role: .windowApplication, userActivity: userActivity, options: options)
UIApplication.shared.activateSceneSession(for: request, errorHandler: handleHelpError)
}
I submitted a Mac Catalyst app for TestFlight and before it can be tested by external testers it requires an App Review. The iOS app passed review, but the Mac Catalyst app failed review.
The rejection reason given was that App Sandbox needed the entitlement:
"com.apple.security.network.client" to be YES / true (not false).
I do have "com.apple.security.device.bluetooth" set to YES / true.
The Developer docs for entitlement "com.apple.security.network.client" say "Use this key to allow your sandboxed app to connect to a server process running on another machine, or on the same machine." for entitlement "com.apple.security.network.client", then go on to discuss TCP and UDP. https://developer.apple.com/documentation/security/app_sandbox
While technically a Bluetooth app connecting to another Bluetooth device puts the app in "client mode" and the device in "server mode", I think this network entitlement was intended for TCP / UDP, not Bluetooth.
The entitlement "com.apple.security.device.bluetooth" says
"A Boolean value indicating whether your app may interact with Bluetooth devices." - this seems to cover all the necessary needs for Bluetooth "your app may interact with Bluetooth devices".....
Would someone at Apple familiar with the docs please clarify what entitlements are required for an app that only uses Bluetooth?
If the "com.apple.security.network.client" is required, then I believe the docs for that property should also specify Bluetooth.
Topic:
App Store Distribution & Marketing
SubTopic:
App Review
&TLDR; I see no documentation stating that during the life of UISplitViewController, that I cannot call setViewController(xxxxx, column) more than once on the same column. Yet in my experience calling it a second time does not work, unless I set the value to nil before calling it again to set it to the new value...
I'm using a UISplitViewController in newer column-style layout and when bootstrapping the app, I create the UISplitViewController and use setViewController(primaryViewController, .primary) and setViewController(detailViewController, .secondary).
In order to use the primaryViewController for the compact scenario, I return the .primary column in the UISplitViewControllerDelegate method:
splitViewController(_ svc: UISplitViewController, topColumnForCollapsingToProposedTopColumn proposedTopColumn: UISplitViewController.Column) -> UISplitViewController.Column
Tapping a cell in the primaryViewController, results in a call to
splitViewController.show(.secondary)
This works for both split view (primary + secondary) as well as in compact mode.
Tapping a cell in the secondary viewController results in pushing a new sub-detail onto the navigation sack. Again so far so good.
If I switch back to split mode (primary+secondary) it still looks good with secondary showing the sub-detail.
If I then collapse into compact view, the primary is once again shown. If I tap a different cell in the primary, the same call to:
splitViewController.show(.secondary)
results in the sub-detail viewController being shown. Instead, I want the secondary to show the detail for the new selected cell...not the sub-detail of the prior cell.
To fix this, I popped the navigation stack for the secondary to rootViewController
if secondaryNavigationController.topViewController as? DetailViewController == nil {
secondaryNavigationController.popToRootViewController(animated: false)
next, I attempted to replace splitViewController's secondary viewController by assigning the secondaryNavigationController which now has the DetailViewController as the top (and only) viewController.
splitViewController.setViewController(secondaryNavigationController, for: .secondary)
after this assignment, calling
splitViewController.viewController(for: .secondary)
returns the old sub-detail viewController, not the expected DetailViewController!
IMO this is a bug.
I found the following solution. First set it to nil, then set it to the desired value.
splitViewController.setViewController(nil, for: .secondary)
splitViewController.setViewController(secondaryNavigationController, for: .secondary)
Topic:
UI Frameworks
SubTopic:
UIKit