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

UIKit Documentation

Posts under UIKit subtopic

Post

Replies

Boosts

Views

Activity

This is an internal UIKit bug. Ignoring unexpected nonmatching counterpart: (null)
FB14569448 Since iOS 18 beta came out, our app has been failing at some point when a view controller is dismissed and it appears the main thread ends up looping in layout logic and logs the following to the console. The app hangs until it's terminated due to a memory overallocation issue. Anyone else seen this? <_UINavigationBarItemStackEntry: 0x302ac73f0> normalLayout[active]=0x1391ad880 searchLayout=0x0 item=<UINavigationItem: 0x13913a080> style=navigator: Ignoring unexpected nonmatching counterpart: (null) This is an internal UIKit bug. Snapshotting a view (0x1391e7c00, _UIButtonBarStackView) that has not been rendered at least once requires afterScreenUpdates:YES. frame #0: 0x000000019bb07000 libobjc.A.dylibobjc_msgSend frame #1: 0x00000001a0fb4224 UIKitCore-[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededCollectingViews:forSecondPass:] + 144 frame #2: 0x00000001c270a030 CoreAutoLayout-[NSISEngine withBehaviors:performModifications:] + 84 frame #3: 0x00000001a0fe5424 UIKitCore__100-[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededWithViewForVariableChangeNotifications:]_block_invoke + 120 frame #4: 0x00000001a0fe3ae0 UIKitCore-[UIView(AdditionalLayoutSupport) _withUnsatisfiableConstraintsLoggingSuspendedIfEngineDelegateExists:] + 112 frame #5: 0x00000001a0fe2b4c UIKitCore-[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededWithViewForVariableChangeNotifications:] + 172 frame #6: 0x00000001a0fa9e90 UIKitCore-[UIView _updateConstraintsAtEngineLevelIfNeededWithViewForVariableChangeNotifications:] + 400 frame #7: 0x00000001a0fa9a18 UIKitCore-[UIView _updateConstraintsAsNecessaryAndApplyLayoutFromEngine] + 312 frame #8: 0x00000001a0fa97a4 UIKitCore-[UIView(Hierarchy) layoutSubviews] + 204 frame #9: 0x00000001a124fa78 UIKitCore-[_UIButtonBarStackView layoutSubviews] + 56 frame #10: 0x00000001a0f6430c UIKitCore-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2492 frame #11: 0x00000001a029d8d0 QuartzCoreCA::Layer::layout_if_needed(CA::Transaction*) + 496 frame #12: 0x00000001a0fa81d0 UIKitCore-[UIView(Hierarchy) layoutBelowIfNeeded] + 300 frame #13: 0x00000001a1843fa4 UIKitCore-[_UINavigationBarTransitionContextCrossfade _prepareContentView] + 132 frame #14: 0x00000001a18443bc UIKitCore-[_UINavigationBarTransitionContextCrossfade prepare] + 84 frame #15: 0x00000001a184e59c UIKitCore-[_UINavigationBarVisualProviderModernIOS _performAnimationWithTransitionCompletion:transition:] + 1524 frame #16: 0x00000001a180f938 UIKitCore-[UINavigationBar _popNavigationItemWithTransitionAssistant:] + 220 frame #17: 0x00000001a180f5f8 UIKitCore-[UINavigationBar _popNavigationItemWithTransition:] + 224 frame #18: 0x00000001a13bec9c UIKitCore-[UINavigationBar _setItemsUpToItem:transition:] + 240 frame #19: 0x00000001a13be76c UIKitCore-[UIViewController _removeNavigationItemsFromNavigationController:transition:] + 232 frame #20: 0x00000001a19c9dc0 UIKitCore__89-[UINavigationController _immediatelyApplyViewControllers:transition:animated:operation:]_block_invoke_3 + 800 frame #21: 0x00000001a19d0b2c UIKitCore__98-[UINavigationController _shouldSkipHostedRefreshControlUpdateSchedulingDeferredUpdateIfNecessary]_block_invoke + 40 frame #22: 0x00000001a19d7574 UIKitCore-[UINavigationController transitionConductor:didStartDeferredTransition:context:] + 792 frame #23: 0x00000001a21c9600 UIKitCore-[_UIViewControllerTransitionConductor startDeferredTransitionIfNeeded] + 688 frame #24: 0x00000001a10ab040 UIKitCore-[UINavigationController __viewWillLayoutSubviews] + 84 frame #25: 0x00000001a1350bcc UIKitCore-[UILayoutContainerView layoutSubviews] + 172 frame #26: 0x00000001a0f6430c UIKitCore-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2492 frame #27: 0x00000001a029d8d0 QuartzCoreCA::Layer::layout_if_needed(CA::Transaction*) + 496 frame #28: 0x00000001a029d45c QuartzCoreCA::Layer::layout_and_display_if_needed(CA::Transaction*) + 148 frame #29: 0x00000001a02f64e0 QuartzCoreCA::Context::commit_transaction(CA::Transaction*, double, double*) + 472 frame #30: 0x00000001a02736c4 QuartzCoreCA::Transaction::commit() + 648 frame #31: 0x00000001a02b6584 QuartzCoreCA::Transaction::flush_as_runloop_observer(bool) + 88 frame #32: 0x00000001a1002c3c UIKitCore_UIApplicationFlushCATransaction + 52 frame #33: 0x00000001a10002dc UIKitCore_UIUpdateSequenceRun + 84 frame #34: 0x00000001a0ffff2c UIKitCoreschedulerStepScheduledMainSection + 172 frame #35: 0x00000001a1000df0 UIKitCorerunloopSourceCallback + 92 frame #36: 0x000000019e7edf90 CoreFoundation__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28 frame #37: 0x000000019e7edf24 CoreFoundation__CFRunLoopDoSource0 + 176 frame #38: 0x000000019e7eba10 CoreFoundation__CFRunLoopDoSources0 + 244 frame #39: 0x000000019e7eac14 CoreFoundation__CFRunLoopRun + 840 frame #40: 0x000000019e7ea4c8 CoreFoundationCFRunLoopRunSpecific + 572 frame #41: 0x00000001eb06d1c4 GraphicsServicesGSEventRunModal + 164 frame #42: 0x00000001a1334a90 UIKitCore-[UIApplication _run] + 816 frame #43: 0x00000001a13e2d1c UIKitCoreUIApplicationMain + 340 frame #44: 0x000000010038ca7c LabWare Developmentmain at AppDelegate.swift:31:7 frame #45: 0x00000001c4f4e9b4 dyldstart + 2724
Topic: UI Frameworks SubTopic: UIKit Tags:
2
0
724
Aug ’24
UITab view controller not being displayed when tapped from within a UITabGroup
The following: tabBarController.tabs = [ UITab(title: "First", image: UIImage(...), identifier: "First Tab") { _ in myViewController() } Works as expected. Tap on a a tab or sidebar item, and myViewController appears. However, the following: let collectionsGroup = UITabGroup( title: "Lists", image: nil, identifier: "Tabs.CollectionsGroup", children: [ UITab(title: "First", image: nil, identifier: "First Tab") { _ in myViewController() } ]) { _ in fallbackViewController() } Does not work as expected. Tapping on any tab in the sidebar always displays fallbackViewController, instead of myViewController or any other specified view controllers in the given tab. Am I doing something wrong, or is this a bug with the current betas?
Topic: UI Frameworks SubTopic: UIKit
2
0
693
Aug ’24
Setting the `backgroundColor` property of UIBackgroundConfiguration breaks the default UIConfigurationColorTransformer
The following is a UIKit app that displays a collection view with list layout and diffable data source (one section, one row). class ViewController: UIViewController { var collectionView: UICollectionView! var dataSource: UICollectionViewDiffableDataSource<String, String>! override func viewDidLoad() { super.viewDidLoad() configureHierarchy() configureDataSource() } func configureHierarchy() { collectionView = .init(frame: .zero, collectionViewLayout: createLayout()) view.addSubview(collectionView) collectionView.frame = view.bounds collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight] } func createLayout() -> UICollectionViewLayout { UICollectionViewCompositionalLayout { section, layoutEnvironment in let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped) return NSCollectionLayoutSection.list(using: config, layoutEnvironment: layoutEnvironment) } } func configureDataSource() { let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, String> { cell, indexPath, itemIdentifier in var backgroundConfiguration = UIBackgroundConfiguration.listGroupedCell() backgroundConfiguration.backgroundColor = .systemBlue cell.backgroundConfiguration = backgroundConfiguration } dataSource = .init(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier) } var snapshot = NSDiffableDataSourceSnapshot<String, String>() snapshot.appendSections(["main"]) snapshot.appendItems(["demo"]) dataSource.apply(snapshot, animatingDifferences: false) } } If you tap on the row, it seems like selection doesn't happen: giving the cell a blue background broke its default background color transformer. Here's what I've tried and didn't work: Setting the collection view's delegate and specifying that you can select any row Setting the color transformer to .grayscale Setting the backgroundConfiguration to UIBackgroundConfiguration.listGroupedCell().updated(for: cell.configurationState) Combinations of the approaches above Setting the color transformer to UIBackgroundConfiguration.listGroupedCell().backgroundColorTransformer and cell.backgroundConfiguration?.backgroundColorTransformer (they're both nil) Setting the cell's backgroundColor directly I also considered using a custom color transformer: var backgroundConfiguration = UIBackgroundConfiguration.listGroupedCell() backgroundConfiguration.backgroundColorTransformer = UIConfigurationColorTransformer { _ in if cell.configurationState.isSelected || cell.configurationState.isHighlighted { .systemBlue.withAlphaComponent(0.7) } else { .systemBlue } } cell.backgroundConfiguration = backgroundConfiguration However, if you push a view controller when you select the row, the row gets deselected, which is unfortunate, giving that I like to deselect rows in viewWillAppear(_:) to keep users more oriented. There might be ways to circumvent this, but my custom color transformer might still differ from the default one in some other ways. So how do I assign the default one to my cell?
Topic: UI Frameworks SubTopic: UIKit
4
0
545
Aug ’24
In iOS 18 beta, UICollectionView/scrollToItem(at:at:animated:) now scrolls at 4 FPS
In iOS 18.0, UICollectionView/scrollToItem(at:at:animated:) causes UICollectionView to scroll with an awkward stuttered animation at about 4 frames per second on the device. This behavior is not observed in iOS 15, 16, or 17. I submitted FB13986989 about this issue 6 weeks ago when I first observed it in iOS 18 beta 1, but I have not received a response. The issue has not been fixed in iOS 18.0 beta 2, 3, or 4. Is this a known issue? Does Apple intend to fix it? Assuming Apple has not prioritized fixing this bug, could a UIKit engineer suggest a workaround? My app relies on scrollTo working properly and now looks awful on iOS 18. Thank you for any assistance you can provide.
2
0
1.1k
Aug ’24
UILabel Attributed Text Anomaly: Unexpected Strikethrough When Setting Text Property in Swift
The following code, will create a red color text, without strike-through. class ViewController: UIViewController { @IBOutlet weak var label: UILabel! override func viewDidLoad() { super.viewDidLoad() let text = "Hello World" let textCount = text.count let fullRange = NSRange(location: 0, length: textCount) var attributedText = NSMutableAttributedString(string: text) attributedText.addAttribute(.foregroundColor, value: UIColor.green, range: fullRange) attributedText.addAttribute(.strikethroughStyle, value: NSUnderlineStyle.single.rawValue, range: fullRange) label.attributedText = attributedText attributedText = NSMutableAttributedString(string: text) attributedText.addAttribute(.foregroundColor, value: UIColor.red, range: fullRange) attributedText.removeAttribute(NSAttributedString.Key.strikethroughStyle, range: fullRange) label.attributedText = attributedText } } However, if I trigger label.text in between, it will cause the following strange behavior : A red color text, with strike-through created at the end of function. class ViewController: UIViewController { @IBOutlet weak var label: UILabel! override func viewDidLoad() { super.viewDidLoad() let text = "Hello World" let textCount = text.count let fullRange = NSRange(location: 0, length: textCount) var attributedText = NSMutableAttributedString(string: text) attributedText.addAttribute(.foregroundColor, value: UIColor.green, range: fullRange) attributedText.addAttribute(.strikethroughStyle, value: NSUnderlineStyle.single.rawValue, range: fullRange) label.attributedText = attributedText // Why this will cause a red color text, with strike-through created at the end of function? label.text = text attributedText = NSMutableAttributedString(string: text) attributedText.addAttribute(.foregroundColor, value: UIColor.red, range: fullRange) attributedText.removeAttribute(NSAttributedString.Key.strikethroughStyle, range: fullRange) label.attributedText = attributedText } } Does anyone what is the reason behind this behavior, and how I can avoid such? Thank you.
Topic: UI Frameworks SubTopic: UIKit
0
0
356
Aug ’24
Crash when keywindow.rootViewController changed using iOS 18
I have already searched for a lot of information about this issue. Many people have encountered it with UISplitViewController or on iPadOS, but I am experiencing this problem on iOS 18. It does occasionally occur on iOS 17, but it definitely happens on iOS 18. The error messages are as follow: *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Layout requested for visible navigation bar, <UINavigationBar: 0x14a6b3c00; frame = (0 44; 375 44); autoresize = W; tintColor = UIExtendedGrayColorSpace 1 1; layer = <CALayer: 0x3026a9da0>> delegate=0x14a674600 standardAppearance=0x300d1d0a0 scrollEdgeAppearance=0x300d1cf50, when the top item belongs to a different navigation bar. topItem = <UINavigationItem: 0x14a7f8780> style=navigator leftBarButtonItems=0x302423b40, navigation bar = <UINavigationBar: 0x14adcb700; frame = (0 0; 375 44); autoresize = W; tintColor = UIExtendedGrayColorSpace 1 1; layer = <CALayer: 0x302680940>> delegate=0x14ade8c00 standardAppearance=0x300d7a7d0 scrollEdgeAppearance=0x300d7a610, possibly from a client attempt to nest wrapped navigation controllers.' *** First throw call stack: (0x193f3a08c 0x191242698 0x19330a8fc 0x196939290 0x1966847b4 0x1967cdc88 0x1959ba6d8 0x1966c86bc 0x196769d50 0x1967cae58 0x196771f28 0x196b0fcb8 0x196764800 0x196684280 0x1959ba6d8 0x1959ba264 0x195a12edc 0x195990560 0x1968295f0 0x193f1c218 0x193f0a4c0 0x193f09b84 0x193f09368 0x1e00fc1c4 0x196a569b0 0x196b04d54 0x10462b1fc 0x1ba144734) libc++abi: terminating due to uncaught exception of type NSException I am sure about the process on iOS 17, first I use UINavigationController.present(UINavigationController()) and then call keyWindow.rootViewController = UINavigationController(), it crashes. So I can dismiss the presentedViewController before assign keyWindow.rootViewController. However, on iOS 18, the app crash when launch.
2
0
997
Aug ’24
React to pinned state of a CollectionView header
I'm in the process of rewriting a TableView as a modern CollectionView, using UICollectionLayoutListConfiguration and UICollectionViewCompositionalLayout.list together with a diffable data source. One feature of our TableView is that it has section headers that are pinned when scrolling (plain table view style). They also change their background based on whether they are currently pinned or not. This is accomplished by setting UITableViewHeaderFooterView's automaticallyUpdatesBackgroundConfiguration to false and override updateConfiguration(using:). However, I don't see a way of doing the same for a CollectionView's header. I can easily provide a header view by setting the supplementaryViewProvider of the data source, and they are sticky thanks to UICollectionLayoutListConfiguration.Appearance.plain But the header view itself is a UICollectionReusableView which does not seem to have the same mechanism as UITableViewHeaderFooterView for reacting to changes to the pinned state. Is it at all possible to accomplish this with CollectionView headers? If so, how?
Topic: UI Frameworks SubTopic: UIKit
1
0
379
Aug ’24
iOS 18 beta 5 NSAttributedString Crash
In iOS 18 beta 5 version, setting the conversion to NSAttributedString using [.documentType: NSAttributedString.DocumentType.html] occasionally causes crashes. The same issue was encountered in previous versions. However, after running the code on the main thread, it no longer crashed. But after upgrading to the iOS 18 beta 5 version, it occasionally crashes even when running on the main thread. How can this issue be resolved? thx~
3
3
1.4k
Aug ’24
iOS 18 new beta5 version crash when call NSMutableAttributedString init
after update to iOS 18 beta5,We found that the next code will crash. When we use html string to generate to a NSMutableAttributedString object. It will be crash. NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithData:[@"some html string" dataUsingEncoding:NSUTF8StringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute : @(NSUTF8StringEncoding) } documentAttributes:nil error:nil];
Topic: UI Frameworks SubTopic: UIKit
2
1
456
Aug ’24
TVOS focus stops working in search keyboard
Hi everyone, I'm trying to solve an issue with focus not being updated in UISearchController keyboard after some letters are typed (one or more if I'm lucky enough to swipe quickly). This started happening when I switched to Xcode 15 and the latest tvOS SDK. The focus engine logs do not explain much to me The result of the focus update was determined from the following preferred focus search: | | Starting preferred focus search. | <UIViewController: 0x10711d180> | └ <RCTRootView: 0x10711a810> | │ No more preferred environments. Trying to infer environment from visual layout... | │ Found environment: <UIKeyboard: 0x105ffcc40> | └ <UIKeyboard: 0x105ffcc40> | (info) It's focusable! | Moving focus from <UIKeyboard: 0x105ffcc40> to <UIKeyboard: 0x105ffcc40> in focus system <UIFocusSystem: 0x303568600>. Ignoring focus update request for disappearing focus environment <UIKBFloatingKeyView: 0x105eeb130>. <<TYPE LETTER GOES HERE >> - ISSUE: This environment does not contain the currently focused item. Ignoring focus update request for disappearing focus environment <_UITextLayoutFragmentView: 0x105fff620>. - ISSUE: This environment does not contain the currently focused item. Ignoring focus update request for disappearing focus environment <UISearchBarTextFieldLabel: 0x105ff6f70>. - ISSUE: This environment does not contain the currently focused item. Ignoring focus update request for disappearing focus environment <UILabel: 0x105ff5090>. - ISSUE: This environment does not contain the currently focused item. In the "focus-freeze" state is not possible to swipe anymore, but I still can repeat typing of the last letter. I'd appreciate any hints on how to debug this problem. Is it possible to list gesture recognizers or other objects that are consuming TV remote events ? I've confirmed the the [UIWindow sendEvent:] is still being triggered.
1
0
591
Aug ’24
UIScrollView Incorrectly Scrolls When Selecting Text in UITextView on iOS 15
I'm experiencing an issue in my iOS app where tapping to select text in a UITextView that is embedded within a UIScrollView causes the scroll view to jump to an incorrect position. This problem seems to occur only on iOS 15. Does anyone know how to fix this issue, or is there a known bug regarding this behavior on iOS 15? class ViewController: UIViewController, UITextViewDelegate, UIGestureRecognizerDelegate { @IBOutlet weak var textView: UITextView! @IBOutlet weak var scrollView: UIScrollView! override func viewDidLoad() { super.viewDidLoad() textView.isScrollEnabled = false textView.layoutManager.allowsNonContiguousLayout = false } }
2
0
495
Aug ’24
ios18 crash
so, we used iOS18 beat5 int our APP, crash list: try self.init(data: data, options: [.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil) html to NSAttributedString crash UINavigationController.viewControllers.remove(at: referIndex)
Topic: UI Frameworks SubTopic: UIKit
10
1
1.2k
Aug ’24
UISearchBar placeHolder and leftView is dissappearing.
I have UISearchBar, when I run from xCode placeholder and icon is working well but when i run from simulator or testflight placeholder and icon is dissappear. How can I solve it? Here my code: view: private lazy var searchBar: UISearchBar = { let view = UISearchBar() view.delegate = self view.barTintColor = UIColor.clear view.backgroundColor = UIColor.clear view.isTranslucent = true view.setBackgroundImage(UIImage(), for: .any, barMetrics: .default) view.placeholder = "Search" return view }() setup method: view.addSubview(searchBar) view.addSubview(collectionView) searchBar.snp.makeConstraints { make in make.top.equalTo(view.safeAreaLayoutGuide).inset(17) make.leading.trailing.equalToSuperview().inset(6) make.height.equalTo(40) }
Topic: UI Frameworks SubTopic: UIKit Tags:
1
0
391
Aug ’24
UITextView's pressesBegan isn't triggered by the software keyboard
I'm building a SwiftUI app with a UITextView subclass, and it seems that the software keyboard doesn't trigger the pressesBegan or pressesEnded functions of UITextView. With a hardware keyboard, pressesBegan works as expected, allowing us to intercept key presses in our subclass. I can't find any documentation about this, or any other forum posts (here or on Stack Overflow) that talk about a discrepancy between software and hardware keyboard behaviors, and I can't believe this is an intended behavior. Our app is a SwiftUI app, in case that's relevant. Does anyone have any guidance? Is this a bug or am I not understanding this API? Any information or work arounds would be greatly appreciated. I've made a sample project that demonstrates this issue, which you can grab from GitHub at https://github.com/nyousefi/KeyPressSample. To see this in action, run the sample project and start pressing keys. The hardware keyboard will print the key press at the top of the screen (above the text view), while the software keyboard won't.
3
0
632
Aug ’24
UICollectionView internal inconsistency: missing final attributes for cell
Hi, I'm running into a crash I can't wrap my head around. I'm using a collectionView with a compositional layout. Upon reloading the collection view via reloadData or reloading a particular section via reloadSection, customers are running into a crash I'm unable to reproduce. The only information is this: Fatal Exception: NSInternalInconsistencyException UICollectionView internal inconsistency: missing final attributes for cell <UICollectionViewListCell: 0x13ad42a40; frame = (0 791; 768 40); layer = <CALayer: 0x28268e0e0>>; initial attributes: <UICollectionViewLayoutAttributes: 0x13ac5aa90> index path: (<NSIndexPath: 0xb33e6ceee91dbb86> {length = 2, path = 4 - 0}); frame = (0 791; 768 40); ; layout query: <UICollectionViewLayoutAttributes: 0x137db5190> index path: (<NSIndexPath: 0xb33e6ceee91dbb86> {length = 2, path = 4 - 0}); frame = (0 800; 768 44); ; collection view: <UICollectionView: 0x13d120a00; frame = (0 0; 768 904); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x2829ad7d0>; layer = <CALayer: 0x2827f1cc0>; contentOffset: {0, 0}; contentSize: {768, 1715}; adjustedContentInset: {0, 0, 0, 0}; layout: <UICollectionViewCompositionalLayout: 0x13ad2bd50>; dataSource: <drchrono_EHR.AppointmentDetailViewController: 0x139fff600>> Any help would be greatly appreciated. Thank you.
0
0
482
Aug ’24
Unexpected animation from UICalendarView embedded in UIStackView
I have a UICalendarView that is embedded in a UIStackView. When I hide/show items in the stack and cause the height of the stack to change, the UICalendarView animates unexpectedly: Note that the height and width of the UICalendarView remain unchanged and the animation appears to leave the actual content unchanged. Interestingly, if I select a month with 6 weeks it does not do this animation: Nothing I have tried has allowed me to avoid this distracting and unnecessary animation. Any thoughts as to why this is happening or, even better, is there anything I can do to avoid it? Appreciate the help!
Topic: UI Frameworks SubTopic: UIKit Tags:
1
0
453
Aug ’24
Crashes occurring with the viewControllerBefore and viewControllerAfter methods of UIPageViewController.
feedbackassistant: https://feedbackassistant.apple.com/feedback/14724519 (FB14724519) We are developing an app using UIPageViewController. We have configured the UIPageViewController to provide 1 or 2 pages with a .pageCurl animation. We discovered a scenario where the viewControllerBefore and viewControllerAfter methods of the UIPageViewControllerDataSource are being called excessively. This happens when dragging on the last page, including dragging along the vertical axis (e.g., dragging from the top right to the bottom left). In this scenario, crashes occur intermittently, and we have observed similar issues in Apple Books as well. We would like to eliminate or minimize these crashes. Unfortunately, due to design constraints, we cannot remove the animation or adjust the page transition speed. Questions: Are there any updates or news regarding this issue, such as changes in the UIKit framework? What is the best way to prevent or minimize this crash? Crash Informations: The number of view controllers provided (0) doesn't match the number required (2) for the requested transition The number of view controllers provided (0) doesn't match the number required (1) for the requested transition Crash Videos: https://www.dropbox.com/scl/fo/bz7ykvm41du29u03ywbwo/AHO1y7CxURIi7s2QrERxPZk?rlkey=ugavf4tqo22q60g5bexe3kguz&e=1&st=xao8ypm6&dl=0
Topic: UI Frameworks SubTopic: UIKit
2
1
518
Aug ’24
UICollectionViewLayout unexpected animations when cells contain AutoLayout views with custom height
The code for the issue is attached below. Hello, I am trying to implement a custom UICollectionViewLayout that does the following: Everything works great for the most part, however I have encountered some unexpected animations when applying a new snapshot: As you can see, any cell that contains a custom view with a height set with AutoLayout is scaled vertically before animating to it's intended height. Here is a simple Xcode project that demonstrates the issue. Tap on the plus sign in the top right corner and watch the cells. Example project: https://we.tl/t-9Y25NHzxiI Custom UICollectionViewLayout code: final class CustomLayout: UICollectionViewLayout { struct PMCardContainerLayoutCell: Equatable { var column: Int var row: Int } // Configurable properties public var numberOfColumns: Int = 6 public var cellHeight: Double = 100 public var cellSpacing: Double = 20 public var rowSpacing: Double = 20 public var sectionInsets: NSDirectionalEdgeInsets = .zero public var layoutAttributes: [IndexPath: UICollectionViewLayoutAttributes] = [:] override func prepare() { super.prepare() guard let collectionView else { return } var updatedLayoutAttributes: [IndexPath: UICollectionViewLayoutAttributes] = [:] let columnWidth: Double = (collectionView.bounds.width - cellSpacing * Double(numberOfColumns - 1) - sectionInsets.leading - sectionInsets.trailing) / Double(numberOfColumns) let numberOfSections: Int = collectionView.numberOfSections for section in 0..<numberOfSections { var occupiedCells: [PMCardContainerLayoutCell] = [] var currentColumn: Int = 0 var currentRow: Int = 0 let numberOfItems: Int = collectionView.numberOfItems(inSection: section) for item in 0..<numberOfItems { let itemIndexPath = IndexPath(item: item, section: section) let itemAttributes = UICollectionViewLayoutAttributes(forCellWith: itemIndexPath) let itemSpanColumn = 1 let itemHeight = layoutAttributes[itemIndexPath]?.bounds.height ?? 140 let itemSpanRow = Int(ceil(itemHeight / (cellHeight + rowSpacing))) let itemWidth = columnWidth * Double(itemSpanColumn) + cellSpacing * (Double(itemSpanColumn) - 1) while true { var itemDoesFit: Bool = true if currentColumn + itemSpanColumn > numberOfColumns { currentColumn = 0 currentRow += 1 } for cell in 0..<itemSpanColumn { if occupiedCells.contains(.init(column: currentColumn + cell, row: currentRow)) { itemDoesFit = false } } if itemDoesFit { break } currentColumn += itemSpanColumn } if itemSpanRow > 1 { for row in 1..<itemSpanRow { for column in 0..<itemSpanColumn { occupiedCells.append(.init(column: currentColumn + column, row: currentRow + row)) } } } let originX = sectionInsets.leading + columnWidth * Double(currentColumn) + cellSpacing * Double(currentColumn) let originY = + cellHeight * Double(currentRow) + rowSpacing * Double(currentRow) itemAttributes.frame = CGRect( x: originX, y: originY, width: itemWidth, height: itemHeight ) itemAttributes.zIndex = itemIndexPath.section * 10 + itemIndexPath.item updatedLayoutAttributes[itemIndexPath] = itemAttributes currentColumn += itemSpanColumn } } layoutAttributes = updatedLayoutAttributes } override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { var allAttributes: [UICollectionViewLayoutAttributes] = [] for (_, attributes) in layoutAttributes { if (rect.intersects(attributes.frame)) { allAttributes.append(attributes) } } return allAttributes } override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { return layoutAttributes[indexPath] } override var collectionViewContentSize: CGSize { guard let collectionView else { return .zero } let contentHeight: CGFloat = layoutAttributes.map({ $0.value.frame.maxY }).max() ?? 0 return CGSize(width: collectionView.bounds.width, height: contentHeight) } override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { return true } override func shouldInvalidateLayout(forPreferredLayoutAttributes preferredAttributes: UICollectionViewLayoutAttributes, withOriginalAttributes originalAttributes: UICollectionViewLayoutAttributes) -> Bool { return originalAttributes.frame.height != preferredAttributes.frame.height } override func invalidationContext(forPreferredLayoutAttributes preferredAttributes: UICollectionViewLayoutAttributes, withOriginalAttributes originalAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutInvalidationContext { layoutAttributes[preferredAttributes.indexPath]?.frame.size = preferredAttributes.frame.size let context = super.invalidationContext(forPreferredLayoutAttributes: preferredAttributes, withOriginalAttributes: originalAttributes) return context } public override func invalidateLayout(with context: UICollectionViewLayoutInvalidationContext) { super.invalidateLayout(with: context) if context.invalidateEverything || context.invalidateDataSourceCounts { layoutAttributes.removeAll() } } } Anyone have any idea what I am doing wrong? Thank you!
Topic: UI Frameworks SubTopic: UIKit Tags:
1
0
381
Aug ’24