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

Posts under UIKit tag

200 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

How long does the proximity sensor work on iPhone devices with dynamic islands?
On iPhone devices with dynamic islands (e.g. iPhone 15 Pro Max), the proximity sensor takes about 3 seconds to activate, is this normal? The iPhone 13 responds almost instantly, but the iPhone 15 Pro Max seems to take a while. // Shared instance for global access (optional) static let shared = ProximitySensorManager() // Proximity sensor activation flag private(set) var isSensorEnabled: Bool = false // Start observing proximity sensor changes func enableProximitySensor(observer: Any) { guard !isSensorEnabled else { return } isSensorEnabled = true UIDevice.current.isProximityMonitoringEnabled = true NotificationCenter.default.addObserver( observer, selector: #selector(proximityStateChanged), name: UIDevice.proximityStateDidChangeNotification, object: nil ) } // Stop observing proximity sensor changes func disableProximitySensor(observer: Any) { guard isSensorEnabled else { return } isSensorEnabled = false UIDevice.current.isProximityMonitoringEnabled = false NotificationCenter.default.removeObserver( observer, name: UIDevice.proximityStateDidChangeNotification, object: nil ) } // Proximity sensor state change handler @objc private func proximityStateChanged() { if UIDevice.current.proximityState { print("Proximity sensor detected close object") // Additional functionality can be added here (e.g. lowering the screen brightness) } else { print("Proximity sensor detected no object") } } deinit { //disableProximitySensor() // Clean up observer on deinitialization } }
1
0
150
Oct ’24
VoiceOver focus jumping around when adding UIViewController as Child to another UIViewController
I'm facing an accessibility issue, where when I call UIViewController.addChild(_:) and pass in another instance of a UIViewController, the VoiceOver focus is jumping to the "Back" button in the navigation bar. How might one go about avoid this behaviour and having the accessibility/voiceover focus remain where it was at the time of adding the child?
1
0
245
Oct ’24
Navigation Bar Elements Disappear When Using UIPageViewController in SwiftUI Under Low Power Mode
Problem Description: In a SwiftUI application, I've wrapped UIKit's UIPageViewController using UIViewControllerRepresentable, naming the wrapped class PagedInfiniteScrollView. This component causes navigation bar elements (title and buttons) to disappear. This issue only occurs in Low Power Mode on a physical device. Steps to Reproduce: Enable Low Power Mode on a physical device and open the app's home page. From the home page, open a detail sheet containing PagedInfiniteScrollView. This detail page include a navigation title and a toolbar button in the top-right corner. PagedInfiniteScrollView supports horizontal swiping to switch pages. Tap the toolbar button in the top-right corner of the detail page to open an edit sheet. Without making any changes, close the edit sheet and return to the detail page. On the detail page, swipe left and right on the PagedInfiniteScrollView. Expected Result: When swiping the PagedInfiniteScrollView, the navigation title and top-right toolbar button of the detail page should remain visible. Actual Result: When swiping the PagedInfiniteScrollView, the navigation title and top-right toolbar button of the detail page disappear. import SwiftUI @main struct CalendarApp: App { var body: some Scene { WindowGroup { ContentView() } } } import SwiftUI struct ContentView: View { @State private var showDetailSheet = false @State private var currentPage: Int = 0 var body: some View { NavigationStack { Button { showDetailSheet = true } label: { Text("show Calendar sheet") } .sheet(isPresented: $showDetailSheet) { DetailSheet(currentPage: $currentPage) } } } } struct DetailSheet: View { @Binding var currentPage: Int @State private var showEditSheet = false var body: some View { NavigationStack { PagedInfiniteScrollView(content: { pageIndex in Text("\(pageIndex)") .frame(width: 200, height: 200) .background(Color.blue) }, currentPage: $currentPage) .sheet(isPresented: $showEditSheet, content: { Text("edit") }) .navigationTitle("Detail") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItemGroup(placement: .topBarTrailing) { Button { showEditSheet = true } label: { Text("Edit") } } } } } } import SwiftUI import UIKit struct PagedInfiniteScrollView<Content: View>: UIViewControllerRepresentable { typealias UIViewControllerType = UIPageViewController let content: (Int) -> Content @Binding var currentPage: Int func makeCoordinator() -> Coordinator { Coordinator(self) } func makeUIViewController(context: Context) -> UIPageViewController { let pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal) pageViewController.dataSource = context.coordinator pageViewController.delegate = context.coordinator let initialViewController = UIHostingController(rootView: IdentifiableContent(index: currentPage, content: { content(currentPage) })) pageViewController.setViewControllers([initialViewController], direction: .forward, animated: false, completion: nil) return pageViewController } func updateUIViewController(_ uiViewController: UIPageViewController, context: Context) { let currentViewController = uiViewController.viewControllers?.first as? UIHostingController<IdentifiableContent<Content>> let currentIndex = currentViewController?.rootView.index ?? 0 if currentPage != currentIndex { let direction: UIPageViewController.NavigationDirection = currentPage > currentIndex ? .forward : .reverse let newViewController = UIHostingController(rootView: IdentifiableContent(index: currentPage, content: { content(currentPage) })) uiViewController.setViewControllers([newViewController], direction: direction, animated: true, completion: nil) } } class Coordinator: NSObject, UIPageViewControllerDataSource, UIPageViewControllerDelegate { var parent: PagedInfiniteScrollView init(_ parent: PagedInfiniteScrollView) { self.parent = parent } func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { guard let currentView = viewController as? UIHostingController<IdentifiableContent<Content>>, let currentIndex = currentView.rootView.index as Int? else { return nil } let previousIndex = currentIndex - 1 return UIHostingController(rootView: IdentifiableContent(index: previousIndex, content: { parent.content(previousIndex) })) } func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { guard let currentView = viewController as? UIHostingController<IdentifiableContent<Content>>, let currentIndex = currentView.rootView.index as Int? else { return nil } let nextIndex = currentIndex + 1 return UIHostingController(rootView: IdentifiableContent(index: nextIndex, content: { parent.content(nextIndex) })) } func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { if completed, let currentView = pageViewController.viewControllers?.first as? UIHostingController<IdentifiableContent<Content>>, let currentIndex = currentView.rootView.index as Int? { parent.currentPage = currentIndex } } } } extension PagedInfiniteScrollView { struct IdentifiableContent<Content: View>: View { let index: Int let content: Content init(index: Int, @ViewBuilder content: () -> Content) { self.index = index self.content = content() } var body: some View { content } } }
3
0
227
Oct ’24
UITextField Input Issue While Using Bilingual Keyboard in iOS 18
Input issues occur in the textField while using a bilingual keyboard (Korean and English). System settings: Keyboard: Bilingual (Korean & English) Project environment: Xcode >= 15.4 & iOS >= 18.0 Base localization: Korean // UITextField settings: textField.keyboardType = .decimalPad // or .phonePad self.textField.addTarget(self, action: #selector(self.textFieldEditingChanged), for: .editingChanged) @objc func textFieldEditingChanged() { self.textField.text = "\(self.textField.text!)-" } /* Input: 123456 Expected: 1-2-3-4-5-6- Result: 11111123456- */ The issue occurs when modifying the text of the textField in the editingChanged event. In the above code, a hyphen is appended to the input with each character. When typing 123456, the expected result is: Input: 1 → Result: 1- Input: 2 → Result: 1-2- … Input: 6 → Result: 1-2-3-4-5-6- However, the actual result is 11111123456-. Another example: @objc func textFieldEditingChanged() { print("before", self.textField.text!) self.textField.text = self.textField.text?.replacingOccurrences(of: "0", with: "1") print("after", self.textField.text!) } When inputting 0 1 0 sequentially, the output is: before 0 after 1 before 01 after 11 before 010 after 111 The value of "after" matches expectations, but the "before" value reverts to 0 on the next input, even though it appears as 1 on the UI. When the bilingual keyboard option is turned off or the base localization is set to something other than Korea, the issue does not occur. Could you provide information on whether this issue will be resolved in the next iOS version, or if there is a workaround?
7
0
594
Oct ’24
tvOS App support portrait display?
Hi, We are going to create a tvOS App with portrait display(HDMI screen will rotate 90 degree). It seems there is no rotate setting in tvOS18, neither Xcode provide relative support. As our investigation, we might need to rotate each UIKit component 90 degree by code to archive it. Is there any better suggestion? Thanks.
0
0
250
Oct ’24
Unable to change UITabbar Background color in iOS 18 for ipad
I am trying to change UITabBar background color runtime as theme changed. It is already working in iOS 17 as I am updating UITabBar.appearance().barTintColor and tintColor But for iOS first i need to change because I don't want that new elevated tabbar so I create custom tabbar controller as described in https://stackoverflow.com/questions/78631030/how-to-disable-the-new-uitabbarcontroller-view-style-in-ipados-18 Accepted Answer by awulf. And by doing this, My tabbar looks same like Old and it is working in iPhone and ipad for iOS 16, iOS 17 and iOS 18 too. But the issue is that I am unable to change my tabbar background color. I have also checked this forum: https://forums.developer.apple.com/forums/thread/761056 But not able to change I have set below 3 properties but no effect let appearance = UITabBar.appearance() appearance.backgroundColor = appearance.barTintColor = appearance.tintColor = I have created CustomTabBarController in storyboard and all working fine Also the appearance changed only once per application lifecycle. It will change color by restarting the app then it will pick last selected theme and the colors are changed. but not able to change colors runtime I have also did below code for reloading purpose tabBar.setNeedsLayout() tabBar.setNeedsDisplay() But nothing work
0
0
392
Oct ’24
Swift pressesBegan no longer works iOS 18?
Previously this code would trigger fine on pressesBegan in iOS 17 and earlier versions, but no longer works in iOS 18. How can I start capturing pressesBegan in iOS 18? It seems like UIResponder is just not capturing the keyboard anymore? struct ContentView: View { var body: some View { KeyBoardView() } } //To Use in SwiftUI struct KeyBoardView: UIViewRepresentable{ func makeUIView(context: Context) -> KeyEventView { KeyEventView() } func updateUIView(_ uiView: KeyEventView, context: Context) { } class KeyEventView: UIView { init() { super.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0)) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) { print("test") } } }
0
0
170
Oct ’24
Invalid memory pointer crash: cannot figure out cause
Hi there! I'm one year into iOS development, and can usually figure out the cause of a crash. However, I've been bumping my head against this one for a while now. Invalid memory pointer crash According to this article, the crash (EXC_BAD_ACCESS) happens due to an invalid memory pointer. When I use the atos command to symbolicate the crash report, the line where the crash happens in my app (see line 39 in the full stack trace below) is simply the very first line in MyApp that extends App (annotated with @main) -- but there's no code on that line. It seems like the error is happening somewhere with UIKit's UIViewController but I can't seem to figure it out. Could be relevant code I do have the following class in my app, which helps with hiding the tab bar I use when another view is opened. It might be relevant: struct HideTabBar: UIViewControllerRepresentable { var callback: (UITabBar) -> Void private let proxyController = ViewController() func makeUIViewController(context: UIViewControllerRepresentableContext<HideTabBar>) -> UIViewController { proxyController.callback = callback return proxyController } func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<HideTabBar>) { } typealias UIViewControllerType = UIViewController private class ViewController: UIViewController { var callback: (UITabBar) -> Void = { _ in } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) if let tabBar = self.tabBarController { self.callback(tabBar.tabBar) } } } } Full stack trace: Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000010 Exception Codes: 0x0000000000000001, 0x0000000000000010 VM Region Info: 0x10 is not in any region. Bytes before following region: 4363845616 REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL UNUSED SPACE AT START ---> Termination Reason: SIGNAL 11 Segmentation fault: 11 Terminating Process: exc handler [664] Triggered by Thread: 0 Kernel Triage: VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter Thread 0 name: Dispatch queue: com.apple.main-thread Thread 0 Crashed: 0 libobjc.A.dylib 0x19205fc20 objc_msgSend + 32 1 UIKitCore 0x19c697a68 -[UIViewController dealloc] + 860 2 UIKitCore 0x19c863c80 -[UINavigationController dealloc] + 296 3 UIKitCore 0x19c863b34 -[_UISplitViewControllerColumnContents .cxx_destruct] + 44 4 libobjc.A.dylib 0x192061acc object_cxxDestructFromClass(objc_object*, objc_class*) + 116 5 libobjc.A.dylib 0x192060f00 objc_destructInstance + 80 6 libobjc.A.dylib 0x192060ea4 _objc_rootDealloc + 80 7 CoreFoundation 0x19a0fc730 cow_cleanup + 164 8 CoreFoundation 0x19a0fec80 -[__NSDictionaryM dealloc] + 148 9 libobjc.A.dylib 0x192061acc object_cxxDestructFromClass(objc_object*, objc_class*) + 116 10 libobjc.A.dylib 0x192060f00 objc_destructInstance + 80 11 libobjc.A.dylib 0x192060ea4 _objc_rootDealloc + 80 12 UIKitCore 0x19c8f4a54 -[UISplitViewControllerPanelImpl dealloc] + 100 13 libobjc.A.dylib 0x192061acc object_cxxDestructFromClass(objc_object*, objc_class*) + 116 14 libobjc.A.dylib 0x192060f00 objc_destructInstance + 80 15 libobjc.A.dylib 0x192060ea4 _objc_rootDealloc + 80 16 UIKitCore 0x19c457730 -[UIResponder dealloc] + 124 17 UIKitCore 0x19c697ba0 -[UIViewController dealloc] + 1172 18 libobjc.A.dylib 0x192060df4 AutoreleasePoolPage::releaseUntil(objc_object**) + 212 19 libobjc.A.dylib 0x192060c80 objc_autoreleasePoolPop + 260 20 UIKitCore 0x19c4315ec -[_UIAfterCACommitBlock run] + 92 21 UIKitCore 0x19c43149c -[_UIAfterCACommitQueue flush] + 164 22 UIKitCore 0x19c4313b4 _runAfterCACommitDeferredBlocks + 496 23 UIKitCore 0x19c430fec _cleanUpAfterCAFlushAndRunDeferredBlocks + 80 24 UIKitCore 0x19c430efc _UIApplicationFlushCATransaction + 72 25 UIKitCore 0x19c42e660 _UIUpdateSequenceRun + 84 26 UIKitCore 0x19c42e2a4 schedulerStepScheduledMainSection + 172 27 UIKitCore 0x19c42f148 runloopSourceCallback + 92 28 CoreFoundation 0x19a14b834 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28 29 CoreFoundation 0x19a14b7c8 __CFRunLoopDoSource0 + 176 30 CoreFoundation 0x19a149298 __CFRunLoopDoSources0 + 244 31 CoreFoundation 0x19a148484 __CFRunLoopRun + 828 32 CoreFoundation 0x19a147cd8 CFRunLoopRunSpecific + 608 33 GraphicsServices 0x1deb951a8 GSEventRunModal + 164 34 UIKitCore 0x19c781ae8 -[UIApplication _run] + 888 35 UIKitCore 0x19c835d98 UIApplicationMain + 340 36 SwiftUI 0x19e33c294 0x19df48000 + 4145812 37 SwiftUI 0x19e2e8860 0x19df48000 + 3803232 38 SwiftUI 0x19e2f461c 0x19df48000 + 3851804 39 MyApp 0x1041f8690 0x1041b0000 + 296592 40 dyld 0x1bd91f154 start + 2356
0
1
197
Oct ’24
AppleArchive crashes on corrupt archive instead of failing gracefully
We're trying to implement a backup/restore data feature in our business productivity iPad app using UIDocumentPickerViewController and AppleArchive, but discovered AppleArchive crashes instead of failing gracefully when decrypting a corrupt archive. As described in forum post 765101, UIDocumentPickerViewController can handoff a corrupt copy of an archive to UIDocumentPickerDelegate under specific circumstances. We've duplicated this behavior with iPadOS 16.6.1 and 17.7 when building our app with Xcode 15.4 targeting minimum deployment of iPadOS 16. We haven't tested this with the bleeding edge iPadOS 18. Our app is primarily Objective-C, but it utilizes the Swift-based AppleArchive 'EncryptingAndDecryptingDirectories' sample code associated with WWDC21 session: 10233: Bring Encrypted Archives and Performance Improvements to Your App with Accelerate. The WWDC21 'EncryptingAndDecryptingDirectories' Swift sample project crashes in a similar manner when a corrupt archive file created by UIDocumentPickerViewController is dropped into the sample app's window for decryption (see attached crash log). Does anyone know if there's a workaround for the 'EncryptingAndDecryptingDirectories' sample project to prevent AppleArchive from crashing when decrypting a corrupt archive? crash log.txt
2
0
259
Sep ’24
UIDocumentPickerViewController provides corrupt copy of file when user taps multiple times on file
We're trying to implement a backup/restore data feature in our business productivity iPad app using UIDocumentPickerViewController and AppleArchive, but discovered odd behavior of [UIDocumentPickerViewController initForOpeningContentTypes: asCopy:YES] when reading large archive files from a USB drive. We've duplicated this behavior with iPadOS 16.6.1 and 17.7 when building our app with Xcode 15.4 targeting minimum deployment of iPadOS 16. We haven't tested this with bleeding edge iPadOS 18. Here's our Objective-C code which presents the picker: NSArray* contentTypeArray = @[UTTypeAppleArchive]; UIDocumentPickerViewController* docPickerVC = [[UIDocumentPickerViewController alloc] initForOpeningContentTypes:contentTypeArray asCopy:YES]; docPickerVC.delegate = self; docPickerVC.allowsMultipleSelection = NO; docPickerVC.shouldShowFileExtensions = YES; docPickerVC.modalPresentationStyle = UIModalPresentationPopover; docPickerVC.popoverPresentationController.sourceView = self.view; [self presentViewController:docPickerVC animated:YES completion:nil]; The UIDocumentPickerViewController remains visible until the selected external archive file has been copied from the USB drive to the app's local tmp sandbox. This may take several seconds due to the slow access speed of the USB drive. During this time the UIDocumentPickerViewController does NOT disable its tableview rows displaying files found on the USB drive. Even the most patient user will tap the desired filename a second (or third or fourth) time since the user's initial tap appears to have been ignored by UIDocumentPickerViewController, which lacks sufficient UI feedback showing it's busy copying the selected file. When the user taps the file a second time, UIDocumentPickerViewController apparently begins to copy the archive file once again. The end result is a truncated copy of the selected file based on the time between taps. For instance, a 788 MB source archive may be copied as a 56 MB file. Here, the UIDocumentPickerDelegate receives a 56 MB file instead of the original 788 MB of data. Not surprisingly, AppleArchive fails to decrypt the local copy of the archive because it's missing data. Instead of failing gracefully, AppleArchive crashes in AAArchiveStreamClose() (see forums post 765102 for details). Does anyone know if there's a workaround for this strange behavior of UIDocumentPickerViewController?
2
0
270
Oct ’24
Application Got Crash in IOS 18 device
Can anyone help me to resolve this issue? I have two collectionviews in a tableview and each time you try to scroll the collecctionview after clicking a cell, it crashes with the following error: *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Expected dequeued view to be returned to the collection view in preparation for display. When the collection view's data source is asked to provide a view for a given index path, ensure that a single view is dequeued and returned to the collection view. Avoid dequeuing views without a request from the collection view. For retrieving an existing view in the collection view, use -[UICollectionView cellForItemAtIndexPath:] or -[UICollectionView supplementaryViewForElementKind:atIndexPath:]
2
1
844
Oct ’24
iOS 18 Issue: When we add arm64 into Excluded Architecture and try to present screen, Screen will get froze and unable to select images.
I am using Storyboard to present a UIImagePickerController on a view controller (a simple initial view without any navigation or tab bar). Due to a requirement, we need to exclude the arm64 architecture. However, when I try to present the screen, it gets stuck. I am unable to select an image, and the screen becomes inaccessible. It's happening only on simulator. Does anyone have any solution.
1
0
307
Oct ’24
XCode or IOS 18 Bug?
I just finished updating my app to support the new screen sizes for the iPhone 16 series devices (iPhone16 Pro and iPhone 16 Pro Max). In testing the changes, I've come across what I hope is simply a bug in the Xcode 16 simulators. I don't have any actual devices (yet) that I can use to test. In landscape mode, my app presents a "tab" on the right side of the screen that can be tapped to bring out another view. Activating the tab is based on capturing the screen coordinates from a "tap". In Xcode 16, using the iPhone16 simulators on IOS 18, the area of the tab does not recognize that a tap has occurred. After hours of banging my head against my laptop, it dawned on me that the area of the screen that hosts the "tab" is in exactly the same location as "unavailable area" that represents the camera on the simulator. I have arrived at the assumption that the issue is that the simulator is treating the same space at the bottom of the device as it treats that reserved area at the top of the screen. Has anyone else experienced this? Is this a bug in the simulator or is this expected behavior on the iPhone 16 series devices?
3
1
707
Sep ’24
Issue with OCR on Swift iOS App: Roboflow API Bounding Boxes Missing After Response
Hi everyone, I'm working on an iOS app built in Swift using Xcode, where I'm integrating Roboflow's object detection API to extract items from grocery receipts. My goal is to identify key information (like items, total, tax, etc.) from the images of these receipts. I'm successfully sending images to the Roboflow API and receiving predictions with bounding box data, but when I attempt to extract text from the detected regions (bounding boxes), it appears that the text extraction is failing—no text is being recognized. The issue seems to be that the bounding boxes are either not properly being handled or something is going wrong in the way I process the API response. Here's a brief breakdown of what I'm doing: The image is captured, converted to base64, and sent to the Roboflow API. The API response comes back with bounding boxes for the detected elements (items, date, subtotal, etc.). The problem occurs when I try to extract the text from the image using the bounding box data—it seems like the bounding boxes are being found, but no text is returned. I suspect the issue might be happening because the app’s segue to the results view controller is triggered before the OCR extraction completes, or there might be a problem in my code handling the bounding box response. Response Data: { "inference_id": "77134cce-91b5-4600-a59b-fab74350ca06", "time": 0.09240847699993537, "image": { "width": 370, "height": 502 }, "predictions": [ { "x": 163.5, "y": 250.5, "width": 313.0, "height": 127.0, "confidence": 0.9357666373252869, "class": "Item", "class_id": 1, "detection_id": "753341d5-07b6-42a1-8926-ecbc61128243" }, { "x": 52.5, "y": 417.5, "width": 89.0, "height": 23.0, "confidence": 0.8819760680198669, "class": "Date", "class_id": 0, "detection_id": "b4681149-d538-47b1-8700-d9528bf1daa0" }, ... ] } And the log showing bounding boxes: Prediction: ["width": 313, "y": 250.5, "x": 163.5, "detection_id": 753341d5-07b6-42a1-8926-ecbc61128243, "class": Item, "height": 127, "confidence": 0.9357666373252869, "class_id": 1] No bounding box found in prediction. I've double-checked the bounding box coordinates, and everything seems fine. Does anyone have experience with using OCR alongside object detection APIs in Swift? Any help on how to ensure the bounding boxes are properly processed and used for OCR would be greatly appreciated! Also, would it help to delay the segue to the results view controller until OCR is complete? Thank you!
0
0
333
Sep ’24
Displaying limited contacts list in UIKit
I have an app that was written in UIKit. It's too large, and it would be much too time consuming at this point to convert it to SwiftUI. I want to incorporate the new limited contacts into this app. The way it's currently written everything works fine except for showing the limited contacts in the contact picker. I have downloaded and gone though the Apple tutorial app but I'm having trouble thinking it through into UIKit. After a couple of hours I decided I need help. I understand I need to pull the contact IDs of the contacts that are in the limited contacts list. Not sure how to do that or how to get it to display in the picker. Any help would be greatly appreciated. func requestAccess(completionHandler: @escaping (_ accessGranted: Bool) -> Void) { switch CNContactStore.authorizationStatus(for: .contacts) { case .authorized: completionHandler(true) case .denied: showSettingsAlert(completionHandler) case .restricted, .notDetermined: CNContactStore().requestAccess(for: .contacts) { granted, error in if granted { completionHandler(true) } else { DispatchQueue.main.async { [weak self] in self?.showSettingsAlert(completionHandler) } } } // iOS 18 only case .limited: completionHandler(true) @unknown default: break } } // A text field that displays the name of the chosen contact @IBAction func contact_Fld_Tapped(_ sender: TextField_Designable) { sender.resignFirstResponder() // The contact ID that is saved to the Db getTheCurrentContactID() let theAlert = UIAlertController(title: K.Titles.chooseAContact, message: nil, preferredStyle: .actionSheet) // Create a new contact let addContact = UIAlertAction(title: K.Titles.newContact, style: .default) { [weak self] _ in self?.requestAccess { _ in let openContact = CNContact() let vc = CNContactViewController(forNewContact: openContact) vc.delegate = self // this delegate CNContactViewControllerDelegate DispatchQueue.main.async { self?.present(UINavigationController(rootViewController: vc), animated: true) } } } let getContact = UIAlertAction(title: K.Titles.fromContacts, style: .default) { [weak self] _ in self?.requestAccess { _ in self?.contactPicker.delegate = self DispatchQueue.main.async { self?.present(self!.contactPicker, animated: true) } } } let editBtn = UIAlertAction(title: K.Titles.editContact, style: .default) { [weak self] _ in self?.requestAccess { _ in let store = CNContactStore() var vc = CNContactViewController() do { let descriptor = CNContactViewController.descriptorForRequiredKeys() let editContact = try store.unifiedContact(withIdentifier: self!.oldContactID, keysToFetch: [descriptor]) vc = CNContactViewController(for: editContact) } catch { print("Getting contact to edit failed: \(self!.VC_String) \(error)") } vc.delegate = self // delegate for CNContactViewControllerDelegate self?.navigationController?.isNavigationBarHidden = false self?.navigationController?.navigationItem.hidesBackButton = false self?.navigationController?.pushViewController(vc, animated: true) } } let cancel = UIAlertAction(title: K.Titles.cancel, style: .cancel) { _ in } if oldContactID.isEmpty { editBtn.isEnabled = false } theAlert.addAction(getContact) // Select from contacts theAlert.addAction(addContact) // Create new contact theAlert.addAction(editBtn) // Edit this contact theAlert.addAction(cancel) let popOver = theAlert.popoverPresentationController popOver?.sourceView = sender popOver?.sourceRect = sender.bounds popOver?.permittedArrowDirections = .any present(theAlert,animated: true) } func requestAccess(completionHandler: @escaping (_ accessGranted: Bool) -> Void) { switch CNContactStore.authorizationStatus(for: .contacts) { case .authorized: completionHandler(true) case .denied: showSettingsAlert(completionHandler) case .restricted, .notDetermined: CNContactStore().requestAccess(for: .contacts) { granted, error in if granted { completionHandler(true) } else { DispatchQueue.main.async { [weak self] in self?.showSettingsAlert(completionHandler) } } } // iOS 18 only case .limited: completionHandler(true) @unknown default: break } } // MARK: - Contact Picker Delegate extension AddEdit_Quote_VC: CNContactPickerDelegate { func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) { selectedContactID = contact.identifier let company: String = contact.organizationName let companyText = company == "" ? K.Titles.noCompanyName : contact.organizationName contactNameFld_Outlet.text = CNContactFormatter.string(from: contact, style: .fullName)! companyFld_Outlet.text = companyText save_Array[0] = K.AppFacing.true_App setSaveBtn_AEQuote() } } extension AddEdit_Quote_VC: CNContactViewControllerDelegate { func contactViewController(_ viewController: CNContactViewController, shouldPerformDefaultActionFor property: CNContactProperty) -> Bool { return false } func contactViewController(_ viewController: CNContactViewController, didCompleteWith contact: CNContact?) { selectedContactID = contact?.identifier ?? "" if selectedContactID != "" { let company: String = contact?.organizationName ?? "" let companyText = company == "" ? K.Titles.noCompanyName : contact!.organizationName contactNameFld_Outlet.text = CNContactFormatter.string(from: contact!, style: .fullName) companyFld_Outlet.text = companyText getTheCurrentContactID() if selectedContactID != oldContactID { save_Array[0] = K.AppFacing.true_App setSaveBtn_AEQuote() } } dismiss(animated: true, completion: nil) } }
1
0
301
2w
Define the correct UIDocument subclass with the key UIDocumentClass
Hi there, I'm trying to migrate my app to using the UIDocumentViewController so I can use the new launch experience. My app exports a custom file type and uses UIDocument + UIDocumentBrowserViewController. I tried creating a UIDocumentViewController and making it the root view of my app but it doesn't recognise my custom document type. class Document_VC: UIDocumentViewController { var storyCardsDocument: PlotCardDocument? { self.document as? PlotCardDocument } override func viewDidLoad() { super.viewDidLoad() configureViewForCurrentDocument() } override func documentDidOpen() { configureViewForCurrentDocument() } func configureViewForCurrentDocument() { guard let document = storyCardsDocument, !document.documentState.contains(.closed) && isViewLoaded else { return } print("Document opened: \(document.fileURL)") } } The app opens but when I navigate to a document made in a previous version of the app it is greyed out. I also don't see a 'New' button in the launcher view. To try and see what I was doing wrong, I tested the markdown app sample code. When I make the UIDocumentViewController the root and try to open or create a new markdown document I get the following error: no document class found. Define the correct UIDocument subclass with the key UIDocumentClass in the info.plist's CFBundleDocumentTypes dictionary.
1
0
210
Sep ’24
iOS 18 HTML images are not loading in WKWebView
iOS 18 WKWebView images are not loading, no errors in older versions. The example while loading HTML is as follows. A problem occurs when you pull an image from a url. To get a URL image you need a cookie or something. I add them too, but it doesn't work on iOS 18. I get the error "An error occurred trying to load the resource." and a blue question mark on the screen. webView.configuration.websiteDataStore.httpCookieStore.setCookie(cookie) <html> <head> <style> body { font-family: -apple-system; margin: 0; padding: 0; text-align: center; } img { width: 100%; height: auto; } </style> </head> <body> <h1>Resim Görüntüleme</h1> <img src="https://xx.***.xx/example.png"> </body> </html> """
2
1
795
Sep ’24
A glitch with retained view controllers on Catalyst
Hello! I discovered a bug on Catalyst about a three years ago but it still seems to be not fixed. My bug report number is FB9705748. The Internet is silent on this so I'm even not sure, perhaps it's only me. So to the problem. When you display UICollectionViewController or UIViewController that contains UICollectionView, interact with the collection view then dismiss the view controller, the displayed view controller isn't released if dismissal is done through navigation bar item. The problem occurs only when the run target is My Mac (Mac Catalyst). Everything is fine when you run on iOS or via My Mac (Designed for iPad). The sample project is uploaded to GitHub. It has a video that shows this strange behavior, see the log for 'deinit' messages. I did have some workaround to fix this but it stops to work, presumable on the new macOS. Also, chances are that it's not only UICollectionView which initiates the glitch, it's just that I only encounter it with collection views.
1
0
196
Sep ’24