Testing my app, I noticed a button in my UI which presents a UIAlertController appeared to do nothing all of a sudden, after a few days.
So hooking up the console app I see UIKit spit out the following log when I press the button:
"Warning: Attempt to present UIAlertController on MyViewController which is already presenting SomeOtherViewController.
No view controller appears to be presented. SomeOtherViewController is not currently in the UI but for some reason after it was dismissed the presentedViewController property wasn't set to nil (haven't been able to reproduce the issue yet).
So SomeOtherViewController I know is a "Detail View Controller" which only get pushed on the UINavigationController stack (I never present it modally). The only time it gets presented modally is when it is a "preview view controller" used in UIContextMenuConfiguration, but otherwise it doesn't get presented. Has anyone run into this sort of situation before and know of a potential cause/solution?
The presentedViewController does not appear on screen but for some reason UIKit is holding a strong reference to it in the presentedViewController property which prevents subsequent calls to -presentViewController:animated:completion:
As a workaround I could try using the code below but I'd really like to find the root cause of the issue:
-(void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
{
UIViewController *currentPresentedVC = self.presentedViewController;
if ([currentPresentedVC isKindOfClass:[SomeOtherViewController class]])
{
//this is unexpected.
[currentPresentedVC dismissViewControllerAnimated:NO completion:^{
[super presentViewController:viewControllerToPresent animated:flag completion:completion];
}];
}
else
{
[super presentViewController:viewControllerToPresent animated:flag completion:completion];
}
}
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I noticed a bug on rotation change in my app on iPhone 14 Pro Max simulator. Basically a view in my view hierarchy is hidden when it shouldn't be. In landscape mode there isn't enough room for this view so I hide it on the iPhone (not essential). But when tilting back to portrait mode I unhide it.
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
BOOL isIPhone = UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPhone;
BOOL isIPhoneAndGoingLandscapeMode = (isIPhone
&& size.width > size.height);
if (isIPhoneAndGoingLandscapeMode)
{
self.someView.hidden = YES;
}
else
{
self.someView.hidden = NO;
}
}
So this view controller is presented modally (form sheet style).
On iPhone 14 Pro Max on orientation -viewWillTransitionToSize:withTransitionCoordinator: is called twice and the size parameter is always:
(CGSize) size = (width = 414, height = 394)
This is the sized passed to my app when rotating to portrait and landscape so my isIPhoneAndGoingLandscapeMode flag always is YES because 414 > 394. The 414 x 394 size appears to be false.
My view controller's view in landscape on iPhone 14 pro max logs out to:
(origin = (x = 0, y = 0), size = (width = 932, height = 430))
And 932 x 430 is the size I expected to be passed to me in -viewWillTransitionToSize:withTransitionCoordinator:
Unless I'm missing something can this behavior be explained?
When I open a new window via UIWindowSceneActivationAction, the window is shown like a modally presented view controller. I noticed a little layout hiccup when the window is in this state, because the window is reporting a safeAreaInset.bottom value of 20.0 even though the window is nowhere near the Home Indicator.
Is there a good way to detect when a window is in this "modal like presentation" state on iPad? Size classes don't provide. I'd hate to have to sniff the frame of the window and compare it to the mainScreen frame (I know UIScreen.mainScreen is deprecated)?
So experimenting with UISplitViewController on Mac Catalyst. I have a triple split. The primary view controller is a sidebar. I have the default sidebar button showing in the toolbar and that collapsed/expands the sidebar fine. But when I drag to try to collapse the split (as is typical on macOS) the sidebar doesn't collapse. It clamps to the min. size. Is there anyway to enable this? I tried passing 0 to -setMinimumPrimaryColumnWidth: but that didn't work.
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?
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 can't seem to get rid of the "vibrancy" effect on the titlebar/toolbar area of the window on Mac Catalyst. I have a triple Split View controller.
The primary vc style is sidebar in the split vc.. And that has the blur/visual effect and that's all well and good.
But the title bar area on the supplementary column has the blur effect too and it looks kind of terrible (the navigation bar in the supplementary view controller has all of its navigationBar appearances configured with opaque content:
UINavigationBarAppearance *opaqueAppearance = [[UINavigationBarAppearance alloc]init];
[opaqueAppearance configureWithOpaqueBackground];
opaqueAppearance.backgroundEffect = nil;
opaqueAppearance.backgroundColor = [UIColor myColor];
//set to all appearances
But I still get the blur effect on the navigation bar, which presumably is being mapped to NSToolbar. Is it possible to disable this blur effect for the column? It really doesn't look good in my app.
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?
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?
My UISplitViewController is configured like this:
A list (collection view) is used in the primary view controller (sidebar style).
When a selection is made in the primary view controller a table view displays data in the supplementary column.
When a selection is made in the supplementary view controller, a view controller with scrollable content is shown in the secondary view controller.
This is like the Mail app on Mac. So when I run the app I hit the tab key once and the list (collection view) in the primary column gets focus. I can navigate the list with the keyboard. This works as expected.
So now with a selection in the list, a table view is showing in the supplementary column. I hit the tab key again and the table view gets focus. This works as expected as I can navigate the table view from the keyboard with the arrow keys.
Now with a selection made in the table view, the scrollable view controller is showing in the secondary view controller column. I hit the tab key again and focus goes back to the list in the primary column. This is not the expected behavior. I'd expect hitting tab would move focus to the scroll view in the secondary column instead of jumping back to the primary column (as I should be able to scroll the scroll view in the secondary column with the up and down arrow keys). The user is then required to click on the secondary view controller in order to scroll it with the arrow keys. This breaks full keyboard navigation.
The behavior I'm after is actually the default behavior in the Mail app but I can't figure out how to get it to work in Mac Catalyst?
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.
On macOS it is typical for apps to have a "Done" button showing at the bottom of a window sheet. Usually the button is blue (or whatever your system accent color is set to) and this button can be invoked by pressing the return key.
On NSButton all you do is assign the return key as the key equivalent. So in the Mac Catalyst environment how do I achieve this behavior? I'm able to get the button to look exactly how I want configuring UIButton like this:
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeSystem];
[doneButton setTitle:@"Done" forState:UIControlStateNormal];
doneButton.role = UIButtonRolePrimary;
Is there a quick way to get its action to be invoked when the return key is pressed or do I have to manually implement UIKeyCommand?
Thanks in advance to anyone who answers.
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.