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

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
215
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
818
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
200
Sep ’24
UISwitch initialization failure in SPM test for visionOS 2 & Xcode 16
In SPM package test running on visionOS 2, when creating a UISwitch we get a crash / error: Nil UISwitch visual element provided by <UISwitch: 0x102b15590; frame = (0 0; 0 0); layer = <CALayer: 0x6000004c1780>> (NSInternalInconsistencyException) This issue only occurs on visionOS 2 in Xcode 16 with Swift Package Manager. It works fine when running on visionOS 1.2 in Xcode 16 with SPM, as well as on iOS 18 in Xcode 16 with SPM. Additionally, running the test on visionOS inside of a non-SPM package (Project test) is also fine. What results you expected - The test should pass for UISwitch initialization on SPM for visionOS 2 on Xcode 16. What results you actually saw - Test failure with error - Nil UISwitch visual element provided by <UISwitch: 0x102b15590; frame = (0 0; 0 0); layer = <CALayer: 0x6000004c1780>> (NSInternalInconsistencyException) The version of Xcode you are using - Xcode 16 Feedback id - FB15254532
0
0
206
Sep ’24
iOS 18 SwiftUI sheet resizing from page to form presentation sizing
I'm presenting a UIKit view controller from SwiftUI in a sheet using UIViewControllerRepresentable. The size of the sheet is being set to PagePresentationSizing using the new iOS 18 presentationSizing method. When Split View is used and the size class changes from regular to compact, the sheet resizes as expected to fit in the smaller window. When the app returns to full screen and the size class changes back to regular, the sheet is now displayed using FormPresentationSizing instead of PagePresentationSizing. This all worked as expected in iOS 17 with the view controller modalPresentationStyle being specified in the UIViewControllerRepresentable implementation, but the behaviour has now changed with iOS 18. How do I preserve the desired presentation sizing of the sheet? Thanks for any help.
2
0
863
Sep ’24
How to transition & resize a view from one view controller to another using UIKit & Snapshots?
I am trying to seamlessly transition a view from one view controller and have it "jump" into a sheet. Apple does this in their widget picker for example when you add one of the top widgets. Based on all the documentation I've read, the most common approach to this is to snapshot the area/view that you are trying to seamlessly transition in the presented view controller (the place where the item is coming from. And then have that snapshot translate across into where it should be in the layout of the presenting view controller. func makeAnimatorIfNeeded( using transitionContext: UIViewControllerContextTransitioning ) -> UIViewPropertyAnimator { if let animator = animator { return animator } // Presentation animation let animator = UIViewPropertyAnimator( duration: 0.5, timingParameters: UISpringTimingParameters(dampingRatio: 1.0) ) guard let fromVC = transitionContext.viewController(forKey: .from), let toVC = transitionContext.viewController(forKey: .to) else { transitionContext.completeTransition(false) return animator } /// !IMPORTANT: For some weird reason, accessing the views of the view controller /// directly, like `fromVC.view` or `toVC.view` will break the sheet transition and gestures. /// Instead, use the `view(forKey:)` method of the `transitionContext` to get the views. let fromView = transitionContext.view(forKey: .from) let toView = transitionContext.view(forKey: .to) let containerView = transitionContext.containerView let fromFrame = transitionContext.viewController(forKey: .from).map { transitionContext.finalFrame(for: $0) } ?? containerView.bounds let toFrame = transitionContext.viewController(forKey: .to).map { transitionContext.finalFrame(for: $0) } ?? containerView.bounds // Calculate the frame of sourceView relative to fromVC.view to capture the correct snapshot area. let snapshotFrameInFromVC = sourceView?.convert(sourceView?.frame ?? .zero, to: fromVC.view) ?? containerView.frame // Calculate the frame of sourceView relative to containerView to position the snapshot correctly. let snapshotFrameInContainer = sourceView?.convert(sourceView?.frame ?? .zero, to: containerView) ?? containerView.frame let snapshot: UIView? if isPresenting { // Create a snapshot of fromVC.view from the defined area (snapshotFrameInFromVC). let originalColor = fromVC.view.backgroundColor fromVC.view.backgroundColor = .clear snapshot = fromVC.view.resizableSnapshotView(from: snapshotFrameInFromVC, afterScreenUpdates: true, withCapInsets: .zero) fromVC.view.backgroundColor = originalColor // Position the snapshot correctly within the snapshot container snapshot?.frame = snapshotFrameInContainer toView?.frame = toFrame toView?.transform = CGAffineTransform(translationX: 0, y: containerView.frame.size.height) toView?.layoutIfNeeded() if let fromView { containerView.addSubview(fromView) } if let toView { containerView.addSubview(toView) containerView.addSubview(snapshot ?? UIView()) } let toViewCenter = CGPoint( x: toVC.view.bounds.midX, y: toVC.view.bounds.midY + 55 ) let gestureVelocity = CGPoint(x: 0, y: -5000) animator.addAnimations { Wave.animate( withSpring: self.animatedSpring, mode: .animated, gestureVelocity: gestureVelocity ) { snapshot?.animator.frame.size = CGSize(width: 204, height: 204) // Important to animate first snapshot?.animator.center = toViewCenter } completion: { finished, retargeted in print("finished: \(finished), retargeted: \(retargeted)") } toView?.transform = CGAffineTransform.identity } animator.addCompletion { animatingPosition in switch animatingPosition { case .end: snapshot?.removeFromSuperview() transitionContext.completeTransition(true) default: transitionContext.completeTransition(false) } } } else { // Transitioning view is fromView if let toView { containerView.addSubview(toView) } if let fromView { containerView.addSubview(fromView) } animator.addAnimations { fromView?.transform = CGAffineTransform(translationX: 0, y: containerView.frame.size.height) } animator.addCompletion { animatingPosition in switch animatingPosition { case .end: transitionContext.completeTransition(true) default: transitionContext.completeTransition(false) } } } self.animator = animator return animator } I can pull this off seamlessly if the animation involves a simple movement from A to B. But if I try to resize the snapshot as well, the snapshot becomes pixelated and low quality (I assume this is because the snapshot is literally a small screenshot and I'm stretching it from 56x56 to 204x204). Is there another way that I'm overlooking to pull this off without a snapshot? Or is there a way I can resize the snapshot without losing quality? Here is the animator code, it works great without the sizing so this should help future people looking to replicate the same effect anyways.
0
0
171
Sep ’24
Tapping a TextKit 2 backed UITextView moves the caret to a random location
With the upcoming launch of Apple Intelligence and Writing Tools, we've been forced to migrate our text editing app to TextKit 2. As soon as we released the update, we immediately got complaints about incorrect selection behaviour, where the user would tap a word to begin editing, but the caret would be shown in an undefined location, often dozens of paragraphs below the selected content. To reproduce: Create a UITextView backed by a standard TextKit 2 stack and a large amount of text (50,000+ words) - see sample project below Scroll quickly through the text view (at least 20% of the way down) Tap once to select a position in the document. Expected: The caret appears at the location the user tapped, and UITextView.selectedRange is the range of the text at the location of the tap. This is the behaviour of TextKit 1 based UITextViews. Actual: The caret is positioned at an undefined location (often completely off screen), and the selectedRange is different to the range at the location of the tap, often by several thousand. There is no pattern to the magnitude of the discrepancy. This incorrect behaviour occurs consistently in the sample project on the simulator, but you may need to hide the keyboard by pulling down, then repeat steps 2-3 a few times. This happens on iPhone and iPad, and on iOS 17, 18, and 18.1. Do you have any insight into why this might be happening or how to work around this issue? Sample code is here: https://github.com/nathantesler/textkit2-issue/tree/master
2
0
325
Sep ’24
External Display with SwiftUI in 2024
What is current best-practice for supporting an external display in a SwiftUI iOS app in 2024? (I'm only interested in iOS 17 and/or iOS 18) The only docs I found require abandoning the SwiftUI App structure and "switching back to a full UIKit App Delegate". Is this still the only option? Are there any complete examples on how to accomplish this? Also is testing external displays with Simulator at all reliable? All experiences I read about say that it never works. Thanks in advance.
0
0
163
Sep ’24
UIKit in SwiftUI memory leak while displaying images
I'm using UIKit to display a long list of large images inside a SwiftUI ScrollView and LazyHStack using UIViewControllerRepresentable. When an image is loaded, I'm using SDWebImage to load the image from the disk. As the user navigates through the list and continues to load more images, more memory is used and is never cleared, even as the images are unloaded by the LazyHStack. Eventually, the app reaches the memory limit and crashes. This issue persists if I load the image with UIImage(contentsOfFile: ...) instead of SDWebImage. How can I free the memory used by UIImage when the view is removed? ScrollView(.horizontal, showsIndicators: false) { LazyHStack(spacing: 16) { ForEach(allItems) { item in TestImageDisplayRepresentable(item: item) .frame(width: geometry.size.width, height: geometry.size.height) .id(item.id) } } .scrollTargetLayout() } import UIKit import SwiftUI import SDWebImage class TestImageDisplay: UIViewController { var item: TestItem init(item: TestItem) { self.item = item super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 200, height: 200)) imageView.center = view.center view.addSubview(imageView) imageView.sd_setImage(with: item.imageURL, placeholder: nil) } } struct TestImageDisplayRepresentable: UIViewControllerRepresentable { var item: TestItem func makeUIViewController(context: Context) -> TestImageDisplay { return TestImageDisplay(item: item) } func updateUIViewController(_ uiViewController: TestImageDisplay, context: Context) { uiViewController.item = item } }
0
0
299
Sep ’24
Could not build Module 'UIKit'
Im currentrly having this issue when compiling iOS for my react native app. The error is "Could not build Module 'UIKit'" which brings more subsequent errors down the line like "Could not build module 'DarwinFoundation'" and "Could not build module 'Foundation'. Might it be an error of dependencies or something like that. Im currently on MacOS sequoia, running XCode 16 and trying to build on iOS 18 with react native 0.75.3. For context, i inherited the project with React native 0.69.7 and had to upgrade. Please help, i've been stuck for days and i do not know what to do. Everything in the internet talks about XCode 16 beta but not the actual public release.
1
0
645
Sep ’24
Wait for some completion in main thread using Catalyst environment
I need to bring an iOS application to macOS using Catalyst. This application contain parts where it waits for a button to be pressed in the main thread, using [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; in a while loop to allow some dispatching while waiting. I know that this is not good style, but I need to convert this old source code and mentioned that when using this part of code under Catalyst, the main thread will not dispatch. So the button cannot be clicked, and a beach ball appears after two seconds. I saw a similar construct for native macOS applications: NSEvent *event= [[NSApplication sharedApplication] nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate dateWithTimeIntervalSinceNow:0.1] inMode:NSDefaultRunLoopMode dequeue:YES]; if (event) { [[NSApplication sharedApplication] sendEvent:event]; } but I do not have access to NSEvent and NSApplication in a Catalyst environment. Question: I there any code snippet which I can use to achieve the above? I do not want to completely rewrite old code if there is a solution for this. Any ideas or hints are highly appreciated. Thank you! Markus
4
0
343
Oct ’24
iOS18 Must appear crash bug
1、 hook respondsToSelector: 接口,比如 hook 后的接口名字为 yy_respondsToSelector: 2、在 yy_respondsToSelector 中使用传入的参数 aSelector。示例代码如下: (BOOL) yy_respondsToSelector:(SEL)aSelector { if ([self yy_respondsToSelector:aSelector]) { return YES; } if ([self.selectorNameArray containsObject:NSStringFromSelector(aSelector)]) { return YES; } return NO; } 2、在自定义 UIViewController,比如 YYViewController,实现下述代码 (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; NSMutableArray *vcs = [[NSMutableArray alloc]init]; [vcs addObject:[[UIViewController alloc] init] ]; [vcs addObject:[[UIViewController alloc] init] ]; self.navigationController.viewControllers = vcs; } 3、当页面 YYViewController加载并执行 viewDidAppear 时候, App 一定会出现崩溃,因为 aSelector 是一个非法指针,访问就会崩溃
1
0
229
Sep ’24
Background Decoration View Overlapping Collection View Cells
I am encountering an issue with my UICollectionView layout where the background decoration view is overlapping the collection view cells. Below is the relevant code for my layout configuration: let itemSize = NSCollectionLayoutSize( widthDimension: .absolute(60), heightDimension: .absolute(100) ) let item = NSCollectionLayoutItem(layoutSize: itemSize) let groupSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1), heightDimension: .absolute(100) ) let group = NSCollectionLayoutGroup.horizontal( layoutSize: groupSize, subitems: [item] ) let section = NSCollectionLayoutSection(group: group) section.decorationItems = [ NSCollectionLayoutDecorationItem.background(elementKind: "customBackgroundElementKind") ] return section Problem: The background decoration view is appearing on top of the collection view cells, which results in the cells being obscured. This issue is specific to iOS 18 and does not occur on iOS 17 and below. Request: Can anyone provide guidance or suggest a solution to ensure the decoration view does not overlap the collection view cells specifically on iOS 18? Thank you!
4
2
460
Sep ’24
.matchedGeomtryEffect from View to Sheet.
I'm trying to accomplish something like this: https://x.com/mlaithv/status/1835041850236838265 But it seems like Apple uses a Private API to pull it off. Has anyone managed to create something similar? I know there is a package named Transmission that can do it but it seems hacky & I'm unfamiliar with UIKit. The source uses a "custom modal" but I'm not sure how.
0
0
214
Sep ’24
How to make iPad app move to display show full-screen and center align
I wrote an app that can show live streaming. When using iPad, I can connect an external display and move app to display, that I can do what I want on my iPad and watch live streaming on external display using cable. But app moving to display is not always full screen, and on some displays it shows larger than the external display range that I should go to Settings -> Display & Brightness -> External Display -> Switching "Allow Display Mode Changes" to fix this issue. Are there APIs to make the App "move to display" programmatically, keep app full-screen, matching the external display's resolution on the External display?
2
0
345
Sep ’24
Xcode16RC present PHPickerViewController layout error & cell non-Interactive.
After upgrading to Xcode16RC, in an old project based on ObjC, I directly used the following controller code in AppDelegate: - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. UIButton *b = [[UIButton alloc]initWithFrame:CGRectMake(100, 100, 44, 44)]; [b setTitle:@"title" forState:UIControlStateNormal]; [self.view addSubview:b]; [b addTarget:self action:@selector(onB:) forControlEvents:UIControlEventTouchUpInside]; } - (IBAction)onB:(id)sender{ PHPickerConfiguration *config = [[PHPickerConfiguration alloc]initWithPhotoLibrary:PHPhotoLibrary.sharedPhotoLibrary]; config.preferredAssetRepresentationMode = PHPickerConfigurationAssetRepresentationModeCurrent; config.selectionLimit = 1; config.filter = nil; PHPickerViewController *picker = [[PHPickerViewController alloc]initWithConfiguration:config]; picker.modalPresentationStyle = UIModalPresentationFullScreen; picker.delegate = self; [self presentViewController:picker animated:true completion:nil]; } - (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results{ } Environment: Simulator iPhone 15 Pro (iOS18) Before this version (iOS17.4), clicking the button to pop up the system photo picker interface was normal (the top boundary was within the SafeAreaGuide area), but now the top boundary of the interface aligns directly to the top of the window, and clicking the photo cell is unresponsive. If I create a new Target, using the same codes, the photo picker page does not have the above problem. Therefore, I suspect it may be due to the old project’s .proj file’s info.plist, buildSetting, or buildPhase lacking some default configuration key value required by the new version, (My project was built years ago may be from iOS13 or earlier ) but I cannot confirm the final cause. iOS18.0 has the additional messages: objc[79039]: Class UIAccessibilityLoaderWebShared is implemented in both /Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/System/Library/AccessibilityBundles/WebCore.axbundle/WebCore (0x198028328) and /Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/System/Library/AccessibilityBundles/WebKit.axbundle/WebKit (0x1980fc398). One of the two will be used. Which one is undefined. AX Safe category class 'SLHighlightDisambiguationPillViewAccessibility' was not found! Has anyone encountered the same issue as me?
2
2
629
Sep ’24
CollectionView (Inside a SwiftUI TABView as a Page) Doesn't scroll to top when Pressed near the notch area of the device.
I have created a paging app With SwiftUI TabView with TabViewStyle: PageTabViewStyle. In every page there is an UICollectionView holding a list of rows. Now I have used UIViewControllerRepresentable to show the view inside TabView. It works okay, but the iOS default phenomenon that when a user pressed out side the safeArea on top(near the notch), the collectionview auto scrolls to top, doesn't work. Is it a fault of TabView or I am missing Something?
0
0
228
Sep ’24
iPadOS 18 - Move Tab Bar to bottom
As iPadOS 18 shows Tab Bar on top (tvOS'esq), can someone please tell me what changes do I need to make to get tab bar shown as a regular one (Pre iPadOS 18 style)? Tab bar being at the bottom is easily accessible. And, it being on top needs too much of hands movement. That being on top is is occupying, in a way, more screen real estate. Any ideas appreciated. Thank you.
5
3
1.6k
Sep ’24