Demo project link
https://cdn.pokekara.com/int/other/1737343007_fbcdee810da429552b12ffa2644d928c.zip
UIKit
RSS for tagConstruct and manage graphical, event-driven user interfaces for iOS or tvOS apps using UIKit.
Post
Replies
Boosts
Views
Activity
I am implementing a new Intents UI Extension and am noticing that the viewWillDisappear, viewDidDisappear, and deinit methods are not being called on my UIViewController that implements INUIHostedViewControlling, when pressing the "Done" button and dismissing the UIViewController.
This causes the memory for the UI Extension to slowly increase each time I re-run the UI Extension until it reaches the 120MB limit and crashes.
Any ideas as to what's going on here and how to solve this issue?
With iPadOS 18, the UITabBar now defaults to the floating style. I successfully reverted the tab bar to its traditional style by overriding the UITabBarController's horizontalSizeClass property:
self.tabBarController?.traitOverrides.horizontalSizeClass = .unspecified
When I launch the app on my Mac using Apple Silicon, TWO tab bars appear:
One appears at the bottom of the screen, like a traditional tab bar.
The second tab bar is still embedded in the app toolbar in its floating style.
Is this a bug? How do you ensure that overriding the horizontalSizeClass will remove/hide the floating tab bar when running an app on Apple Silicon? TIA!
(Demonstrated on a test project)
Using gesture recognizers it is easy to implement a long-press gesture to open a menu, show a preview or something else on the iOS platform. And you can provide the duration the user must hold down the finger until the gesture recognizer fires.
But I could not yet find out how to determine the default duration for a long-press gesture that is configured in the system settings within the "accessibility" settings under "Haptic Touch" (the available options are fast, standard and slow here).
Is it possible to read out this setting, so my App can adapt to this system setting as well?
System: iOS 18.1.1
When connected to Carplay, after playing a song, check the playback page CPNowPlayingTemplate. This error appears on the BMW car, as shown in the picture:
In our project, this is achieved using the following methods:
UIImage *image1 = [UIImage imageNamed:@"imageName"];;
CPNowPlayingImageButton *button1 = [[CPNowPlayingImageButton alloc] initWithImage:image1 handler:^(__kindof CPNowPlayingButton * _Nonnull action) {
//do something
}];
UIImage *image2 = [UIImage imageNamed:@"imageName"];;
CPNowPlayingImageButton *button2 = [[CPNowPlayingImageButton alloc] initWithImage:image2 handler:^(__kindof CPNowPlayingButton * _Nonnull action) {
//do something
}];
NSArray<CPNowPlayingButton *> *buttons;
buttons = @[button1,button2];
[[CPNowPlayingTemplate sharedTemplate] updateNowPlayingButtons:buttons];
Is there any way to solve this problem?
I'm trying to implement UI state restoration in an old Objective-C UIKit app that does not use scenes and also does not have a storyboard. I have implemented the correct AppDelegate methods -- application:shouldSaveSecureApplicationState: and application:shouldRestoreSecureApplicationState: -- and I can see that they are being called when expected.
I have also implemented the state restoration and UIViewControllerRestoration viewControllerWithRestorationIdentifierPath:coder: methods for the view controllers I want to persist and restore; along with correctly setting their restorationIdentifier and restorationClass properties. I can also see that those are being called when expected.
I've also installed the restorationArchiveTool and have verified that the persisted archive contains the expected view controllers and state.
However, once state restoration is complete, the window's rootViewController property is still nil and has not been assigned to the view controller that has the restorationIdentifier of the rootViewController at the time the state is persisted.
I found this sample app that does what I want to do -- persist and restore the state of the view controllers without the use of storyboards. Running that I verified that it does in fact work as expected.
https://github.com/darrarski/iOS-State-Restoration
The difference between what that app does and what mine does, is that it always creates the top level view controllers in application:willFinishLaunchingWithOptions:.
func application(_ application: UIApplication,
willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
let viewControllerA = DemoViewController()
viewControllerA.title = "A"
let navigationControllerA = UINavigationController(rootViewController: viewControllerA)
navigationControllerA.restorationIdentifier = "Navigation"
let viewControllerB = DemoViewController()
viewControllerB.title = "B"
let navigationControllerB = UINavigationController(rootViewController: viewControllerB)
navigationControllerB.restorationIdentifier = "Navigation"
let tabBarController = UITabBarController()
tabBarController.restorationIdentifier = "MainTabBar"
tabBarController.viewControllers = [navigationControllerA, navigationControllerB]
window = UIWindow(frame: UIScreen.main.bounds)
window?.restorationIdentifier = "MainWindow"
window?.rootViewController = tabBarController
return true
}
Unfortunately, my app is more dynamic and the rootViewController is determined after launch. When I updated the app to be structured more like mine, I see that it fails the same as mine and no longer restores the rootViewController.
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var didRestoreState = false
func application(_ application: UIApplication,
willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.restorationIdentifier = "MainWindow"
return true
}
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if !didRestoreState {
let viewControllerA = DemoViewController()
viewControllerA.title = "A"
let navigationControllerA = UINavigationController(rootViewController: viewControllerA)
navigationControllerA.restorationIdentifier = "Navigation"
let viewControllerB = DemoViewController()
viewControllerB.title = "B"
let navigationControllerB = UINavigationController(rootViewController: viewControllerB)
navigationControllerB.restorationIdentifier = "Navigation"
let tabBarController = UITabBarController()
tabBarController.restorationIdentifier = "MainTabBar"
tabBarController.viewControllers = [navigationControllerA, navigationControllerB]
window?.rootViewController = tabBarController
}
window?.makeKeyAndVisible()
return true
}
func application(_ application: UIApplication, shouldSaveSecureApplicationState coder: NSCoder) -> Bool {
let libraryDirectory = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first
let appStateUrl = libraryDirectory?.appendingPathComponent("Saved Application State")
NSLog("Restoration files: \(appStateUrl?.path ?? "none")")
return true
}
func application(_ application: UIApplication, shouldRestoreSecureApplicationState coder: NSCoder) -> Bool {
return true
}
func application(_ application: UIApplication, didDecodeRestorableStateWith coder: NSCoder) {
didRestoreState = true
}
}
I don't really understand why this doesn't work since the archive file looks identical in both cases, and the methods used to create and restore state of the view controllers are being called in both cases.
Is there something else I need to do to correctly restore the view controllers without having to create them all before state restoration begins?
I encountered an issue with UITextView on iOS 18 where, when typing Pinyin, extra Unicode characters such as U+2004 are inserted unexpectedly. This occurs when using a Chinese input method.
Steps to Reproduce:
1. Set up a UITextView with a standard delegate implementation.
2. Use a Pinyin input method to type the character “ㄨ”.
3. Observe that after the character “ㄨ” is typed, extra spaces (U+2004) are inserted automatically between the characters.
Code Example:
class ViewController: UIViewController {
@IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
extension ViewController: UITextViewDelegate {
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
print("shouldChangeTextIn: range \(range)")
print("shouldChangeTextIn: replacementText \(text)")
return true
}
func textViewDidChange(_ textView: UITextView) {
let currentText = textView.text ?? ""
let unicodeValues = currentText.unicodeScalars.map { String(format: "U+%04X", $0.value) }.joined(separator: " ")
print("textViewDidChange: textView.text: \(currentText)")
print("textViewDidChange: Unicode Scalars: \(unicodeValues)")
}
}
Output:
shouldChangeTextIn: range {0, 0}
shouldChangeTextIn: replacementText ㄨ
textViewDidChange: textView.text: ㄨ
textViewDidChange: Unicode Scalars: U+3128
------------------------
shouldChangeTextIn: range {1, 0}
shouldChangeTextIn: replacementText ㄨ
textViewDidChange: textView.text: ㄨ ㄨ
textViewDidChange: Unicode Scalars: U+3128 U+2004 U+3128
------------------------
shouldChangeTextIn: range {3, 0}
shouldChangeTextIn: replacementText ㄨ
textViewDidChange: textView.text: ㄨ ㄨ ㄨ
textViewDidChange: Unicode Scalars: U+3128 U+2004 U+3128 U+2004 U+3128
This issue may affect text processing, especially in cases where precise text manipulation is required, such as calculating ranges in shouldChangeTextIn.
The stack trace is: Fatal Exception: NSInternalInconsistencyException Need an imageRef Have you encountered similar problems?
I'm running into a problem with the focus order in my UICollectionView in my tvOS app. The layout of my app is outlined in the following diagram
On the uppermost layer I have a UITableView, each cell containing a single UICollectionView that can contain a variable number of UICollectionViewCells.
When the user swipes down, I want the left-most item in the next row down to be selected, as follows:
I've been able to get this to work for the majority of cases. The exception is when the previously focused item extends to the length of the screen - in this case the next focused item isn't the leftmost item, but rather the center item, as follows.
Using focus guides won't really fit the use case here since collection views are dynamically generated.
I've found that there is a function in UICollectionViewDelegate, indexPathForPreferredFocusedView that should help here but it only seems to be called intermittedly, even though I have set remembersLastFocusedIndexPath on the collectionview to true. I can force it to be called by calling setNeedsFocusUpdate() but I can't figure out a good place to call it - shouldUpdateFocus is too early and didUpdateFocus is too late.
Is there some way to constrain the focus area of a view to a certain subset of it's frame - for example, the left-most quarter of its width?
Or does anyone know of some other solution to this problem?
More specifically, if I have 2 pinned tabs that are displayed in different order for compact and regular and switch between compact and regular, when it gets to regular mode, the images for both tabs will not be rendered. The tabs can still be pressed, just the icon is missing.
I set the isHidden property of a view in traitCollectionDidChange and found that sometime it does not take effect after being set(value of isHidden actually not changed either). It looks like the setting does not take effect when triggered an even number of times, but it is normal when triggered an odd number of times.
When setting isHidden, what actually goes into is [UIView (Rendering) setHidden:], which internally calls [UIView _ bitFlagValueAfterIncrementingHiddenManagement CountForKey: withIncrement: bitFlagValue:] to handle the relevant logic of "_UIViewPendingHiddenCount". Is this issue related to this part of the processing? returning 0 after calling seems normal
This view is a UIStackView, and it is uncertain whether it is related to the type of view
Hi there,
I am flagging for extra attention that it feels to me that something feels extra off about Screen Time tracking in iOS 18.3 Beta. There's been many days now where I can't reconcile the time spent (it's much higher than expected - by multiple hours).
Feedback is here with an image: FB16270245.
Not sure if happens on Beta 2 - just upgraded.
I am able to retrieve the text in the input field by doing:
let contextBeforeInput = textDocumentProxy.documentContextBeforeInput ?? ""
let contextAfterInput = textDocumentProxy.documentContextAfterInput ?? ""
let fullText = contextBeforeInput + contextAfterInput
However, when I'm pasting text into the input field, textDocumentProxy.documentContextBeforeInput refuses to return the entire text from the input field but instead only returns the last two sentences.
I have tried this with the input fields in WhatsApp, Signal, and Telegram and it's all the same, so it doesn't seem to be caused by the specific app.
At first I thought it was a limitation imposed by Apple but other third party keyboard extensions such as Grammarly are able to pick up the whole pasted text from the input field, so how are they doing it?
I am trying to give bottom padding to tabbar i.e ** tabBarFrame.origin.y = view.frame.height - tabBarHeight - 30** but it is not moving up from bottom, it gets sticked to bottom = 0 and the tabbar content moving up taher than tabbar itself..
Code snippet is -
`i override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let tabBarHeight: CGFloat = 70 // Custom height for the capsule tab bar
var tabBarFrame = tabBar.frame
tabBarFrame.size.height = tabBarHeight
tabBarFrame.size.width = view.frame.width - 40
tabBarFrame.origin.y = view.frame.height - tabBarHeight - 30
tabBarFrame.origin.x = 20
tabBar.frame = tabBarFrame
tabBar.layer.cornerRadius = tabBarHeight / 2
tabBar.clipsToBounds = true
view.bringSubviewToFront(tabBar)
}`
Can anyone please help to resolve the issue for iOS 18, it is coming in iOS 18 rest previous versions are fine with the code.
We have a sample code that initialises an NSAttributed string with simple HTML code and the result differs massively since XCode 16 and iPadOS 18 SDK.
DESCRIPTION OF PROBLEM Since Xcode Version 16.1 HTML content passed into an NSAttributedString is not rendered correctly. Specifically, enumeration characters (such as bullet points or numbers) and the proper indentation for text within list items are missing. As a result, the structure of the HTML content, especially ordered and unordered lists, is not displayed as expected.
STEPS TO REPRODUCE A UILabel was added to the view in a new Objective-C project in Xcode.
A HTML string containing and Tags was converted into an NSAttributedString (With NSAttributedString::initWithData and NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType Parameter)within the viewDidLoad method and assigned to the UILabel.
Expected Result:
The lists should be displayed correctly with enumeration characters and appropriate indentation, as shown in the attached screenshot expected_result.jpeg.
Same Code still works as expected using XCode 15.x
Actual Result:
The list is displayed without enumeration characters or indentation, which matches the attached screenshot actual_result.jpeg.
Sample Code
NSString *html = @"Es ist wichtig, dass Sie Ihren Arzt informieren:\n<ol>\n\t<li><strong>HIER !!!!!!! </strong>Wenn Sie gegenwärtig mit Zometa®, dass die gleiche aktive Substanz enthält wie Aclasta® behandelt werden.</li>\n</ol>\n\n<ul>\n\t<li><strong>Hier !!!!!!</strong> Wenn Sie Nierenbeschwerden haben oder hatten, denn Ihre Nieren müssen korrekt funktionieren, um das überflüssige Aclasta ® das für Ihre Knochen nicht benötigt wird, ausscheiden zu können.</li>\n\t<li>Wenn sie Medikamente einnehmen, die Kortsion als Bestandteil enthalten (z. B. Prendisolon oder Dexamethason)</li>\n\t<li>Wenn sie unter schlechter Zahngesundheit oder Zahnfleischerkrankungen leiden oder wenn eine Zahnextraktion geplant ist</li>\n</ul>\n";
NSString *textAttr = [NSString stringWithFormat:@"<span style=\"font-family:Arial; line-height: 80%%; font-size:10px;\">%@</style>", html];
NSData *data = [textAttr dataUsingEncoding:NSUTF16StringEncoding];
NSAttributedString *string = [[NSAttributedString alloc] initWithData:data
options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: @(NSUTF16StringEncoding)}
documentAttributes:nil error:nil];
self.label.numberOfLines = 0;
self.label.attributedText = string;
Greetings
Before ios18, when two fingers are switched to single fingers, the printing scale value will not change. When switching to two fingers again, the pinch and zoom printing scale will change. The same operation is performed after ios18, and two fingers are switched to single fingers. Switch back to two fingers, and the scale printing will not change.
code here:
- (void)pinchGesture:(UIPinchGestureRecognizer *)recognizer {
NSSet <UIEvent*> *events = [recognizer valueForKey:@"_activeEvents"];
UIEvent *event = [events anyObject];
if (recognizer.state == UIGestureRecognizerStateBegan) {
NSLog(@"---- begin finger count: %d scale: %f",event.allTouches.count,recognizer.scale);
recognizer.scale = 1.0;
} else if (recognizer.state == UIGestureRecognizerStateChanged) {
NSLog(@"---- change finger count: %d scale: %f",event.allTouches.count,recognizer.scale);
// recognizer.scale = 1.0;
}
log image for iOS 17.7
log image for ios18.0.2
Hi everyone,
I've come across an issue on iOS that seems to affect many apps. Here's what happens:
A user logs in with correct credentials and proceeds to the OTP verification screen as part of multi factor authentication.
iOS presents the system password save prompt ("Would you like to save this password?").
Without selecting an option on this prompt, the user backgrounds the app (e.g., to check their email for the OTP).
Upon returning to the app, the keyboard becomes completely inaccessible on the OTP screen or any other screen.
From my testing, this behavior appears to be an OS-level bug, as it occurs consistently across various apps. Has anyone else encountered this? Any known workarounds or updates from Apple on this behavior would be greatly appreciated!
Thanks!
Question
How can I suppress this prohibition mark during this operation?
Background
I am implementing drag-and-drop functionality in a UITableView to allow users to reorder cells. During the drag operation, when a cell is dragged back to its original position, a prohibition mark (🚫) appears over the cell.
I have reviewed the API documentation for UITableViewDragDelegate and UITableViewDropDelegate, but I could not find any clear way to suppress this mark. The behavior does not impact functionality but is visually unappealing.
What I Tried
Customizing UITableViewDropProposal: I ensured that operation is set to .move and intent to .insertAtDestinationIndexPath. This did not resolve the issue.
Customizing drag preview: Using dragPreviewParametersForRowAt to set a clear background. The prohibition mark still appeared.
Verifying drop session: Checked the UIDropSession state in dropSessionDidUpdate to ensure valid drop handling.
Environment
Xcode Version: Version 16.2
Testing Device: iPhone 16 pro + iOS 18.2
Steps to Reproduce
Code Example
Create new app with this ViewController
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITableViewDragDelegate, UITableViewDropDelegate {
let tableView = UITableView()
var items = ["Item 1", "Item 2", "Item 3", "Item 4"]
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
tableView.delegate = self
tableView.dataSource = self
tableView.dragDelegate = self
tableView.dropDelegate = self
tableView.dragInteractionEnabled = true
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
tableView.separatorStyle = .none
tableView.layer.cornerRadius = 10
tableView.backgroundColor = UIColor.systemGray6
view.addSubview(tableView)
NSLayoutConstraint.activate([
tableView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5),
tableView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
tableView.topAnchor.constraint(equalTo: view.topAnchor, constant: 50),
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -50)
])
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = items[indexPath.row]
cell.textLabel?.textAlignment = .center
cell.backgroundColor = UIColor.systemBlue.withAlphaComponent(0.2)
cell.layer.cornerRadius = 10
cell.clipsToBounds = true
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 60
}
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
let dragItem = UIDragItem(itemProvider: NSItemProvider(object: items[indexPath.row] as NSString))
dragItem.localObject = items[indexPath.row]
return [dragItem]
}
func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal {
guard destinationIndexPath != nil else {
return UITableViewDropProposal(operation: .cancel)
}
return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
}
func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
guard let destinationIndexPath = coordinator.destinationIndexPath,
let dragItem = coordinator.items.first?.dragItem.localObject as? String else {
return
}
if let sourceIndex = items.firstIndex(of: dragItem) {
tableView.performBatchUpdates {
items.remove(at: sourceIndex)
items.insert(dragItem, at: destinationIndexPath.row)
tableView.moveRow(at: IndexPath(row: sourceIndex, section: 0), to: destinationIndexPath)
}
coordinator.drop(coordinator.items.first!.dragItem, toRowAt: destinationIndexPath)
}
}
}
Run simulator and start dragging a cell without moving it to a different position.
Observe that a prohibition mark appears at the upper right of the cell
Any guidance would be greatly appreciated. Thank you in advance!
hi does any one know if there changes in lifecycle in xcode 16 ios 18 cause i notice that my view will appear does what view didappear use to do in older version and it kind of a problem cause all the rest of ios work diffrently does anyone else found a problem with it?
or does anyone know if there was a known change to life cycles
I don't know why, but for my MacCatalyst target, I have to make my view controller Y orgin 36 and the subtract the view height by 36 points, or the view is clipped.
The following works in my main UIViewController, but feels super hacky. I'd feel better if I understood the issue and addressed it properly.
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
#if targetEnvironment(macCatalyst)
if view.frame.origin.y < 1 {
let f = UIApplication.shared.sceneBounds
let newFrame = CGRect(x: 0.0, y: 36, width: f.size.width, height: f.size.height - 36)
self.view.frame = newFrame
}
#endif
}
My guess is it starts the view under the title bar, but I have these set in the view controller:
self.extendedLayoutIncludesOpaqueBars = false
self.edgesForExtendedLayout = []