Can I ask why Apple added a new type UITextContentType - birthdate, but when you set it for a text field, and then become in that text field, the system doesn't offer your date of birth ?
I have already checked everything, the date of birth is set everywhere, I have created a new test application, only with one text field, I set it type “birthdate” and nothing offers, with all other types of fields and their setting, everything works fine. And there is no information about it anywhere on the internet.
And also, if you go to sites through safari, and becomes in the field to enter the date of birth, the system offers autofill, but in the application does not.
UIKit
RSS for tagConstruct and manage graphical, event-driven user interfaces for iOS or tvOS apps using UIKit.
Post
Replies
Boosts
Views
Activity
Tab bars on iPadOS 18 have moved to the top of the screen. They now share space with navigation bars.
We have added calls to setTabBarHidden(_:animated:) alongside existing calls to setNavigationBarHidden(_:animated:) in pushed view controller's viewWillAppear(_:) methods to manage the appearance of the tab bar and navigation bar within navigation controllers.
This results in layout issues with the safe area and navigation bar. I've attached screenshots from an example app demonstrating the issue. How can we manage the appearance of both the navigation bar and tab bar so that they share the same space when visible, but are properly hidden and excluded from the safe area when not?
/// The root view controller shows both the navigation bar and tab bar
class ViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(false, animated: animated)
tabBarController?.setTabBarHidden(false, animated: animated)
}
}
/// The second view controller hides both the navigation bar and tab bar
class ViewController2: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(true, animated: animated)
tabBarController?.setTabBarHidden(true, animated: animated)
}
@IBAction func customBackButtonTapped(_ sender: Any) {
navigationController?.popViewController(animated: true)
}
}
/// The third view controller shows the navigation bar but hides the tab bar
class ViewController3: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(false, animated: animated)
tabBarController?.setTabBarHidden(true, animated: animated)
}
}
I'm trying to unpack this sentence
Note that after adding a second text container to the layout manager, the text views become uneditable and unselectable.
Found on this example code:
https://developer.apple.com/documentation/uikit/textkit/display_text_with_a_custom_layout
I'm implementing my own UITextInput which makes use of the example code setup to replicate a multi-page text editor (kind of like a basic version of Pages/Word)
Each page has its own NSTextContainer which gets added to one NSLayoutManager.
The code works and my views are rendering text across each page, however, only the first text view is editable.
It appears this is "by design" (?)
How do we get around this? Is there another level we have to drop down to enable multiple editing containers?
The sample code is wayback in iOS 13, so it would seem very odd if the capability of multiple editable text fields/containers was impossible to achieve.
Sample app
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)
}
}
Problem
If you tap on the row, it doesn't look like it gets selected: the line backgroundConfiguration.backgroundColor = .systemBlue breaks the cell's default background color transformer.
Question
Given that my goal is to have my cell manifest its selection exactly like usual (meaning exactly as it would without the line backgroundConfiguration.backgroundColor = .systemBlue), that the details of how a cell usually does so are likely not public, that I would like to set a custom background color for my cell and that I would want to configure its appearance using configurations, since I seem to understand that that is the way to go from iOS 14 onwards, does anybody know how to achieve my goal by resetting something to whatever it was before I said backgroundConfiguration.backgroundColor = .systemBlue?
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 cell's backgroundConfiguration to UIBackgroundConfiguration.listGroupedCell().updated(for: cell.configurationState)
Setting the color transformer to cell.defaultBackgroundConfiguration().backgroundColorTransformer
Using collection view controllers (and setting collectionView.clearsSelectionOnViewWillAppear to false)
Setting the cell's automaticallyUpdatesBackgroundConfiguration to false and then back to true
Putting the cell's configuration code inside a configurationUpdateHandler
Combinations of the approaches above
Setting the color transformer to UIBackgroundConfiguration.listGroupedCell().backgroundColorTransformer and cell.backgroundConfiguration?.backgroundColorTransformer (they're both nil)
Workaround 1: use a custom color transformer
var backgroundConfiguration = UIBackgroundConfiguration.listGroupedCell()
backgroundConfiguration.backgroundColorTransformer = .init { _ in
if cell.configurationState.isSelected || cell.configurationState.isHighlighted || cell.configurationState.isFocused {
.systemRed
} else {
.systemBlue
}
}
cell.backgroundConfiguration = backgroundConfiguration
Workaround 2: don't use a background configuration
You can set the cell's selectedBackgroundView, like so:
let v = UIView()
v.backgroundColor = .systemBlue
cell.selectedBackgroundView = v
You won't be able to use custom background content configurations though and might want to use background views instead:
var contentConfiguration = UIListContentConfiguration.cell()
contentConfiguration.text = "Hello"
cell.contentConfiguration = contentConfiguration
let v = UIView()
v.backgroundColor = .systemBlue
cell.backgroundView = v
let bv = UIView()
bv.backgroundColor = .systemRed
cell.selectedBackgroundView = bv
Consideration on the workarounds
Both workarounds seem to also not break this code, which deselects cells on viewWillAppear(_:) and was taken and slightly adapted from Apple's Modern Collection Views project (e.g. EmojiExplorerViewController.swift):
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
deselectSelectedItems(animated: animated)
}
func deselectSelectedItems(animated: Bool) {
if let indexPath = collectionView.indexPathsForSelectedItems?.first {
if let coordinator = transitionCoordinator {
coordinator.animate(alongsideTransition: { [weak self] context in
self?.collectionView.deselectItem(at: indexPath, animated: true)
}) { [weak self] (context) in
if context.isCancelled {
self?.collectionView.selectItem(at: indexPath, animated: false, scrollPosition: [])
}
}
} else {
collectionView.deselectItem(at: indexPath, animated: animated)
}
}
}
(Collection view controllers don't sport all of that logic out of the box, even though their clearsSelectionOnViewWillAppear property is true by default.)
I am trying to build an application that interacts with iphone screen to perform operations like touch/tap/swipe (Not inside an app but whole screen). The closest tool to do it is FB IDB (Ios Development Bridge). But IDB doesn't support UI interactions with physical device, quoting that apple doesn't allow it. Is it possible to do it? If not, is there any official document that quotes apple doesn't allow UI interactions on physical devices, programmatically ?
I am trying to keep the tableVies scroll position when I come back into my screen. I am getting this error:
Terminating app due to uncaught exception 'NSRangeException', reason: 'Attempted to scroll the table view to an out-of-bounds row (7) when there are only 4 rows in section 0.
There should be 10 rows in section 0. I think that the tableView is not fully loaded and that's why the error says there is only 1 row in section 0 because this crash doesn't occur most of the time. Usually it works fine. Variable savedRowMainFave is saved in viewWillDisappear
I put some print statements to show values:
Leaving indexPath = [0, 7]. (this is in the viewWillDisappear(). Prints savedRowMainFave = (dealsTable.indexPathsForVisibleRows?.last) ?? savedRowMainFave)
filteredDeals.count = 10 (also in the viewWillAppear() this is the number of items in the array that populates the tableView called dealsTable)
this is the calculated rows = 10 (also in the viewWillAppear() this prints self.dealsTable.numberOfRows(inSection: savedRowMainFave.section))
This code scrolls to the saved position. The if statement is supposed to protect from crashing but is obviously self.dealsTable.numberOfRows(inSection: savedRowMainFave.section) is not working
if (self.dealsTable.numberOfRows(inSection: savedRowMainFave.section) > savedRowMainFave.row){
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {self.dealsTable.scrollToRow(at: savedRowMainFave, at: .bottom, animated: false)
}
Any suggestions for ways of verifying a valid savedRowMainIndex ( an indexPath) would be greatly appreciated. Thanks
Starting from August 6, some iOS18 users will experience crashes during the App startup phase. From the stack of the crash log, it can be seen that the system's Network library crashed. Below is the specific crash information, please check it out. This problem has never occurred before. Is this a bug in the iOS18 system?
I have an iOS app I've added Catalyst support to. It is a UIDocument based app using a UIDocumentBrowserController subclass.
When the app launches a file browser SHOULD appear in front of the app window. And if I have launched the app for the first time or it was force quit the last time it was used this works as intended.
However if I open a document and then quit the app either by closing the app window or choosing AppMenu -> Quit then launch the app again I get an error dialog that only Says "No document could be created" with an okay button. When you click okay the app window comes to the front covering the document browser creating an app killing problem that is confusing for users. Yes they can go to file -> New or File -> Open Document but the situation is very confusing.
I have tried returning false for these functions in my AppDelegate:
func application(_ application: UIApplication, shouldSaveApplicationState coder: NSCoder) -> Bool {
return false
}
func application(_ application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool {
return false
}
func application(_ application: UIApplication, shouldSaveSecureApplicationState coder: NSCoder) -> Bool{
return false
}
And I've added NSQuitAlwaysKeepsWindows = No in my info.plist and the problem persists.
I have set a break point in my document's init(fileURL:) function but it is not called so I have no idea what document is attempting to be created or how to stop it.
I am trying to build a Hangman game to play with my daughter since we both enjoy the game and playing together, but I have found issues regarding the size of the LiveLayout on the transcript screen
I have implemented the method contentSizeThatFits
override func contentSizeThatFits(_ size: CGSize) -> CGSize {
CGSize(width: 432, height: 700)
}
But even after implementing the size of the message bubble on transcript mode is not changing to adopt the size I am providing.
What should I do in this case? or how can I make the bubble to adopt a better size?
I tried to attach an image without any success.
Recently, my application has a crash, which did not exist before iOS18, how can I fix this problem, the following is crash stack
my code
how i ues it
darkText = NSAttributedString.getHtmlText(self.bannerModel?.darkText ?? "")
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!
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
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!
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.
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.
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)
}
I know, for secure reason, apple forbidden app the ability to get clipboard data in background.
But in some case, for example, i use appium to e2e testing my real device. And I could't get clipboard from webdriver. Because it's running background!
So, it's there any way to get clipboard from webdriver? It bothers me.
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)
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
}
}
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.