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

UIKit Documentation

Post

Replies

Boosts

Views

Activity

UIAccessibility.Notification concurrency errors with Xcode 16 beta 2
I am running into some Swift 6 concurrency errors that I think are due to an odd oversight in the UIAccessibility Swift interface. There are a number of constants defined in here for various things, most of which are marked "let" (appropriately). However, the constants for notifications in extension UIAccessibility.Notification are all marked as var for some reason. For example: public static var pageScrolled: UIAccessibility.Notification Because it is var, not let, anytime I try to access it, I get a concurrency violation. I am baffled as to how I am supposed to work around this. For example, this line of code: UIAccessibility.post(notification: .pageScrolled, argument: "test") gives the error: "Reference to static property 'pageScrolled' is not concurrency-safe because it involves shared mutable state" I can't for the life of me figure out how to work around this. I guess maybe define my own constant somewhere and suss out the rawValue somehow for now? This really needs to be fixed in the SDK.
4
0
61
8h
Correct Collection View "stretchy header" implementation?
Hello, I have the following subclass of UICompositionalCollectionViewLayout to get the stretchy header effect as shown below. It works quite well, but I don't really have an experience with creating custom layouts so I thought I'd ask if maybe my implementation doesn't have some important flaws. I once ran into persistent layout loop crash with this and I am not sure what exactly I changed but it stopped happening. However since I am using this layout on important screen, I would like to make sure there isn't obvious potential for the layout loop crash happening in App Store version. I am particularly unsure about the shouldInvalidateLayout implementation. Originally I was returning true all the time, but decided to change it and only force invalidation for negative content offset which is when my header is supposed to stretch. Here is the full code: final class StretchyCompositionalLayout: UICollectionViewCompositionalLayout { override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { var attrs = super.layoutAttributesForElements(in: rect) ?? [] guard let collectionView = collectionView else { return attrs } let contentOffset = collectionView.contentOffset.y guard contentOffset < 0 else { return attrs } var newAttributes: UICollectionViewLayoutAttributes? attrs.forEach({ attribute in if attribute.indexPath.section == 0 && attribute.indexPath.item == 0 { let startFrame = attribute.frame newAttributes = attribute.copy() as? UICollectionViewLayoutAttributes let newFrame: CGRect = .init(x: 0, y: contentOffset, width: startFrame.width, height: startFrame.height - contentOffset) newAttributes?.frame = newFrame } }) if let new = newAttributes { attrs.removeAll { attr in return attr.indexPath.section == 0 && attr.indexPath.item == 0 } attrs.insert(new, at: 0) } return attrs } override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { guard let attributes = super.layoutAttributesForItem(at: indexPath) else { return nil } let contentOffset = collectionView?.contentOffset.y ?? 1 guard contentOffset < 0 else { return attributes } if indexPath.section == 0 && indexPath.item == 0 { let attributes = attributes.copy() as? UICollectionViewLayoutAttributes ?? attributes let startFrame = attributes.frame let newFrame: CGRect = .init(x: 0, y: contentOffset, width: startFrame.width, height: startFrame.height - contentOffset) attributes.frame = newFrame return attributes } else { return super.layoutAttributesForItem(at: indexPath) } } override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { let contentOffset = collectionView?.contentOffset.y ?? 1 // There is visual glitch when 0 is used in this condition if contentOffset < 1 { return true } else { return super.shouldInvalidateLayout(forBoundsChange: newBounds) } } } Any feedback welcome!
0
0
66
1d
How to implement UITextItem in custom text view with UITextInput and TextKit2
Hi Apple, I'm implementing a custom text view by conforming to UITextInput and backing it with TextKit2. However, I like the UITextItem feature of the default UITextView. Can I get some guidance on how to reimplement it? Are we looking at overlaying UIMenu buttons? Or some API where I can display a UIMenu at a rect I specify? Hopefully, it is not some kind of private API? Thanks for the help in advance.
0
0
46
1d
How on earth do I get the actual dimensions of a presented modal view on iPad?
This is the stupidest thing that should be so easy. I simply present a view controller using: [self presentViewController:settingsView animated:YES completion:^(){ }]; Then in the code for the view controller being presented, I want to know it's width, which should be stupidly simple using: const int viewWidth = self.view.frame.size.width; HOWEVER, this gives me a value that is the same as the parent view's width, yet on iPad at least this view is visibly smaller than the parent/presenting view (as it is hovering over it with the view visible around the edges behind it). I have tried every stupid thing I can find within the parent view and view controller code that mentions margins and insets and whatnot, but nothing seems to give me the actual stupid value of the stupid presented view's visible dimensions! Any ideas? The iPad is on iPadOS 15.3.1, might try installing a newer version and see if this is some bug in this particular version of the OS.
4
0
100
2d
Should iPadOS 18's UITabBarController work with more than 7 tabs?
Is it expected that UITabBarController in iPadOS 18 beta 2 should be working with more than 7 tabs yet, or is this still a work-in-progress on Apple's end? Currently, if I create a UITabBarController and configure it with more than 7 root tabs (i.e. enough to trigger the "more" tab in previous iPadOS versions) using the new UITab API, any tab after the seventh one is effectively not selectable: If the view is at a horizontally regular width: When you select via the new floating tab bar or the sidebar, the tab / sidebar item itself does become selected, but the actually displayed view controller remains unchanged. If you switch the window to a horizontally compact width, it switches to the old-style of tab bar, and the "More" tab with its moreNavigationController functionality becomes visible, and from there you select and actually present one of the 'excess' tabs. (Note: there appear to be some push/pop animation glitches when transitioning between the moreNavigationController and the tab's view controller) Then if you're in one of those 'more' tabs and then switch the window back to horizontally regular width: The currently displayed view controller (e.g. "view controller 9") is still shown, and the "More" back button along with it The new tab bar controls will act like some other tab is selected: specifically, whichever tab was selected when the window was last in the horizontally regular width mode If you tap on the "More" back button, you get the moreNavigationController and from that you can select any of the other overflow tabs (all the while with the old old tab showing as selected in the tab bar) If the moreNavigationController's tab list is visible, and you select one of the overflow tabs from the new tab bar or side bar, the correct view controller will be pushed onto the moreNavigationController's stack and show as selected in the new tab bar / side bar. (Hooray!) But this only appears to work specifically when the moreNavigationController's tab list is visible and there's nothing else on that navigation stack. Fundamentally, it feels like the work to sync the new tab management state with the moreNavigationController state isn't finished yet? But I've looked at the beta release notes and not seen any mention of these limitations. My questions, before I file any feedbacks: Are these known issues that are still being worked on? Is it Apple's intent that >7 root tabs should work by the time of iPadOS 18's release?
1
0
99
3d
Displaying HDR image, isn't showing dynamic range
I'm playing around with HDR images in iOS. I'm able to load an HDR image, but it isn't displaying with the expected "pop" I see of the same image in the Photos app. I exported the photo from Photos (on the Mac) using Export Unmodified. I reimported to confirm Photos shows the "pop." I'm trying both UIImage and CIImage, with the same results. The below is tested on my iPhone 14 Pro (not Simulator). The Storyboard for the code below has three UIImageViews (top, middle, and bottom). let fileURL = Bundle.main.url(forResource: "IMG_6972", withExtension:"HEIC")! var config = UIImageReader.Configuration() config.prefersHighDynamicRange = true let imageReader = UIImageReader(configuration: config) let topImage = imageReader.image(contentsOf: fileURL)! topImageView.preferredImageDynamicRange = .high topImageView.image = topImage // The image appears, looks SDR print("topImage.isHighDynamicRange: \(topImage.isHighDynamicRange)") // true let ciimage = CIImage(contentsOf: fileURL)! bottomImageView.image = UIImage(ciImage: ciimage) // The image appears, looks SDR - identical to topImage print("color space: \(ciimage.colorSpace!)") // (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; Display P3) let gainMap = CIImage(contentsOf: fileURL, options: [.auxiliaryHDRGainMap: true])! middleImageView.image = UIImage(ciImage: gainMap) // The gain map image appears as expected Additionally, for comparison, I tried: let sdrImage = UIImage(named: "IMG_6972.HEIC")! // UIImage.named doesn't support HDR print("sdrImage.isHighDynamicRange: \(sdrImage.isHighDynamicRange)")``` // false, as expected bottomImageView.image = sdrImage and the image matches the other two, further confirming the HDR version of the image isn't displaying in either UIImageReader or CIImage versions above. I also track the UIScreen's use of EDR with: print("currentEDR: \(UIScreen.main.currentEDRHeadroom)") print("maxEDR: \(UIScreen.main.potentialEDRHeadroom)") maxEDR is 8.0. currentEDR is 1.0 at launch, 1.3 after a 1.0 second delay. Which makes me think it might be showing a little HDR, but not enough to be noticeable. Is there something special I need to do to set the UIViewController, UIScreen, or UIApplication (etc) to be an an "HDR Mode" or similar?
1
0
84
3d
UI Tab Bar
Anyone else get these warnings when using UI Tab Bar in visionOS? Are these detrimental to pushing my visionOS app to the App Review Team? import SwiftUI import UIKit struct HomeScreenWrapper: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> UITabBarController { let tabBarController = UITabBarController() // Home View Controller let homeVC = UIHostingController(rootView: HomeScreen()) homeVC.tabBarItem = UITabBarItem(title: "Home", image: UIImage(systemName: "house"), tag: 0) // Brands View Controller let brandsVC = UIHostingController(rootView: BrandSelection()) brandsVC.tabBarItem = UITabBarItem(title: "Brands", image: UIImage(systemName: "bag"), tag: 1) tabBarController.viewControllers = [homeVC, brandsVC] return tabBarController } func updateUIViewController(_ uiViewController: UITabBarController, context: Context) { // Update the UI if needed } } struct HomeScreenWrapper_Previews: PreviewProvider { static var previews: some View { HomeScreenWrapper() } }
1
0
103
4d
UIKit MacCatalyst - How to drag a table view item to Finder to create a folder of items
I have a UITableView that displays a Group/Note hierarchy analogous to a Finder Folder/Files hierarchy. I have implemented Drag and Drop such that if I drag a Note to the Finder Desktop an HTML file is created of the Note, and if I drag a Group to the Finder Desktop a Text file is created of the Group's title. Here is the Helper Dragging extension that I've implemented: // // Model+Dragging.swift // /* Abstract: Helper methods for providing and consuming drag-and-drop data. */ import UIKit import MobileCoreServices // Conditionalize Drag and Drop so it is not in iOS target. #if targetEnvironment(macCatalyst) extension Model { /** A helper function that serves as an interface to the data model, called by the implementation of the `tableView(_ canHandle:)` method. */ func canHandle(_ session: UIDropSession) -> Bool { // In order to enable dragging all text type files changed the class // loadable objects from NSString to my custom TEXTClass. return session.canLoadObjects(ofClass: TEXTClass.self) } /** A helper function that serves as an interface to the data model, called by the `tableView(_:itemsForBeginning:at:)` method. */ func dragItems(for indexPath: IndexPath) -> [UIDragItem] { let itemProvider = NSItemProvider() let item = self.getDisplayItem(for: indexPath.row) if item is Note { let note:Note = item as! Note let html = note.noteHTML let data = html?.data(using: .utf8) // Drag to finder creates an html file. itemProvider.suggestedName = note.title + ".html" itemProvider.registerDataRepresentation(forTypeIdentifier: kUTTypeData as String, visibility: .all) { completion in completion(data, nil) return nil } } else { let group:Group = item as! Group let title = group.title let data = title?.data(using: .utf8) // Drag to finder creates a text file. itemProvider.suggestedName = group.title + ".text" itemProvider.registerDataRepresentation(forTypeIdentifier: kUTTypeData as String, visibility: .all) { completion in completion(data, nil) return nil } } return [ UIDragItem(itemProvider: itemProvider) ] } } #endif I would now like to change the result of dragging a Group to the Finder. Instead of creating a Text file from the drag data, I would like to create a Folder containing the Group's Notes. Note: I am unconcerned with the task of assembling the Group/Notes hierarchies as Folder/Files hierarchies because I already have implemented such previously as a menu export command. My concern is where and how I can communicate it to the Finder in the Drag and Drop process. As a first step I thought I would simply create an empty folder from the drag of a Group. So far, none of my experiments have been successful. Every variation of itemProvider.registerDataRepresentation(forTypeIdentifier: or itemProvider.registerFileRepresentation(forTypeIdentifier: or registerItem(forTypeIdentifier:loadHandler: that I have tried has failed to produce anything but empty TEXT files, if they worked at all. It is my understanding that itemProviders may provide directories instead of files, but I have been unable to find any examples of such. My problem may be a lack of understanding of the syntax and usage of the NSItemProvider.LoadHandler completion block. Any Swift examples on point would be greatly appreciated!
0
0
61
4d
Text selection doesn't work in WKWebView on macOS Sonoma
Can not select anything within WkWebView editor view of my MacCatalyst app when running on macOS 14 Sonoma. Any selection gesture or command key fails to select anything in content editable WKWebView, so none of the Editor tools can be activated. My application uses the nnhubbard / ZSSRichTextEditor WKWebView-based Rich Text Editor: https://github.com/nnhubbard/ZSSRichTextEditor. The app is built with Xcode 15.4. The app is a Catalyst app that implements an editor view with a ZSSRichTextEditor WKWebView. The problem does not occur if the the app is run in macOS 11, 12, or 13 (Catalina, Monterey, or Ventura.) The issue only occurs in macOS 14 Sonoma. The following error message is logged whenever an attempt to select any text in the WKWebView content: 0x1359ecc18 - [pageProxyID=14, webPageID=15, PID=14,932] WebPageProxy::didFailProvisionalLoadForFrame: frameID=1, isMainFrame=1, domain=NSURLErrorDomain, code=18,446,744,073,709,550,614, isMainFrame=1, willInternallyHandleFailure=0 Without the ability to select text the editor (WKWebView) is useless since no editing tool can be invoked without a selection. An Apple Feedback report was filed: FB13344011. An incident was filed with DTS concerning this issue. Apple Developer Technical Support's reply was "Our engineers have reviewed your request and have determined that you are experiencing a known issue for which there is no known workaround at this time." Since DTS’ reply there has been no further response from them.
2
0
87
4d
iOS 18. UINavigationController stack changes with delay
If I do something like this: var viewControllers = navigationController.viewControllers if let lastViewController = viewControllers.popLast() { navigationController.viewControllers = viewControllers navigationController.pushViewController(lastViewController, animated: false) } } I got crash: pushing the same view controller instance more than once If I set delay: var viewControllers = navigationController.viewControllers if let lastViewController = viewControllers.popLast() { navigationController.viewControllers = viewControllers DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { navigationController.pushViewController(lastViewController, animated: false) } } it will work but with unnecessary transitions. Should it work like this in iOS 18 ?
0
0
59
4d
The HEIC images in the Assets folder are displaying abnormally
I placed a PNG format image in the Assets folder and also added a HEIC format image that was converted from PNG. When the slicing is set to None, both images appear the same in the UIImageView. However, when I select "Horizontal and Vertical" for the Slices of both images, they no longer appear consistent, and the HEIC image displays abnormally. @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [self addImageViews]; } - (void)addImageViews { UIImageView *heicImageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, [self imageViewSize].width,[self imageViewSize].height)]; UIImageView *pngImageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 300, [self imageViewSize].width,[self imageViewSize].height)]; heicImageView.image = [UIImage imageNamed:@"heic"]; pngImageView.image = [UIImage imageNamed:@"png"]; [self.view addSubview:heicImageView]; [self.view addSubview:pngImageView]; } - (CGSize)imageViewSize { return CGSizeMake(146, 44); } @end
1
0
69
4d
iOS 18 beta1/2 CoreText Crash
0 libobjc.A.dylib 0x000000018e27f008 objc_msgSend + 8 (:-1) 1 CoreFoundation 0x0000000190eaa4bc -[__NSDictionaryM objectForKey:] + 168 (NSDictionaryM.m:179) 2 CoreFoundation 0x0000000190f003e8 -[NSDictionary containsKey:] + 56 (NSDictionary.m:80) 3 CoreFoundation 0x0000000190f0006c CFDictionaryContainsKey + 52 (CFDictionary.c:265) 4 libGSFont.dylib 0x00000001af98cc14 GSFontIsOverriddenSystemFontName + 32 (GSFont.m:2860) 5 CoreText 0x0000000192d6f1fc CopyAttributeForSystemFont(__CFString const*, __CFString const*) + 64 (MetadataSupport.cpp:194) 6 CoreText 0x0000000192d6edd4 AddVariationInfo(TCFMutableDictionary&, __CFString const*) + 60 (SplicedFontSupport.cpp:6760) 7 CoreText 0x0000000192de1ea0 MakeSpliceDescriptor(__CFString const*, unsigned long, __CFString const*, __CFString const*, __CFNumber const*, __CFNumber const*, unsigned int, CTFontTextStylePlatform, unsigned int, __CFNumber co... + 4504 (SplicedFontSupport.cpp:7429) 8 CoreText 0x0000000192ddd374 TDescriptorSource::CopySpliceFontForName(__CFString const*, __CFString const*, __CFNumber const*, __CFNumber const*, CTFontLegibilityWeight, __CFBoolean const*, __CFNumber const*, __CFString const*... + 1376 (TDescriptorSource.cpp:4288) 9 CoreText 0x0000000192dda800 TDescriptorSource::CopySplicedDescriptorForName(__CFString const*, __CFString const*, __CFString const*, __CFNumber const*, __CFNumber const*, CTFontLegibilityWeight, __CFBoolean const*, __CFNumber... + 172 (TDescriptorSource.cpp:4322) 10 CoreText 0x0000000192d0a214 TDescriptor::CreateMatchingDescriptorInternal(__CFSet const*, unsigned long) const + 2332 (TDescriptor.cpp:804) 11 CoreText 0x0000000192d09148 TDescriptor::InitBaseFont(unsigned long, double) + 76 (TDescriptor.cpp:952) https://feedbackassistant.apple.com/feedback/14091158
1
1
119
4d
Fatal Exception: NSInvalidArgumentException Application tried to present modally a view controller <UIAlertController: 0x10786d000> that is already being presented by
We never received customer report this crash, and we could not see during development phase However we can see this crash quite often on crash analytics. I have gone through UIAlertController in code level, it always creates new one instead reusing it. Please help me identify why this occurs? Much appreciated crash_session_2ecf1bdde30e402f9df795ea7681272b_DNE_0_v2_stacktrace.txt
0
0
110
5d
Cordova based app not working after updating iOS to 17.5.1
After updating iOS, my Cordova app behaves incorrectly after receiving a voip push. When a push notification is received, my application launches CallKit, displays the Native Dialer screen and starts other necessary services. Until 17.5.1 (possibly 17.5) everything worked correctly. All services and sockets were established/ connected and working. After updating iOS to 17.5, the application crashes, and while voice connection is established the app is no longer active. Xcode logs have these error messages: Invalidating grant <invalid NS/CF object> failed Type: Error | Timestamp: 2024-06-20 13:27:44.719601+02:00 | Process: MyApp | Library: WebKit | Subsystem: com.apple.WebKit | Category: ProcessCapabilities | TID: 0x3a4929 Invalidating grant <invalid NS/CF object> failed Type: Error | Timestamp: 2024-06-20 13:27:44.732219+02:00 | Process: MyApp | Library: WebKit | Subsystem: com.apple.WebKit | Category: ProcessCapabilities | TID: 0x3a4929 Invalidating grant <invalid NS/CF object> failed Type: Error | Timestamp: 2024-06-20 13:27:44.733996+02:00 | Process: MyApp | Library: WebKit | Subsystem: com.apple.WebKit | Category: ProcessCapabilities | TID: 0x3a4929 I am using: Cordova iOS: 6.2 iOS 17.5.1 Can anyone please help?
1
0
220
5d
Workout session active but "Return to app" option not displayed in menu
I have an iOS app, with a watch counterpart, used to enter scores for a match. The watch app starts a match (and a workout session) when it receives a notification from the mobile app, after the user started a match on their phone. Basically the watch app is just a more convenient way of inputing scores, so the user wouldn't have to reach for and unlock their phone every time - therefore the need for the watch app to always be displayed. The flow follows these steps: the user is prompted for workout session access when first launching the app; after they accept, I start the workout; the delegate method workoutSession(didChangeTo) returns the expected values; the app remains active, even when the user lowers their wrist; when I go to the clock, the app's icon is displayed in a circle at the top (bringing the app back to foreground on tap). The only problem is that the "Return to app" option in the "Return to Clock" settings menu is missing, what do I need to do in order to display it? Here's an example of what it looks like for the Strava app: and how it looks for mine.
0
0
124
5d
Spring Animations with Constraints don't behave properly
Repo is here Visual Description is here: Basically the red view should never be inside the blue view. The red view has a fixed aspect ratio. The blue view initially has an aspect ratio different from the red view and is animated to have the same aspect ratio. The red view is constrained inside the blue view as follows: let ac = brokenView.widthAnchor.constraint(equalTo: brokenView.heightAnchor, multiplier: 9/16) let xc = brokenView.centerXAnchor.constraint(equalTo: animView.centerXAnchor) let yc = brokenView.centerYAnchor.constraint(equalTo: animView.centerYAnchor) let widthC = brokenView.widthAnchor.constraint(equalTo: animView.widthAnchor) widthC.priority = .defaultLow let gewc = brokenView.widthAnchor.constraint(greaterThanOrEqualTo: animView.widthAnchor) let geHC = brokenView.heightAnchor.constraint(greaterThanOrEqualTo: animView.heightAnchor) geHC.priority = .required So the red view should start at equal width, but prioritize always been taller and wider than the blue view while staying centered and keeping a fixed aspect ratio. As you can see in the visual description it is not priortizing being taller. Any suggestions on how to fix, work around, or otherwise get past this would be appreciated. Really trying to avoid manually doing a spring animation with keyframes and an assload of math. I have filed a bug on feedback assistant, but figured someone here might have experience//know how. Thanks
0
0
95
6d
Any way to have UIBlurEffectView ignor views below it?
Is there any way to have a UIBlurEffectView ignore views underneath it? More than just masking it. Mask of a view below it, it'll still process that view and you'll still see a "halo" around the edge. Ideally I'd like to have a view 'below' the blur, mask it, and also not have the view be processed in the blur.
1
0
87
6d