Post

Replies

Boosts

Views

Activity

How to modify context menu shown in a UITextView?
In my iPad app running under macOS Catalyst I would like to modify the context menu that appears when you right-click on a UITextViiew but I can't figure out how.I have overridden the buildMenuWithBulder:/buildMenu(with:) method from UIResponder in my view controller and app delegate but none are called when right-clicking on a UITextView.I have been able to disable a couple of the menu options by subclassing UITextView and overriding the canPerformAction:withSender:/canPerformAction(_:withSender:) and targetForAction:withSender:/target(_:withSender:) methods but I can't remove/disable most of the menu.I also overrode the validateCommand:/validate(_:) method in my UITextView subclass and that was only called for a small subset of the menus I wish to remove/disable.The Menus sample app only shows how to modify the app's main menu and how to add a context menu to a view controller but there is no info on how to modify the context menu of a control such as UITextView.Does anyone know how to do this?Specifically I want to remove the Show Fonts and Show Colors menus under Font and I wish to remove the whole Substitutions menu. The allowsEditingTextAttributes property of the text view is enabled which is what makes the Font portion of the menu appear. I want to keep the Bold/Italic/Underline toggles.
2
0
3.6k
May ’23
How to get the AVCam demo app to work under Mac Catalyst?
My own iOS app is using AVFoundation to do barcode scanning. Under Mac Catalyst I'm getting an error. Turns out the Apple provided AVCam demo app has the exact same issue.Both the Swift and Objective-C versions of the AVCam demo app fail but the Objective-C version gives a better error so I'll refer to that in the rest of the question.In the AVCamCameraViewController, the configureSession method fails on the line:AVCaptureDeviceInput* videoDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];The error is:Could not create video device input: Error Domain=AVFoundationErrorDomain Code=-11814 "Cannot Record" UserInfo={NSLocalizedDescription=Cannot Record, NSLocalizedRecoverySuggestion=Try recording again.}It turns out that none of the three attempts to call [AVCaptureDevice defaultDeviceWithDeviceType:... are succeeding.This is the same error I get in my own app though I only attempt to call [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; which is also returning nil.Permission was granted for the app to access the camera.There is nothing related to this issue in the release notes for macOS 10.15. I am running the GM version of 10.15 with Xcode 11.1 on a 2018 15" Macbook Pro.How do we successfully get a video capture device under Mac Catalyst?
5
0
4.4k
May ’23
iOS 26 UIKIt: Where's the missing cornerConfiguration property of UIViewEffectView?
In WWDC25 video 284: Build a UIKit app with the new design, there is mention of a cornerConfiguration property on UIVisualEffectView. But this properly isn't documented and Xcode 26 isn't aware of any such property. I'm trying to replicate the results of that video in the section titled Custom Elements starting at the 19:15 point. There is a lot of missing details and typos in the code associated with that video. My attempts with UIGlassEffect and UIViewEffectView do not result in any capsule shapes. I just get rectangles with no rounded corners at all. As an experiment, I am trying to recreate the capsule with the layers/location buttons in the iOS 26 version of the Maps app. I put the following code in a view controller's viewDidLoad method let imgCfgLayer = UIImage.SymbolConfiguration(hierarchicalColor: .systemGray) let imgLayer = UIImage(systemName: "square.2.layers.3d.fill", withConfiguration: imgCfgLayer) var cfgLayer = UIButton.Configuration.plain() cfgLayer.image = imgLayer let btnLayer = UIButton(configuration: cfgLayer, primaryAction: UIAction(handler: { _ in print("layer") })) var cfgLoc = UIButton.Configuration.plain() let imgLoc = UIImage(systemName: "location") cfgLoc.image = imgLoc let btnLoc = UIButton(configuration: cfgLoc, primaryAction: UIAction(handler: { _ in print("location") })) let bgEffect = UIGlassEffect() bgEffect.isInteractive = true let bg = UIVisualEffectView(effect: bgEffect) bg.contentView.addSubview(btnLayer) bg.contentView.addSubview(btnLoc) view.addSubview(bg) btnLayer.translatesAutoresizingMaskIntoConstraints = false btnLoc.translatesAutoresizingMaskIntoConstraints = false bg.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ btnLayer.leadingAnchor.constraint(equalTo: bg.contentView.leadingAnchor), btnLayer.trailingAnchor.constraint(equalTo: bg.contentView.trailingAnchor), btnLayer.topAnchor.constraint(equalTo: bg.contentView.topAnchor), btnLoc.centerXAnchor.constraint(equalTo: bg.contentView.centerXAnchor), btnLoc.topAnchor.constraint(equalTo: btnLayer.bottomAnchor, constant: 15), btnLoc.bottomAnchor.constraint(equalTo: bg.contentView.bottomAnchor), bg.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor), bg.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40), ]) The result is pretty close other than the complete lack of capsule shape. What changes would be needed to get the capsule shape? Is this even the proper approach?
12
5
763
Sep ’25
Summary of iOS/iPadOS 26 UIKit bugs related to UISearchController & UISearchBar using scope buttons
All of these issues appear when the search controller is set on the view controller's navigationItem and the search controller's searchBar has its scopeButtonTitles set. So far the following issues are affecting my app on iOS/iPadOS 26 as of beta 7: When the scopeBarActivation of UISearchController is set to .onSearchActivation, the preferredSearchBarPlacement of the navigationItem is set to .integratedButton, and the searchBarPlacementAllowsToolbarIntegration is set to false (forcing the search icon to appear in the nav bar), on both iPhones and iPads, the scope buttons never appear. They don't appear when the search is activated. They don't appear when any text is entered into the search bar. FB19771313 I attempted to work around that issue by setting the scopeBarActivation to .manual. I then show the scope bar in the didPresentSearchController delegate method and hide the scope bar in the willDismissSearchController. On an iPhone this works though the display is a bit clunky. On an iPad, the scope bar does appear via the code in didPresentSearchController, but when any scope bar button is tapped, the search controller is dismissed. This happens when the app is horizontally regular. When the app on the iPad is horizontally compact, the buttons work but the search bar's text is not correctly aligned within the search bar. Quite the mess really. I still need to post a bug report for this issue. But if issue 1 above is fixed then I don't need this workaround. When the scopeBarActivation of UISearchController is set to .onSearchActivation, the preferredSearchBarPlacement of the navigationItem is set to .stacked, and the hidesSearchBarWhenScrolling property of the navigationItem is set to false (always show the search bar), and this is all used in a UITableViewController, then upon initial display of the view controller on an iPhone or iPad, you are unable to tap on the first row of the table view except on the very bottom of the row. The currently hidden scope bar is stealing the touches. If you activate and then cancel the search (making the scope bar appear and then disappear) then you are able to tap on the first row as expected. The initially hidden scope bar also bleeds through the first row of the table. It's faint but you can tell it's not quite right. Again, this is resolved by activating and then canceling the search once. FB17888632 When the scopeBarActivation of UISearchController is set to .onSearchActivation, the preferredSearchBarPlacement of the navigationItem is set to integrated or .integratedButton, and the toolbar is shown, then on iPhones (where the search bar/icon appears in the toolbar) the scope buttons appear (at the top of the screen) the first time the search is activated. But if you cancel the search and then activate it again, the search bar never appears a second (or later) time. On an iPad the search bar/icon appears in the nav bar and you end up with the same issue as #1 above. FB17890125 Issues 3 and 4 were reported against beta 1 and still haven't been fixed. But if issue 1 is resolved on iPhone, iPad, and Mac (via Mac Catalyst), then I personally won't be affected by issues 2, 3, or 4 any more (but of course all 4 issues need to be fixed). And by resolved, I mean that the scope bar appears and disappears when it is supposed to each and every time the search is activated and cancelled (not just the first time). The scope bar doesn't interfere with touch events upon initial display of the view controller. And there are no visual glitches no matter what the horizontal size class is on an iPad. I really hope the UIKit team can get these resolved before iOS/iPadOS 26 GM.
10
5
805
Nov ’25
PHPickerViewController unusable via Mac Catalyst on macOS 26 when interface is "Scaled to Match iPad"
There is a serious usability issue with PHPickerViewController in a UIKit app running on macOS 26 via Mac Catalyst when the Mac Catalyst interface is set to “Scaled to Match iPad”. Mouse click and other pointer interactions do not take place in the correct position. This means you have to click in the wrong position to select a photo and to close the picker. This basically makes it unusable. To demonstrate, use Xcode 26 on macOS 26 to create a new iOS app project based on Swift/Storyboard. Then update ViewController.swift with the following code: import UIKit import PhotosUI class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() var cfg = UIButton.Configuration.plain() cfg.title = "Photo Picker" let button = UIButton(configuration: cfg, primaryAction: UIAction(handler: { _ in self.showPicker() })) button.translatesAutoresizingMaskIntoConstraints = false view.addSubview(button) NSLayoutConstraint.activate([ button.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor), button.centerYAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerYAnchor), ]) } private func showPicker() { var config = PHPickerConfiguration() config.selectionLimit = 10 config.selection = .ordered let vc = PHPickerViewController(configuration: config) vc.delegate = self self.present(vc, animated: true) } } extension ViewController: PHPickerViewControllerDelegate { func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { print("Picked \(results.count) photos") dismiss(animated: true) } } Then go to the "Supported Destinations" section of the project target. Add a "Mac (Mac Catalyst)" destination. Then under the "Deployment Information" section, make sure the "Mac Catalyst Interface" setting is "Scaled to Match iPad". Then build and run the app on a Mac (using the Mac Catalyst destination) with macOS 26.0.1. Make sure the Mac has a dozen or so pictures in the Photo Library to fully demonstrate the issue. When the app is run, a simple screen appears with one button in the middle. Click the button to bring up the PHPickerViewController. Now try to interact with the picker interface. Note that all pointer interactions are in the wrong place on the screen. This makes it nearly impossible to choose the correct photos and close the picker. Quit the app. Select the project and go to the General tab. In the "Deployment Info" change the “Mac Catalyst Interface” setting to “Optimize for Mac” and run the app again. Now the photo picker works just fine. If you run the app on a Mac running macOS 15 then the photo picker works just fine with either “Mac Catalyst Interface” setting. The problem only happens under macOS 26.0 (I do not have macOS 26.1 beta to test) when the “Mac Catalyst Interface” setting is set to “Scaled to Match iPad”. This is critical for my app. I cannot use “Optimize for Mac”. There are far too many issues with that setting (I use UIStepper and UIPickerView to start). So it is critical to the usability of my app under macOS 26 that this issue be resolved. It is expected that PHPickerViewController responds correctly to pointer events on macOS 26 when running a Mac Catalyst app set to “Scaled to Match iPad”. A version of this has been filed as FB20503207
12
4
612
Oct ’25
Under Xcode 26 beta 3, how to support new glass icons for iOS 26 and old icons for iOS 18?
I know there are several existing threads on this topic but things keep changing. The release notes for Xcode 26 beta 3 have the following statements for a couple of resolved issues: Asset Catalog Fixed: Unable to set Icon Composer icon as alternate iOS icon (153305178) (FB18025356) Icon Composer Fixed: Icon Composer icons back deploy to older versions of iOS, macOS, and watchOS with inconsistent rendering. (152258860) I had a working solution under beta 1 and beta 2 for both of these. But under beta 3, I am now seeing the new glass icons for my app when running on a simulated iOS 18 device. This is happening for both the main app icon and any alternates. This contradicts the statement that beta 3 fixes this issue. There is no documentation (that I can find) describing how you are supposed to support old icons for iOS 18 and new glass icons for iOS 26. There is no documentation for how to support alternate glass icons for iOS 26. What I'm doing at the moment (that worked before beta 3) was to have the normal iOS 18 app icons in the Asset catalog and to have the new glass icons added to the project. The filenames for the glass .icon files have the same name as the app icons in the Assets catalog. This worked under beta 1 and beta 2. And despite the Xcode 26 beta 3 release notes stating that Icon Composer icons no longer back deploy to iOS 18, I'm seeing the opposite. Beta 3 now does the opposite of that statement. Does anyone have a working solution that supports old iOS 18 app icons and new iOS 26 glass icons using Xcode 26 beta 3? Note, all of my testing is with simulated iOS devices and I'm running Xcode 26 beta 3 under macOS 15.5. Maybe that's an issue?
2
3
296
Jul ’25
How to change the app name shown in a Catalyst app?
Working on the Mac Catalyst version of an iPad app. I don't know if this is a bug, intended behavior, or a setting I am missing. But how do you change (or what value is used) the app name shown in the main menu and the About box? For example, let's say my app's "Bundle name" in Info.plist is "MyCoolApp" and the "Bundle display name" is "My Cool App". When the app is run on iOS, I see "My Cool App" under the icon on the home screen. Perfect. But on the Mac, the app's main menu shows "MyCoolApp". Tapping on that menu includes the "About MyCoolApp" menu. The About box also shows "MyCoolApp" under the app icon. Other standard default menus also reference "MyCoolApp". I want all of those to show "My Cool App", not "MyCoolApp". What needs to be changed to get the "Bundle display name" to be used?
5
2
7.5k
Sep ’22
How do you get the cursor to appear programmatically in a custom UITextInput with UITextInteraction?
I have created a custom input field by conforming to UITextInput. It is setup to use UITextInteraction. Everything works very well. If the user taps on the custom field, the cursor (provided by UITextInteraction) appears. The user can type, select, move the cursor, etc. But I'm stumped trying to get the cursor to appear automatically. With a normal UITextField or UITextView you simply call becomeFirstResponder(). But doing that with my custom UITextInput does not result in the cursor appearing. It only appears if the user taps on the custom field. I don't know what I'm missing. I don't see any API in UITextInteraction that can be called to say "activate the cursor layer". Does anyone know what steps are required with a custom UITextInput using UITextInteraction to activate the cursor programmatically without the user needing to tap on the custom field?
4
0
1.5k
Aug ’24
How to get UIFont to respect preferredContentSizeCategory in a Mac Catalyst app?
I have an iOS app that relies on dynamic text size such that all fonts in the app respect the user's setting of Text Size in the iOS Settings app. This app also runs on macOS via Mac Catalyst. But until macOS 14 Sonoma, there was no Text Size setting in the macOS Settings app. But even as of Sonoma, the Text Size setting isn't usable by 3rd party apps. And Sequoia doesn't seem to change that. As a work around, my Mac Catalyst app provides its own Text Size setting. I was able to make it work by providing my own UIApplication subclass and overriding preferredContentSizeCategory. Under macOS 12 to macOS 14, this workaround works just fine and all fonts in the app created with code such as UIFont.preferredFont(forTextStyle:) gives appropriately sized fonts based on the overridden content size category. However, this workaround stopped working with macOS 15 Sequoia. I've also tried code such as: self.window.traitOverrides.preferredContentSizeCategory = myCustomSizeCategoryValue and self.window.maximumContentSizeCategory = myCustomSizeCategoryValue self.window.minimumContentSizeCategory = myCustomSizeCategoryValue in the scene delegate but that made no difference. Is there any way to get code such as UIFont.preferredFont(forTextStyle:) to return an appropriately sized font based on some app provided content size category in a Mac Catalyst app running under macOS 15? It sure would be nice if Mac Catalyst apps automatically responded to the macOS Text Size setting under Settings -> Accessibility -> Display -> Text Size just like a native iOS app.
3
1
711
Apr ’25
iOS 26 RC: Scope buttons never appear for integrated UISearchBar
When trying to use a UISearchController setup with a UISearchBar that has scope buttons, the search controller's scopeBarActivation property is set to .onSearchActivation, the navigation item's preferredSearchBarPlacement property is set to .integrated. or .integratedButton, and the search bar/button appears in the navigation bar, then the scope buttons never appear. But space is made for where they should appear. Some relevant code in a UIViewController shown as the root view controller of a UINavigationController: private func setupSearch() { let sc = UISearchController(searchResultsController: UIViewController()) sc.delegate = self sc.obscuresBackgroundDuringPresentation = true // Setup search bar with scope buttons let bar = sc.searchBar bar.scopeButtonTitles = [ "One", "Two", "Three", "Four" ] bar.selectedScopeButtonIndex = 0 bar.delegate = self // Apply the search controller to the nav bar navigationItem.searchController = sc // BUG - Under iOS/iPadOS 26 RC, using .onSearchActivation results in the scope buttons never appearing at all // when using integrated placement in the nav bar. // Ensure the scope buttons appear immediately upon activating the search controller sc.scopeBarActivation = .onSearchActivation // This works but doesn't show the scope buttons until the user starts typing - that's too late for my needs //sc.scopeBarActivation = .automatic if #available(iOS 26.0, *) { // Under iOS 26 put the search icon in the nav bar - same issue for .integrated and .integratedButton navigationItem.preferredSearchBarPlacement = .integrated // .integratedButton // My toolbar is full so I need the search in the navigation bar navigationItem.searchBarPlacementAllowsToolbarIntegration = false // Ensure it's in the nav bar } else { // Under iOS 18 put the search bar in the nav bar below the title navigationItem.preferredSearchBarPlacement = .stacked } } I need the search bar in the navigation bar since the toolbar is full. And I need the scope buttons to appear immediately upon search activation. This problem happens on any real or simulated iPhone or iPad running iOS/iPadOS 26 RC.
1
1
223
Sep ’25
iOS 26 RC: Scope button in stacked UISearchBar block touches
This is really odd. If you setup a UISearchController with a preferredSearchBarPlacement of .stacked and you setup the search bar with scope buttons, then when the view controller is initially displayed, the currently hidden scope buttons block touch events from reaching the main view just below the search bar. But once the search is activated and dismissed, then the freshly hidden scope buttons no longer cause an issue. This is easily demonstrated by putting a UITableViewController in a UINavigationController. Setup the table view to show a few simple rows. Then setup a search controller using the following code: func setupSearch() { // Setup a stacked search bar with scope buttons // Before the search is ever activated, the hidden scope buttons block any touches in the main view controller // in the area just below the search bar. // Once the search is activated and dismissed, the problem goes away. It seems that displaying and hiding the // scope buttons at least once fixes the issue that exists beforehand. // This issue only exists in iOS/iPadOS 26, not iOS/iPadOS 18 or earlier. let search = UISearchController(searchResultsController: UIViewController()) search.hidesNavigationBarDuringPresentation = true search.obscuresBackgroundDuringPresentation = true search.scopeBarActivation = .onSearchActivation // Ensure button appear immediately let searchBar = search.searchBar searchBar.scopeButtonTitles = [ "One", "Two", "Three" ] self.navigationItem.searchController = search self.navigationItem.hidesSearchBarWhenScrolling = false // Issue appears even if this is true self.navigationItem.preferredSearchBarPlacement = .stacked } When first shown, before any attempt is made to activate the search, any attempt to tap on the upper 2/3 of the first row in the table view (which is just below the search bar) fails. If you tap on the lower 1/3 of the first row it works fine. If you then activate the search (now the scope buttons appear) and then dismiss the search (now the scope buttons are hidden again), then there is no issue tapping anywhere on the first row of the table. But if you restart the app, the problem starts over again. This problem happens on any iPhone or iPad, real or simulated, running iOS/iPadOS 26 RC. This is a regression from iOS 18 or earlier.
3
1
379
Nov ’25
How to turn off background extension effect in UISplitViewController?
I have a triple-column UISplitViewController setup in "tile" mode. Each of the 3 columns has a table view controller. Under iPadOS 26, the section headers and row selection in the middle table extends all the way to the left of the screen, behind the primary column. It looks terrible. The documentation for "Adopting Liquid Glass" makes it sound like you can add this behavior by using UIBackgroundExtensionView. But I get this behavior automatically in a UISplitViewController. How do I turn this off? I created a simpler sample using a double-column split view with two table view controllers. Here's a screenshot of the result: Note how the section headers and the row selection appear all the way to the left edge of the screen. I don't want that effect. How do you turn off this effect in a UISplitViewController? Here is the code used to setup the split view and the app's main window: func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let winScene = (scene as? UIWindowScene) else { return } let primary = PrimaryViewController(style: .plain) let primaryNC = UINavigationController(rootViewController: primary) let detail = DetailViewController(style: .plain) let detailNC = UINavigationController(rootViewController: detail) let sv = UISplitViewController(style: .doubleColumn) sv.preferredDisplayMode = .oneBesideSecondary sv.preferredSplitBehavior = .tile sv.primaryBackgroundStyle = .none sv.displayModeButtonVisibility = .automatic sv.setViewController(primaryNC, for: .primary) sv.setViewController(detailNC, for: .secondary) let win = UIWindow(windowScene: winScene) win.rootViewController = sv win.makeKeyAndVisible() window = win } The PrimaryViewController and DetailViewController are simple UITableViewController subclasses that only add a few rows and section headers as needed.
5
1
213
Oct ’25
How to disable tab editing in a UITabBarController sidebar?
I’m creating a UITabBarController with a simple array of UITab instances. I’m setting the mode to .tabSideBar. How do I prevent editing? I don’t want the Edit button to appear at all. I’ve tried setting the tab controller’s customizableViewControllers property to both nil and an empty array but neither is preventing the Edit button from appearing. I scanned the various delegates and I don‘t see any relevant methods. So far I’ve tested this on a simulated iPad running iPadOS 26 using Xcode 26 RC.
2
0
135
Sep ’25
How to manually install iOS 26 Simulator download archive?
For difficult reasons I won’t get into, I ended up manually downloading the latest iOS 26 simulator runtime. I now have a file named 78756498-8AB4-4E5A-986C-7AA435758657.aar copied to my Mac. How do I get this archive installed so Xcode 26 recognizes it as a proper simulator runtime component? All searching I‘ve done for manually installing simulators references dmg files and older versions of Xcode. There’s no mention of aar files. When I tried the command: sudo xcrun simctl runtime add ./78756498-8AB4-4E5A-986C-7AA435758657.aar I get the result: An error was encountered processing the command (domain=NSPOSIXErrorDomain, code=22): Error while creating AEA backend Invalid argument I tried to use Archive Utility to open the file but that just says it is unable to expand the file. I even tried renaming the file with a dmg extension and then tried mounting the file and I get the same “AEA backend” error. My Mac doesn’t have sufficient Internet access to let me download and install this normally through Xcode. I need to find a way to get this file installed manually.
3
1
579
Sep ’25
How to enable the "Paste and Match Style" context menu in a UITextView?
The UIResponderStandardEditActions protocol includes pasteAndMatchStyle:. UITextView conforms to UIResponderStandardEditActions. But I can't find a way to get that menu to appear. I get the standard "Paste" menu. I've tried overriding pasteAndMatchStyle: in a subclass of UITextView. I've overridden canPerformAction:withSender: but it never gets called with the pasteAndMatchStyle: selector. I've implemented the textView:editMenuForTextInRange:suggestedActions: delegate method. It's called but the suggested actions do not include the "Paste and Match Style" action (key command). I came up with an ugly hack that involved overriding buildMenuWithBuilder: and adding my own key command after the paste command. But this shouldn't be necessary considering it's supposed to be a standard edit action. So what's the trick to make the "Paste and Match Style" edit menu appear properly in a UITextView? I'm testing with iOS 17, 18, and 26.
2
0
179
Sep ’25