Construct and manage graphical, event-driven user interfaces for iOS or tvOS apps using UIKit.

UIKit Documentation

Post

Replies

Boosts

Views

Activity

shouldAutomaticallyForwardAppearanceMethods returns NO by default in UITabBarController, but documentation states YES
Hi all, I’ve been facing a behavior issue with shouldAutomaticallyForwardAppearanceMethods in UITabBarController. According to Apple’s documentation, this property should default to YES, which means that the appearance lifecycle methods (like viewWillAppear and viewDidAppear) should be automatically forwarded to child view controllers. However, in my current development environment, I’ve noticed that shouldAutomaticallyForwardAppearanceMethods returns NO by default in UITabBarController, and this is causing some issues with lifecycle management in my app. I even tested this behavior in several projects, both in Swift and Objective-C, and the result is consistent. Here are some details about my setup: I’m using Xcode 16.0 with iOS 16.4 Simulator. I’ve tested the behavior in both a new UIKit project and a simple SwiftUI project that uses a UITabBarController. Even with a clean new project, the value of shouldAutomaticallyForwardAppearanceMethods is NO by default. This behavior contradicts the official documentation, which states that it should be YES by default. Could someone clarify if this is expected behavior in newer versions of iOS or if there is a known issue regarding this? Any help or clarification would be greatly appreciated! Thanks in advance!
1
0
107
2d
Live Acitivities - ProgressView problem
Hello i ve implemented progressview and updating the state via push notification. the progress view wants closedrange which i followed but whenever i get update, the progress value resets to beginning my range is like : Date.now..endDate but i dont get it, lets assume that i get the date from database and initialized already then how the code will understand that what progress value will be as current ? it has to be something like i suppose : startDate..Date.now..endDate thanks
0
0
90
3d
Fatal Exception: NSInternalInconsistencyException Attempting to select a view controller that isn't a child! (null)
When call: [UITabBarController setViewControllers:animated:] It crashed and raise an Fatal Exception: Fatal Exception: NSInternalInconsistencyException Attempting to select a view controller that isn't a child! (null) the crash stack is: Fatal Exception: NSInternalInconsistencyException 0 CoreFoundation 0x8408c __exceptionPreprocess 1 libobjc.A.dylib 0x172e4 objc_exception_throw 2 Foundation 0x82215c _userInfoForFileAndLine 3 UIKitCore 0x38a468 -[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:] 4 UIKitCore 0x3fa8a4 -[UITabBarController _setSelectedViewController:performUpdates:] 5 UIKitCore 0x3fa710 -[UITabBarController setSelectedIndex:] 6 UIKitCore 0x8a5fc +[UIView(Animation) performWithoutAnimation:] 7 UIKitCore 0x3e54e0 -[UITabBarController _setViewControllers:animated:] 8 UIKitCore 0x45d7a0 -[UITabBarController setViewControllers:animated:] And it appear sometimes, what's the root cause?
1
0
137
3d
How the input of UITextField is stored ?
When user enters in a textfield, is the input of textfield gets stored in a String ? If yes, then String in swift being immutable, as user keeps on typing does new memory for storing that text gets allocated with each key stroke ? And when we read users input by using delegate method textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) from textfield.text, we get users input in a String. Is it same storage as used by textfield for storing the user input on key stroke or is it some other storage with copy of the user's input in it? Or is UItextfield using a diffrent data structure (buffer) for storing the user input and when we do textfield.text, it gives a copy of data stored in original buffer?
1
0
131
3d
NSInternalInconsistencyException Failed to create remote render context
Some crashes were found, not many, but we could not locate the specific code because the error stack is a systematic method. Error: NSInternalInconsistencyException Failed to create remote render context Stack: 0 CoreFoundation 0x000000018a879d78 ___exceptionPreprocess + 220 1 libobjc.A.dylib 0x00000001a34de734 _objc_exception_throw + 60 2 Foundation 0x000000018c0ff358 -[NSMutableDictionary(NSMutableDictionary) initWithContentsOfFile:] + 0 3 UIKitCore 0x000000018d475f8c ___UIKIT_DID_NOT_RECEIVE_A_REMOTE_CACONTEXT_FROM_COREANIMATION_INDICATING_A_POSSIBLE_BACKBOARDD_CRASH + 572 4 UIKitCore 0x000000018d232484 ___UIKIT_IS_REQUESTING_A_CACONTEXT_FROM_COREANIMATION + 80 5 UIKitCore 0x000000018d1fc32c +[_UIContextBinder createContextForBindable:withSubstrate:] + 708 6 UIKitCore 0x000000018d13bdec -[_UIContextBinder _contextForBindable:] + 148 7 UIKitCore 0x000000018cf5bd20 -[_UIContextBinder updateBindableOrderWithTest:force:] + 480 8 UIKitCore 0x000000018d2e1200 -[_UIContextBinder createContextsWithTest:creationAction:] + 92 9 UIKitCore 0x000000018ccd64c0 -[UIWindowScene _prepareForResume] + 156 10 UIKitCore 0x000000018ce2ef80 -[UIScene _emitSceneSettingsUpdateResponseForCompletion:afterSceneUpdateWork:] + 876 11 UIKitCore 0x000000018ce72528 -[UIScene scene:didUpdateWithDiff:transitionContext:completion:] + 288 12 UIKitCore 0x000000018cdfc8c8 -[UIApplicationSceneClientAgent scene:handleEvent:withCompletion:] + 476 13 FrontBoardServices 0x000000019c9dbe18 -[FBSScene updater:didUpdateSettings:withDiff:transitionContext:completion:] + 528 14 FrontBoardServices 0x000000019c9f413c ___94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke_2 + 152 15 FrontBoardServices 0x000000019c9d9308 -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 240 16 FrontBoardServices 0x000000019c9df824 ___94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke + 396 17 libdispatch.dylib 0x000000018a4e0a2c __dispatch_client_callout + 20 18 libdispatch.dylib 0x000000018a4e44e0 __dispatch_block_invoke_direct + 264 19 FrontBoardServices 0x000000019c9dac70 ___FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 48 20 FrontBoardServices 0x000000019c9da040 -[FBSSerialQueue _targetQueue_performNextIfPossible] + 220 21 FrontBoardServices 0x000000019c9de700 -[FBSSerialQueue _performNextFromRunLoopSource] + 28 22 CoreFoundation 0x000000018a89bf04 ___CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28 23 CoreFoundation 0x000000018a8acc90 ___CFRunLoopDoSource0 + 208 24 CoreFoundation 0x000000018a7e6184 ___CFRunLoopDoSources0 + 268 25 CoreFoundation 0x000000018a7ebb4c ___CFRunLoopRun + 828 26 CoreFoundation 0x000000018a7ff6b8 _CFRunLoopRunSpecific + 600 27 GraphicsServices 0x00000001a6899374 _GSEventRunModal + 164 28 UIKitCore 0x000000018d164e88 -[UIApplication _run] + 1100 29 UIKitCore 0x000000018cee65ec _UIApplicationMain + 364 30 ??? 0x00000001059b9ce4 0x00000001059b9ce4 + 0 These crashes occurred when the App was about to enter the foreground. (UIApplicationWillEnterForegroundNotification) These crashes occurred on systems from 15 to 18. crash.log
1
0
65
4d
侧划返回卡死
xcode16,iphone16,iOS 自定义navigationItemLeftBar,设置 navigationController?.interactivePopGestureRecognizer?.delegate = self,侧划返回一半,点击屏幕,界面卡死。 18系统之前的手机,或者非iphone16的手机没有问题。
0
0
123
1w
UIPasteControl sometimes disappear
Problem Our app use UIPasteControl for people taps to place pasteboard contents in UITextView. It worked fine at first, but recently received a lot of user feedback and the button suddenly disappeared This problem usually occurs when an App switches between the front and back More Information When the button disappears, we find that the child view of the UIPasteControl control which name _UISlotView has a size of zero. we use UIKit and AutoLayout,limit button size (100, 36) let config = UIPasteControl.Configuration() config.displayMode = .labelOnly config.cornerStyle = .fixed config.baseForegroundColor = .white config.baseBackgroundColor = .black config.cornerRadius = 18 let btn = UIPasteControl(configuration: config) pasteBtn = btn addSubview(pasteBtn) pasteBtn.snp.makeConstraints { make in make.trailing.equalTo(-20) make.bottom.equalTo(-10) make.size.equalTo(CGSize(width: 100, height: 36)) } UI view information <UIPasteControl: 0x107dda810; frame = (0 0; 100 36); layer = <CALayer: 0x3010ff000>> (lldb) po [0x107dda810 subviews] <__NSSingleObjectArrayI 0x30152ff00>( <_UISlotView: 0x107dea630; frame = (0 0; 100 36); userInteractionEnabled = NO; layer = <CALayer: 0x3010eb460>> ) anyone meet before? is there a workaround?
5
0
451
Jun ’24
MTKView delegate ownership during view controller transitions
The Problem When transitioning between view controllers that each have their own MTKView but share a Metal renderer backend, we run into delegate ownership conflicts. Only one MTKView can successfully render at a time, since setting the delegate on one view requires removing it from the other, leading to paused views during transitions. For my app, I need to display the same visuals across multiple views and have them all render correctly. Current Implementation Approach I've created a container object that manages the MTKView and its relationship with the shared renderer: class RenderContainer { let metalView: MTKView private let renderer: MetalRenderer func startRendering() { metalView.delegate = renderer metalView.isPaused = false } func stopRendering() { metalView.isPaused = true metalView.delegate = nil } } View controllers manage the rendering lifecycle in their view appearance methods: override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) renderContainer.startRendering() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) renderContainer.stopRendering() } Observations & Issues During view controller transitions, one MTKView must stop rendering before the other can start. Also there is no guarantee that the old view will stop rendering before the new one starts, with the current API design. This creates a visual "pop" during animated transitions Setting isPaused = true helps prevent unnecessary render calls but doesn't solve the core delegate ownership problem The shared renderer maintains its state but can only output to one view at a time Questions What's the recommended approach for handling MTKView delegate ownership during animated transitions? Are there ways to maintain visual continuity without complex view hierarchies? Should I consider alternative architectures for sharing the Metal content between views? Any insights for this scenario would be appreciated.
0
0
82
5d
UITableViewDropItem missing in Xcode 16?
Following instructions from ChatGPT, I'm trying to rearrange the order of rows in a UITableView. - (void)tableView:(UITableView *)tableView performDropWithCoordinator:(id<UITableViewDropCoordinator>)coordinator { NSIndexPath *destinationIndexPath = coordinator.destinationIndexPath ?: [NSIndexPath indexPathForRow:self.items.count inSection:0]; [tableView performBatchUpdates:^{ for (UITableViewDropItem *dropItem in coordinator.items) { NSString *movedItem = dropItem.dragItem.localObject; if (movedItem) { NSIndexPath *sourceIndexPath = dropItem.sourceIndexPath; if (sourceIndexPath) { [self.items removeObjectAtIndex:sourceIndexPath.row]; [self.items insertObject:movedItem atIndex:destinationIndexPath.row]; [tableView moveRowAtIndexPath:sourceIndexPath toIndexPath:destinationIndexPath]; } } } } completion:nil]; } Xcode is complaining that UITableViewDropItem does not exist. The class is in all the documentation, it is just not showing up when needed! Suggestions?
1
0
131
1w
allowedWritingToolsResultOptions has no effect in iOS 18.1 Writing Tools
The UITextView.allowedWritingToolsResultOptions has no effect to how "Writing Tools" feature works. When it is set to empty, it still offer all options in the Writing Tools popup dialog. The result is that it is not possible to limit output results to eg. only plain text, or disable tables in output. let textView = UITextView() textView.isEditable = true textView.writingToolsBehavior = .complete textView.allowedWritingToolsResultOptions = [] resulting Writing Tools has all options available. I Tested with TextKit1 and TextKit 2 setup. tested on iPadOS 18.1 beta (22B5069a) Report: FB15429824
2
0
422
Oct ’24
Limiting UITableView Width Across Different Table View Configurations
I have an iOS App which looks great on iPhone, portrait only, which makes a lot of use of UITableViews. On iPad those tables look stretched out in Landscape. On MacOS with Apple Silicon the app can be resized to any size and the table views look very stretched. There are views in the App which users want to resize so limiting app size not an option. I've been modifying the app's table views to limit their width and centre them using constraints. This isn't easy, it's a lot of work as UITableViewController doesn't allow for constraining the table width. Or does it? So I've changed them to UIViewControllers with UITableView imbedded in the root UIView with constraints. Looks really nice. Now I've just run into the limitation that static tables, which I have a number of, aren't allowed to be embedded. So how can I limit the width of them? I really don't want to add a lot of dynamic code. Please tell me there's an simpler, more elegant method to what really makes a much more aesthetically pleasing UI on iOS App running on iPad and MacOS? TIA!
2
0
103
6d
How to fix MainActor warning for QLPreviewControllerDelegate
I'm currently migrating a midsize (20k LOC) project to Swift structured concurrency. With complete checking turned on, it currently builds with only two warnings, both of which are related to the QLPreviewControllerDelegate protocol: "Main actor-isolated instance method 'previewControllerDidDismiss' cannot be used to satisfy nonisolated protocol requirement; this is an error in the Swift 6 language mode" as well as the same warning but substituting 'previewController(_:transitionViewFor:)' for the method name. I'm confused as to how to make these nonisolated, as they use UIKit classes/subclasses as arguments and/or return types.
2
0
177
2w
Calendar integers in english and alphabets in arabic
we are migrating our app to support Arabic language support but the requirement is we want the calendar/date object to display as missed. That is all the numbers in english digits and rest all the words like days, months should be in Arabic. I tried few options but at the end its resulting everything is in Arabic or in English but not the mixed as expected. Attaching the expected behavior.
2
0
211
2w
UICollectionView Auto cell height problem
Hi, I'm trying to create a UICollectionView where the cell high is automatic. Cells contains a UILabel with all anchors to the contentView of the cell. It seems to work but I have a strange behavior with longer text, on reload data and on device rotation: Cells do not display the whole text or they change row, both randomly. To create my collection view I first create the collection view with a custom flow layout setting the automatic size on viewWillAppear: let collectionViewFlowLayout = CustomFlowLayout() collectionViewFlowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize collectionView = UICollectionView(frame: .zero, collectionViewLayout: collectionViewFlowLayout) and I have also overridden: override func willAnimateRotation(to toInterfaceOrientation: UIInterfaceOrientation, duration: TimeInterval) { collectionView.setNeedsLayout() self.collectionView.layoutIfNeeded() self.collectionView.collectionViewLayout.invalidateLayout() //self.collectionView.reloadData() } Then, I created the custom layout as follow: import UIKit final class CustomFlowLayout: UICollectionViewFlowLayout { override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { let layoutAttributesObjects = super.layoutAttributesForElements(in: rect)?.map{ $0.copy() } as? [UICollectionViewLayoutAttributes] layoutAttributesObjects?.forEach({ layoutAttributes in if layoutAttributes.representedElementCategory == .cell { if let newFrame = layoutAttributesForItem(at: layoutAttributes.indexPath)?.frame { layoutAttributes.frame = newFrame } } }) return layoutAttributesObjects } override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { guard let collectionView = collectionView else { fatalError() } guard let layoutAttributes = super.layoutAttributesForItem(at: indexPath)?.copy() as? UICollectionViewLayoutAttributes else { return nil } layoutAttributes.frame.origin.x = sectionInset.left if(indexPath.section == 0){ layoutAttributes.frame.size.width = collectionView.safeAreaLayoutGuide.layoutFrame.width - sectionInset.left - sectionInset.right } else if (indexPath.section == collectionView.numberOfSections - 1){ let width = ScreenUtility.getCollectionCellWidthForElement(in: collectionView, sectionLeft: sectionInset.left, sectionRight: sectionInset.right, minimumInteritemSpacing: minimumInteritemSpacing, multiplier: 3) layoutAttributes.frame.origin.x = ScreenUtility.getCollectionCellOriginForElement(in: collectionView, at: indexPath, forElementHavingWidth: width, sectionLeft: sectionInset.left, sectionRight: sectionInset.right, minimumInteritemSpacing: minimumInteritemSpacing, multiplier: 3) layoutAttributes.frame.size.width = width } else if (indexPath.section == collectionView.numberOfSections - 3) || (indexPath.section == collectionView.numberOfSections - 4){ let width = ScreenUtility.getCollectionCellWidthForElement(in: collectionView, sectionLeft: sectionInset.left, sectionRight: sectionInset.right, minimumInteritemSpacing: minimumInteritemSpacing) layoutAttributes.frame.origin.x = ScreenUtility.getCollectionCellOriginForElement(in: collectionView, at: indexPath, forElementHavingWidth: width, sectionLeft: sectionInset.left, sectionRight: sectionInset.right, minimumInteritemSpacing: minimumInteritemSpacing) layoutAttributes.frame.size.width = width } else { let width = ScreenUtility.getCollectionCellSizeForElementFullRow(in: collectionView, sectionLeft: sectionInset.left, sectionRight: sectionInset.right) layoutAttributes.frame.origin.x = ScreenUtility.getCollectionCellOriginForElementFullRow(in: collectionView, sectionLeft: sectionInset.left, sectionRight: sectionInset.right) layoutAttributes.frame.size.width = width } return layoutAttributes } } And finally on collection view cells: override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { setNeedsLayout() layoutIfNeeded() let targetSize = CGSize(width: layoutAttributes.frame.width, height: 0) layoutAttributes.frame.size = contentView.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel) return layoutAttributes } override func prepareForReuse() { self.nameLabel.text = "" self.idLabel.text = "" self.contentView.setNeedsLayout() self.contentView.layoutIfNeeded() } Let me show you an example on the iPad that is the worst. First Time I open the collection view I have cells on wrong rows and not sized properly Then I rotate the device portrait and the cells are fine On landscape again it changes behavior: This is just an example, things happens apparently randomly, and also sometimes cells disappear (I think the height is set to 0). I really do not understand why, cells width seems to be computed correctly, and cell label is set via setter: open var step: String = "" { didSet { nameLabel.text = step nameLabel.sizeToFit() self.contentView.setNeedsLayout() self.contentView.layoutIfNeeded() } }
2
0
144
1w
iPad OS 18 Tab Bar Controller is ignoring isEnabled property on tar bar items
Running an existing Xcode project in an iPad OS 18 simulator is automatically using the newly introduced tab bar view, moved from the bottom to the top. Unfortunately, the isEnabled property on a tar bar item is no longer honored. In Xcode's Storyboard builder, some tab bar items are initially disabled. (can't add a screenshot here, I will try to do that after posting) The iPad OS 17 simulator shows them correctly as disabled and any user interaction is suppressed as expected. The iPad OS 18 simulator shows them as active and they can be selected. Also setting them to disabled inside of the UITabBarViewController doesn't work: for item in self.tabBar.items! { if item.tag != 99 { item.isEnabled = false } } They stay enabled and selectable. As a workaround, I implemented the UITabBarViewControllerDelegate and overrode this method: func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool { if Global.shared.accessToken == nil { if viewController is LoginViewController || viewController is SettingsViewController { return true } else { return false } } return true } The user can no longer select the tabs, however, there is no visual indicator that they are not selectable. I cannot find any indication in the release notes or documentation, that this behavior is intentional. So I assume this is a bug.
4
0
301
Oct ’24
Show new Format Panel on button press
I'm working on integrating the new format panel shown in the WWDC24 session "What's New in UIKit" under the Text Improvements section. So far, I've implemented long-press functionality on a text passage, allowing the editing options to appear. From there, you can go to Format > More..., which successfully opens the new format panel. However, I would also like to add a button to programmatically display this format panel—similar to how the Apple Notes app has a button in the keyboard toolbar to open it. Does anyone know how to achieve this? Here's my current code for the text editor (I've enabled text formatting by setting allowsEditingTextAttributes to true): struct TextEditorView: UIViewRepresentable { @Binding var text: String func makeCoordinator() -> Coordinator { Coordinator(self) } func makeUIView(context: Context) -> UITextView { let textEditorView = UITextView() textEditorView.delegate = context.coordinator textEditorView.allowsEditingTextAttributes = true return textEditorView } func updateUIView(_ uiView: UITextView, context: Context) { uiView.text = text } class Coordinator: NSObject, UITextViewDelegate { var parent: TextEditorView init(_ uiTextView: TextEditorView) { self.parent = uiTextView } func textViewDidChange(_ textView: UITextView) { self.parent.text = textView.text } } } Thanks in advance for any guidance!
0
0
123
1w
iOS18: UITabBarController.selectedViewController with UINavigationController
In a UITabBarController, its controllers are set to be UINavigationControllers. When programmatically setting the selectedViewController to a desired controller which is not currently displayed, the selected icon is correct however the actual view controller is still the previously selected. Pseudo code: tabController.controllers = [viewcontroller1, viewcontroller2, viewcontroller3].map{ UINavigationController(rootViewController: $0) } .... // let's say at some point tab bar is set to e.g. showing index 1 tabController.selectedController = tabController.controllers[0] // after this the icon of the 1st tab is correctly displayed, but the controller is still the one at index 1 I have noticed that if the controllers are simple UIViewController (not UINavigationController) upon setting the selectedViewController the TabController sets both icon and content correctly. But this is not the wanted setup and different UINavigationControllers are needed. Is this a new bug in iOS18? Any idea how to fix this (mis)behaviour?
1
0
226
2w