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

UIKit Documentation

Post

Replies

Boosts

Views

Activity

UISlider in Mac Catalyst updates UI too late
0 I am developing a Mac Catalyst app using UIKit. I have set the "Mac Catalyst Interface" of the target to "Optimize for Mac". All UISliders in my app update their UI "one interaction late": When I click on the slider track, the value of the slider changes accordingly, but the knob does not move to the appropriate position. Only when I click the second time, the knob moves to that position. But when I click on a different position on the track instead, the knob will move to the location corresponding to the previous click. What I tried: Changing "isContinuous", it has no effect. Listen for the "valueChanged" event and in the handler call "setNeedsLayout()" on the slider. Listen for the "valueChanged" event and in the handler call "setNeedsDisplay()" on the slider. When I change the target's "Mac Catalyst Interface" to "Scaled to match iPad", UISlider behaves as expected. But I need it to be "Optimize for Mac". FWIW, here is my code to add a UISlider in a UIViewController, it is super basic stuff: import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let slider = UISlider() view.addSubview(slider) slider.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ slider.heightAnchor.constraint(equalToConstant: 50), slider.widthAnchor.constraint(equalToConstant: 300), slider.centerXAnchor.constraint(equalTo: view.centerXAnchor), slider.centerYAnchor.constraint(equalTo: view.centerYAnchor) ]) slider.addTarget(self, action: #selector(onSlider(_:)), for: .valueChanged) } @objc func onSlider(_ slider: UISlider) { // slider.setNeedsLayout() // slider.setNeedsDisplay() print("on slider: \(slider.value)") } }
1
0
626
Apr ’23
Mac Catalyst Menu Bar/Toolbar Actions Not Validating Properly After Changing Active Windows
I have a multiple window Mac Catalyst app. I'm using a NSToolbar and the menu bar via UIMenuBuilder. I noticed after changing windows the menu bar isn't always validating properly. For example my app implements "Undo" and "redo". So I can reproduce the issue using these steps: Perform an action that can be undone. Open a new window. This new window has its own undo manager. In the Menu bar select Edit -> Undo Undo validates even though the current window has nothing on its local undo stack. If invoked undo is performed on the inactive window which definitely seems wrong. The same thing sometimes happens in reverse (that is, undo doesn't validate when it should after switching windows). This also happens with other actions after switching windows. Sometimes I can get the actions to validate by hitting the Tab key to move focus then shift tabbing back, which seems to force proper lookup in the responder chain (but sometimes that doesn't work). It seems that Catalyst is losing track of the real active window/window scene for some reason and is validating actions on the wrong window scene. Anyone experience this and know where I could be going wrong and/or know of a possible workaround? I tried subclassing UIApplication and implementing the methods there (and then forwarding them to the active UIWindowScene). However this doesn't work, the wrong window scene has its activationState set to UISceneActivationStateForegroundActive when the problem occurs.
9
1
1.6k
Apr ’23
Xcode 14 live issues broken, shows false errors, but the real errors show only after build and disappear couple of seconds later
Hello, I have several extremely annoying Xcode 14 issues that completely destroyed my productivity. They've been hunting me for the last three or so months. I even searched the darkest corners of the Internet to find the cure, but although I found some solutions for people that had similar problems as mine, they unfortunately didn't help me at all. I have a Swift UIKit project that targets iOS 13.0 and newer (only for iPhone), contains 3 schemas (dev, show and prod channels), uses swift packages with remote and local dependencies. No cocoa pods or something like this. Each schema only defines compilation conditions (so I determine in my code which channel I use), nothing more was affected in the settings. I also use a custom build script that only copies Firebase configuration file to the executable folder depending on project's schema. Even though I tried my best by keeping the project structure as clear as I can do and not changing any other settings, leaving them by default as is, I'm still experiencing frustration, rage and sadness at the same time when I'm working with this project. I encountered the first issue when I was using different Swift Packages depending on project's schema (for dev channel I used an autogenerated dev backend api and so on for show and prod - I wrapped them in #if #else blocks). I also updated Xcode at that time. So the problem was, I got a lot of in-editor error messages saying that Xcode could not find in scope, although the required package was already included in the file. And here comes the frustration - the project still successfully builds. I tried to solve this problem by merging these three packages into one and import them without #if #else tricks, but that didn't help. To make things even worse, autocompletion and code suggestion were broken for all imported Swift Packages - it doesn't matter if package was remote or local. I tried to clean, rebuild, close Xcode, remove DerivedData folder, open Xcode in every combination I can imagine, but that didn't work, the problem didn't go away. After a couple of updates I also realized that live issues were completely broken. I didn't get any warnings and errors while coding. Only after building the project, real warnings and errors appeared in the editor and issue navigator, but only for three-four seconds, and then disappeared again. That drove me crazy. Tried to solve this problem with the same methods, it didn't help. Only after disabling live issues, the real warnings and errors did not disappear, but code suggestion and completion were still not working. I enabled Xcode indexing log by typing defaults write com.apple.dt.Xcode IDEIndexShowLog -bool YES in the Terminal app. I found out that Xcode was not able to find one module: /somePath/SomeFile.swift 0.2 seconds no such module 'somePackageName' This error appeared for every file I open and every character I type, but the error was pointing only at that specific file that actually imports that module. So I import this module (also added in the project settings), but still get an error that the module was not found, but again the project successfully compiles and runs. It is an Xcode Framework from a third-party developer that they provided for us. The framework contains binaries only for ios-arm64 and ios-arm64_x86_64-simulator. I use a glorious M1 Mac. I decided yesterday to create a new project and copy there all code and resource files. I thought that I accidentally broke something in the settings and so I made them again from scratch. I did not had my Lightning cable this time, so I built the app for iPhone 14 Pro simulator. And the Xcode heard my prayers - everything was working great. The live issues worked as they should, I did not get any false errors and the autocompletion and code suggestions were fine. I got relief on that cloudy evening... But that's too good to be true, here is the plot twist. I got today my Lightning cable back, connected an iPhone to my Mac. And now I got all these issues again 💀 So now it looks like these issues only happen when I select a physical device as a run destination. I discovered it while writing this post. Any suggestions how to solve this?
4
10
4k
Apr ’23
iOS 16.x - Keyboard and speech crash
Crash - 1: Fatal Exception: NSRangeException 0 CoreFoundation 0x9e38 __exceptionPreprocess 1 libobjc.A.dylib 0x178d8 objc_exception_throw 2 CoreFoundation 0x1af078 -[__NSCFString characterAtIndex:].cold.1 3 CoreFoundation 0x1a44c -[CFPrefsPlistSource synchronize] 4 UIKitCore 0x1075f68 -[UIPredictionViewController predictionView:didSelectCandidate:] 5 TextInputUI 0x2461c -[TUIPredictionView _didRecognizeTapGesture:] 6 UIKitCore 0xbe180 -[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] 7 UIKitCore 0x42c050 _UIGestureRecognizerSendTargetActions 8 UIKitCore 0x1a5a18 _UIGestureRecognizerSendActions 9 UIKitCore 0x86274 -[UIGestureRecognizer _updateGestureForActiveEvents] 10 UIKitCore 0x132348 _UIGestureEnvironmentUpdate 11 UIKitCore 0x9ba418 -[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] 12 UIKitCore 0xf6df4 -[UIGestureEnvironment _updateForEvent:window:] 13 UIKitCore 0xfb760 -[UIWindow sendEvent:] 14 UIKitCore 0xfaa20 -[UIApplication sendEvent:] 15 UIKitCore 0xfa0d8 __dispatchPreprocessedEventFromEventQueue 16 UIKitCore 0x141e00 __processEventQueue 17 UIKitCore 0x44a4f0 __eventFetcherSourceCallback 18 CoreFoundation 0xd5f24 CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION 19 CoreFoundation 0xe22fc __CFRunLoopDoSource0 20 CoreFoundation 0x661c0 __CFRunLoopDoSources0 21 CoreFoundation 0x7bb7c __CFRunLoopRun 22 CoreFoundation 0x80eb0 CFRunLoopRunSpecific 23 GraphicsServices 0x1368 GSEventRunModal 24 UIKitCore 0x3a1668 -[UIApplication _run] 25 UIKitCore 0x3a12cc UIApplicationMain ============================================================ Crash - 2: Crashed: com.apple.root.background-qos 0 libobjc.A.dylib 0x1c20 objc_msgSend + 32 1 UIKitCore 0xb0e0d8 __37-[UIDictationConnection cancelSpeech]_block_invoke + 152 2 libdispatch.dylib 0x24b4 _dispatch_call_block_and_release + 32 3 libdispatch.dylib 0x3fdc _dispatch_client_callout + 20 4 libdispatch.dylib 0x15b8c _dispatch_root_queue_drain + 684 5 libdispatch.dylib 0x16284 _dispatch_worker_thread2 + 164 6 libsystem_pthread.dylib 0xdbc _pthread_wqthread + 228 7 libsystem_pthread.dylib 0xb98 start_wqthread + 8 ============================================================ I encountered the two keyboard-related crashes in iOS 16.x, but I cannot reproduce them. Can anyone tell me what is going on and how to fix them? Please let me know.
2
2
1.9k
Apr ’23
Memory leak with UISheetPresentationController
Hello, It appears that there is a memory leak when utilizing a UISheetPresentationController. Please take a look at this simple project available here. On the iOS 16.4 simulator for iPhone 14, if I dismiss the sheet, SheetViewController is successfully deinitialized. However, when I run this code on a real device (iPhone XR, iOS 16.4.1), the deinit of SheetViewController is not triggered. It seems like the presentation controller which holds a reference to SheetViewController stays in memory, captured by a closure. Here is the memory leak caused by iOS: Is this bug already known to the community? Should I report it? Is there any workaround for this issue? Thank you.
2
3
888
May ’23
iOS 16.4.1 keyboard dismisses when reloadSections or reloadItems is called
I have an UICollectionView with 2 sections. First section contains a single header cell with an UITextfield. Second section has basic UICollectionViewCells inside of it. When the UITextfield which is inside of the first section is focused and user changes value of text, I need to update second section item cells. After update cells with reloadSections/reloadItems UITextField loses focus and keyboard dismisses. This problem is not existed until iOS 16.4.1. Any idea about how to fix the issue?
4
1
891
May ’23
iOS 16.4 - UICollectionView and NSFetchedResultsController
Since iOS 16.4, a new exception is raised when "the number of sections and/or items returned by the data source before and/or after performing the batch updates are inconsistent with the updates". This post (iOS 16.4.1 - UICollectionViewController crashes) goes into some more detail, with a response from an Apple engineer, but doesn't explain exactly how this mechanism should/could work with NSFetchedResultsController. When using NSFetchedResultsController, its contents could contain unfetched/faulted core data objects in the tens of thousands. As the NSArray returned by NSFetchedResultsController is a reference type, the developer has no control over the point in time it is updated. Further, there doesn't seem to be a way to copy NSFetchedResultsSectionInfo without triggering a deep copy. Therefore, if a developer wishes to play nicely with the UICollectionView batch updates mechanism they are forced to make a deep copy of the results which means faulting a bunch of potentially unused objects and defeating a primary benefit of NSFetchedResultsController. Is there a more performance optimised way of getting UICollectionView batch updates and NSFetchedResultsController to play nicely?
3
0
947
May ’23
UIAlert message text not showed as multiline
I'm using the following code to create and show the UIAlert: let alert = UIAlertController(title: "Warning", message: "Are you sure you want to delete this notification?", preferredStyle: .alert) let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { _ in isDeletedNotification = false } let deleteAction = UIAlertAction(title: "Delete", style: .destructive) { _ in DispatchQueue.main.async { isDeletedNotification = true self.createNotificationToPost() } } alert.addAction(cancelAction) alert.addAction(deleteAction) present(alert, animated: true, completion: nil) It works fine when I run the app from Xcode in the simulator and the device When I stop Xcode and run the app in the simulator or in the device I have this: I was using Xcode 14.2 (14C18). MacBook Pro with macOS Monterey 12.6. I opened the same project in a different MacBook: Xcode 14.3.1 (14E300c). MacBook Pro M1 with macOS Ventura 13.4. In both cases I have the same result, the project is damaged or something? Is possible to fix it? I have the same results with UILabel in the custom cell.
1
0
479
Jun ’23
UITableViewDiffableDatasource crashes on iOS 17
Hi all, We recently got some new weird crash reports on our monitoring systems. These crashes happen in the table view diffable data source on iOS 17. We had these crashes never before on any other operating systems. The error says: Diffable data source detected an item identifier whose hash value changed. The hash value of an identifier cannot change once it has been added to a snapshot. Based on this information, an item's hash value should never change while we expect diffable datasource's apply() function to reload a row if its hash value changed. Full report of bug attached c5671824114048ed87d18f5afe967a97-symbolicated.crash
2
2
1.3k
Jun ’23
On/Off Button Title in updateUI()
I am working through the Getting Started with App Development and on Page 142 it has you write in the updateUI() function if else statement lightButton.setTitle("Off", for: .normal) and lightButton.setTitle("On", for: .normal). My app crashes every time after building it and running it. Image reference below. The app works perfectly fine before adding these two statements. import UIKit class ViewController: UIViewController { @IBOutlet var lightButton: UIButton! var lightOn = true fileprivate func updateUI() { if lightOn { view.backgroundColor = .white lightButton.setTitle("Off", for: .normal) } else { view.backgroundColor = .black lightButton.setTitle("On", for: .normal) } } @IBAction func buttonPressed(_ sender: Any) { lightOn.toggle() updateUI() } override func viewDidLoad() { super.viewDidLoad() updateUI() // Do any additional setup after loading the view. } } Getting this error at the end. libc++abi: terminating due to uncaught exception of type NSException (lldb)
5
0
408
Jul ’23
I have a problem with tableview.reloadData() method
I have a problem with reload data in table view. My app structure has two container views, where the first container view is collection view controller and the second container view is table view controller. In collection view, I select the cell and in table view I want to show information. I need to reload all the data in table view because I can select any cell in the collection view. In selectedDay I get information about the cell I selected in didSet I make a request to Firebase (fetchDataFromFirebase) and get information for the selected day. After that, I append data in workoutList array and in didSet I need to reload all my table view. My code in TableViewController class ScheduleTableViewController: UITableViewController { var selectedDay: Day? { didSet { workoutList.removeAll() fetchDataFromFirebase(day: selectedDay?.day ?? "", month: selectedDay?.month ?? "", year: selectedDay?.year ?? "") } } weak var delegate: EmptyDataInSelectedDayProtocol? private var workoutList = [NewWorkout]() { didSet { print(workoutList) print(workoutList.count) tableView.reloadData() } } override func viewDidLoad() { super.viewDidLoad() } // MARK: - Table view data source override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return workoutList.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ScheduleTableViewCell cell.configure(in: workoutList[indexPath.row]) return cell } // Override to support editing the table view. override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let reSchedule = UIContextualAction(style: .normal, title: "Change workout day") { [unowned self] action, view, completionHandler in workoutList.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .fade) completionHandler(true) } reSchedule.image = UIImage(systemName: "arrow.up.arrow.down") reSchedule.backgroundColor = .primary.withAlphaComponent(0.8) return UISwipeActionsConfiguration(actions: [reSchedule]) } private func fetchDataFromFirebase(day: String, month: String, year: String) { FirebaseHelper.shared.getRefenceFirebase() .child("\(FirebaseHelper.shared.getUserID())").observe(.value) { [self] snapshot in DispatchQueue.main.async { [self] in guard let value = snapshot.value as? [String:Any] else {return} for info in value { let data = value["\(info.key)"] as? NSDictionary guard let userName = data?["userName"] as? String else {return} guard let trainingStartDate = data?["trainingStartDate"] as? String else {return} guard let trainingTime = data?["trainingTime"] as? String else {return} guard let workoutDuration = data?["workoutDuration"] as? String else {return} guard let selectedColor = data?["selectedColor"] as? [String:Any] else {return} guard let workoutDates = data?["workoutDates"] as? [String] else {return} guard let weekDays = data?["weekDays"] as? [String:Any] else {return} for item in workoutDates { if "\(day).\(month).\(year)" == item { delegate?.isEmptyData(in: false) let workout: [NewWorkout] = [NewWorkout(userName: userName, weekDays: weekDays, trainingStartDate: trainingStartDate, workoutDuration: workoutDuration, wortoutTime: trainingTime, userColor: [UserColor(red: selectedColor["red"] as? Double ?? 0.0, green: selectedColor["green"] as? Double ?? 0.0, blue: selectedColor["blue"] as? Double ?? 0.0)], workoutDates: workoutDates)] workoutList.append(contentsOf: workout) } } } } } } }
2
0
277
Jul ’23
Issue with Merging Rooms - RoomPlan - Seeking Guidance
Hello fellow developers, When attempting to merge single rooms into one model, the resulting floorplan I got appears to have rooms stacked on top of each other. I am using a single ARSession for all the scans, to my understanding, the world coordinate system remains consistent during a continuous ARSession. I can't figure out why the rooms are overlapping or positioned vertically on top of each other in the generated floorplan. I am uncertain whether this issue stems from my own code implementation. I did the following modification to the sample code Initiated an ARSession in RoomCaptureViewController private var arWorldTrackingConfig: ARWorldTrackingConfiguration = ARWorldTrackingConfiguration() private var arSession: ARSession = ARSession() Pass ARSession to roomCaptureView private func setupRoomCaptureView() { arSession.run(arWorldTrackingConfig) roomCaptureView = RoomCaptureView(frame: view.bounds, arSession: arSession) roomCaptureView.captureSession.delegate = self roomCaptureView.delegate = self view.insertSubview(roomCaptureView, at: 0) } Pause the ARSession after completion of scanning one room private func saveSession() { isScanning = false roomCaptureView?.captureSession.stop(pauseARSession: false) setCompleteNavBar() } @IBAction func saveScanning(_ sender: UIBarButtonItem) { if isScanning { saveSession() } else { cancelScanning(sender) } self.exportButton?.isEnabled = false self.activityIndicator?.startAnimating() } Any experiences or insights are greatly appreciated.
5
1
1.1k
Jul ’23
UIButton not respecting maximumContentSizeCategory
I have a UIButton inside a dynamically-populated stack view that is within a self-sizing table view cell, and although it has a maximumContentSizeCategory of XXXL it is clearly not respecting that. Has anyone else run into this issue, and if so have you found a workaround? I used the appliedContentSizeCategoryLimitsDescription property described here: https://useyourloaf.com/blog/restricting-dynamic-type-sizes to confirm that the maximumContentSizeCategory is indeed being set correctly. This is in the iOS 16.2 iPhone 14 Pro simulator, running in Xcode 14.2.
4
0
979
Jul ’23
Restrict to UITextField cursor should only focus on end of text
I need to restrict to UITextField text cursor should only focus on end of text every time. Ex- if user entered OTP in textField and again he want to replace digit from text field when he tap to UITextField then cursor should focus on end of text only not beginning of text. I added below code func textFieldDidBeginEditing(_ textField: UITextField){ DispatchQueue.main.async{ let position = textField.endOfDocument textField.selectedTextRange = textField.textRange(from: position, to: position) } } It is working On first time textfield selection. After once cursor focussed in UITextField that time it is moving to Start position if user tap on start position.
1
0
1.3k
Jul ’23
Send touch events programmatically
We are using the Speech framework to enable users to interact with our app via voice commands. When a user says "start test" we send DispatchQueue.main.async { self.startButton.sendActions(for: .touchUpInside) } This works beautifully, except that the screen goes into auto lockout in the middle of a test. Apparently, using sendActions does not actually send a touch event to the OS. My question is how can I tell the OS that a touch event happened programmatically? Thank you
2
0
908
Jul ’23