Looking to get column resizing events for UISplitViewController. I have a UITableView inside on of the columns and when the column is resized I need to invalidate the intrinsic content size of the table view cells to recompute row height.
Best place to handle this?
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Working on a Mac Catalyst app. I have a UInavigationController. On iOS this is full screen but on Mac Catalyst I'm using it inside a UISplitViewController in the supplementary column.
This view controller's root view controller has a navigationItem which configures a UISearchController. The search bar is nowhere to be found unless I set it to UINavigationItemSearchBarPlacementStacked.
So is UINavigationItemSearchBarPlacementInline not supported for the supplementary column of a UISplitViewController? If that's the case I'm fine with that actually but there's got to be a way to make UINavigationItemSearchBarPlacementStacked look a little better on Mac? The search bar border is barely visible on a white background.
I'm on Mac Catalyst.
I have a UISearchController and I keep getting this crash after I clear the search bar, adjust the search scope segmented control if one of the UITableViewCells is focused (via arrow key press) before
Focus item does not provide a parentFocusEnvironment.
I can workaround the problem by overriding -parentFocusEnvironment, holding the parent UITableView in a property and returning it:
-(id<UIFocusEnvironment>)parentFocusEnvironment
{
id<UIFocusEnvironment>theFocus = [super parentFocusEnvironment];
if (theFocus == nil)
{
return self.cachedParentFocus;
}
else
{
self.cachedParentFocus = theFocus
}
return theFocus;
}
The problem with this is it is likely to create a retain cycle (I did try a weak reference but that can cause the following crasher on deallocation (the focus environment continues to call this method on the table view cell even when its outside of a UIWindow):
“Cannot form weak reference to instance (0x13799a000) of class UITableView. It is possible that this object was over-released, or is in the process of deallocation.”
Anyone run into this and know of a potential workaround?
So when a row is selected in UITableView and the table view / cells within it have focus, and the window is active.... the rows are selected with the system Accent color (in my case blue).
I have a view inside the table view cell that does custom drawing. When the cell is selected I draw text white (when unselected I draw the text using UIColor.labelColor).
So when the window is not active but the table view row is selected, the selected background color changes to light gray. In this case I draw the text black (because it looks better against the light gray selection color on an inactive window).
However when the row is selected but another view in the window has focus (say the sidebar) the selected row turns back to the light gray color. In this case my text is incorrectly drawing white instead of black on the light gray background. How do I check for this state from UIKit? In AppKit I think I'd be using:
NSColor.unemphasizedSelectedTextColor
https://developer.apple.com/documentation/appkit/nscolor/2998834-unemphasizedselectedtextcolor?language=objc
I have to update text color manually because I'm doing custom drawing in these table view cells (I have a view that overrides drawRect:) I can't just use the dynamic colors like UIColor.labelColor. I have to set the colors on state change manually and call setNeedsDisplay on my view.
How do I check for the unemphasized state? I did inspect whether or not my table view cell is in the active focusItem's environment, and if it is not I assume the light gray selected color is being used. This worked most of the time but there still seems to be some states where the unemphasized selection color (light gray)is being used on selected cells when the the table view cell is in the active focus environment and my text incorrectly draws white.
My table view supports multiple selection. When holding down the shift key and clicking to extend the selection on Mac focus doesn't move to the clicked row. This isn't how macOS apps normally behave.
I tried working around the problem by catching the last selected index path and forcing a focus update:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.lastSelectedIndexPath = indexPath;
}
-(void)tableView:(UITableView*)tableView didDeselectRowAtIndexPath:(NSIndexPath*)indexPath
{
if ([indexPath isEqual:self.lastSelectedIndexPath])
{
self.lastSelectedIndexPath = nil;
}
}
-(void)tableViewDidEndMultipleSelectionInteraction:(UITableView *)tableView
{
[tableView setNeedsFocusUpdate];
[tableView updateFocusIfNeeded];
}
-(NSIndexPath*)indexPathForPreferredFocusedViewInTableView:(UITableView *)tableView
{
return self.lastSelectedIndexPath;
}
But that didn't work. UITableview never calls -indexPathForPreferredFocusedViewInTableView: after my -setNeedsFocusUpdate / -updateFocusIfNeeded calls.
I tried subclassing UITableView and overriding -preferredFocusEnvironments but that isn't called.
Focus system just ignores updating for shift click. Anyone know of a workaround?
I'm using UIMenuBuilder API to add a menu item to the menu bar on Mac Catalyst (adding a UIKeyCommand object).
So depending on the current selection the title of the menu item should change. As an example in Finder if a single file is selected and you go to the "Edit" menu in the menu bar there is an item that says "Copy Filename"
Now select two files in Finder and go to Edit menu in the menu bar and now it says "Copy 2 Items"
Updating a NSMenuItem in Appkit is pretty easy. I figured I'd be able to do this in -canPerformAction:withSender: but the system doesn't pass my UIKeyCommand as the sender but instead an instance of a private class _UIMenuBarItem. I assume there must be a way to dynamically update the title of a menu bar item in a Catalyst app?
I'm looking to achieve the AppKit equivalent of -acceptsFirstMouse: from the Mac Catalyst environment:
https://developer.apple.com/documentation/appkit/nsview/1483410-acceptsfirstmouse?language=objc
"Overridden by subclasses to return YES if the view should be sent a mouseDown: message for an initial mouse-down event, NO if not."
Is this possible?
I have a triple UISplitViewController. A UINavigationController is in the secondary column.
When the selection changes in the supplementary column I call -setViewControllers:animated: and pass the navigation controller the new vc.
I noticed sometimes the navigation view controller isn't updating and this logs out:
setViewControllers:animated: called on while an existing transition or presentation is occurring; the navigation stack will not be updated.
So this happens when the Split View controller itself is presenting another view controller modally (say a view controller with a UIActivityIndicatorView in it to show loading progress). But there is no transition/presentation occurring on the UINavigationController contained in the secondary view controller column itself. The presentation occurring on the UISplitViewController is completely separate and unrelated to the UINavigationController's navigation stack that's in the secondary column and therefore I should not be prevented from modifying the navigation stack.
I use UNUserNotificationCenterDelegate. I'm in the process of adding new scene configurations for windows for the Mac environment. Some of these windows are auxiliary windows.
So I was just wondering what happens with UNNotificationResponse targetScene property.
In -userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler: is it possible for one of the auxiliary window scenes to be the targetScene or does UNNotificationResponse always choose the configuration at index 0 in the info.plist?
Is there a way to play NSBeep() from the Mac Catalyst environment? Thanks in advance to anyone who answers.
After programmatically changing the selection of a UITableview, focus gets separated from the selection if I programmatically select a cell beyond the visible region of the table view. That is to say the focused cell is not the selected cell which any user would consider wrong.
To reproduce
Add a button to select the "Next" row in a table (deselect the previous selected row, then select the next row just below it)
Click the button.
Keep clicking the button to move the table view selection down. Once you select the row outside the visible region of the table view focus cell gets separated from the selection.
I created a bug report on this with a sample project: FB11803433
Trying to scroll the row visible before programmatically changing the selection doesn't always work around the issue. I experimented with -performSelector:withObject:afterDelay: calls and -setNeedsFocusUpdate and -updateFocusIfNeeded calls but it doesn't always seem to work.
When I set breakpoints on os_log statements like below:
os_log_debug(OS_LOG_DEFAULT, "hi"); //<--break point RIGHT on this line….
I have to click the "Continue Program Execution" button three times to actually continue program execution. At first I thought my method was being called multiple times unexpectedly but it’s not. I just have to keep hitting the continue program execution button. I’m not hitting “Step over” or “step into”. I’m hitting the “Continue Program Execution” button.
FB9792745
Creating a context menu via UIContextMenuConfiguration creates the NSMenu as expected on Mac Catalyst but how do I add separator menu items? https://developer.apple.com/documentation/appkit/nsmenuitem/1514838-separatoritem?language=objc
I'm talking about context menus that are shown via right-click, not the menu bar.
Is it possible to share multiple links at once on Mac Catalyst to Messages? When I provide multiple urls via the UIActivityItemSource API Messages just picks 1 of the links.
The Mail activity handles multiple links without a problem but I'd like this to work with Messages too. I know for sure this is possible in native AppKit but can't seem to figure out how to get this to work on Catalyst.
I tried providing the links to UIActivityViewController with a UIActivityItemsConfiguration object instead of using the UIActivityItemSource API but that didn't work either.
Thanks in advance
According to the UIActivityViewController documentation for UIActivityViewController's completionWithItemsHandler:
Upon the completion of an activity, or the dismissal of the activity view controller, the view controller’s completion block is executed. You can use this block to execute any final code related to the service.
However when invoking the "Messages" or "Mail" actions in the UIActivityViewController this block is never called. I'm presenting the UIActivityViewController in a popover. Simple to reproduce. Just do this on Mac Catalyst in a table view delegate (sorry for the poor code formatting but it is hard to format code well on these forums).
-(UISwipeActionsConfiguration*)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
UIContextualAction *shareAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal
title:@"Share"
handler:^(UIContextualAction *action,
UIView * _Nonnull sourceView,
void (^_Nonnull completionHandler)(BOOL))
{
[self showPopoverWithSourceItem:sourceView completionWithItemsHandler:^(UIActivityType _Nullable activityType,
BOOL completed,
NSArray * _Nullable returnedItems,
NSError * _Nullable activityError) {
//This block isn't called when Messages/Mail activities are selected. Probably other too but that's all I tested.
completionHandler(completed); //Need to call the UIContextualAction's completionHandler here to close up the swipe actions.
}];
}];
shareAction.image = [UIImage systemImageNamed:@"square.and.arrow.up.fill"];
UISwipeActionsConfiguration *config = [UISwipeActionsConfiguration configurationWithActions:@[shareAction]];
return config;
}
-(void)showPopoverWithSourceItem:(id<UIPopoverPresentationControllerSourceItem>)sourceItem
completionWithItemsHandler:(UIActivityViewControllerCompletionWithItemsHandler)handler
{
NSURL *shareLink = [NSURL URLWithString:@"https://www.apple.com"];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc]initWithActivityItems:@[shareLink]
applicationActivities:nil];
activityViewController.completionWithItemsHandler = handler;
activityViewController.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *presentationController;
presentationController = (UIPopoverPresentationController*)activityViewController.presentationController;
presentationController.sourceItem = sourceItem;
presentationController.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:activityViewController animated:YES completion:nil];
}
Run that and choose "Mail" or "Messages" in the activity view controller. The table view remains swiped after the activity is invoked and the popover is dismissed. Now if you click outside the popover without invoking an activity the popover dismisses and the completionWithItemsHandler is called.
Related but different UIActivityViewController/UIActivity bug I reported here yesterday: https://developer.apple.com/forums/thread/722003
I will file a bug on this and post the number here soon.
Can I please work a full day without running into a system bug in this framework....just one day..please.
I wouldn't be so disgruntled about all this if my obvious bug reports actually got fixed in a reasonable amount of time but I've been a developer long enough to know that I'm lucky if they get fixed for macOS 14, if ever.