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

New Sliders
For the past couple of years, Apple has been using custom sliders in Music, Podcasts, and on the Lock Screen for scrubbing music and controlling volume. But those sliders are not available to 3rd party devs. We can recreate them theoretically for scrubbing audio. But not for volume, where in UIKit we are supposed to use MPVolumeView. Anyone from Apple? Are there any plans to make the slider styles used in Apple's audio apps available to the rest of us? FB12261162
0
0
200
Jun ’24
UIKit ContactsAccessButton?
Apple revealed the ContactsAccessButton in the WWDC24 session 10121: Meet the Contact Access Button. After watching the video, reading through the documentation as well as the sample code , I can only find a SwiftUI ContactsAccessButton. However, our code base is written largely in UIKit, and our team prefers to do complex work and customization with lists via UITableView as opposed to SwiftUI List. So we would greatly prefer to use a UIKit ContactAccessButton. Is there not a UIKit equivalent to ContactsAccessButton? If there is, where can we find it?
1
0
270
Jun ’24
iOS18Bate导航栏
代码如下 (void)viewDidLoad { [super viewDidLoad]; self.navigationController.navigationBar.translucent = NO; } (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.navigationController setNavigationBarHidden:true]; } 此时加载VC时顶部会出现空白,整个VC的frame的Y值向下偏移了状态栏的高度,再次切换到此VC则会恢复,这是iOS18Bate的bug吗
1
0
210
Jun ’24
self.edgesForExtendedLayout=UIRectEdgeNone ios18beta move UIView down
Using the UINavigationController, jump from page A(UIViewController A) to page B (UIViewController B), and page B(UIViewController B) clicks back. When page A(UIViewController A) is returned, the view of page A(UIViewController A) moves down as a whole, and the top turns black. Reproduce steps: step1: Set “self.edgesForExtendedLayout = UIRectEdgeNone;” in the method “viewDidLoad” UIViewController - (void)viewDidLoad { [super viewDidLoad]; // step1 self.edgesForExtendedLayout = UIRectEdgeNone; } step2:Set “ self.navigationController.navigationBarHidden = YES;” in the method “viewWillAppear” UIViewController - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // step2 self.navigationController.navigationBarHidden = YES; } step3:Set “self.navigationController.navigationBarHidden = NO;” in the method “viewWillDisappear” UIViewController - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; // step3 self.navigationController.navigationBarHidden = NO; } step4:Set “[self.navigationControllerpopViewControllerAnimated:NO];” in the method “viewWillDisappear” UIViewController When page is returned - (void)click { UIViewController *vc = [[UIViewController alloc] init]; vc.view.backgroundColor = [UIColor redColor]; [self.navigationController pushViewController:vc animated:YES]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // step4,animated NO [self.navigationController popViewControllerAnimated:NO]; }); } The test found that the UIView was normal after removing the "self.edgesForExtendedLayout=UIRectEdgeNone" setting.
0
0
152
Jun ’24
iOS 18 developer beta: Writing Tools
Based on the session content, it seems that setting the TextView property writingToolsBehavior = .complete should bring up the writing tools bottom panel view. However, it does not appear to be working. Is this a feature that will be added in a future update, or is there something additional I need to do? Test on: XCode 16.0 beta (16A5171c), iOS Simulator 18.0 Beta, iPhone 11 Pro iOS 18.0 Beta
4
6
420
Jun ’24
Add 30 frames per secons in assetWriter
Hello, I have converted UIImage to CVPixelBuffer. I am creating a video writing app. In some cases, the same CVPixelBuffer should last in the video for 2 seconds or more. However, I need to add 30 CVPixelBuffers per second because the video, to work on social media, must be 30 frames per second. The problem is that whenever I try to add frames to long videos, like 50-minute videos, it gives an error. The error is something like "Operation cannot be completed". Give me an example of a loop to add 30 CVPixelBuffers per second to a currently written video. Example: while true { if videoInput.isReadyForMoreMediaData { break } if videoInput.isReadyForMoreMediaData, let buffer = videoProvider.getNextFrame() { adaptor.append(buffer, withPresentationTime: CMTime(value: 1, timescale: 30)) } } I await your response.
0
0
264
Jun ’24
Xcode 16: SwiftUI plain Button & UIImageView not working
It looks like Xcode 16 has changed this behaviour so I'm not sure if this is a bug or not. When a SwiftUI Button wraps a UIImageView and the button style is .plain the button doesn't work without setting isUserInteractionEnabled. struct ContentView: View { var body: some View { Button { print("Hello World!") } label: { UITestImage() } .buttonStyle(.plain) } } struct UITestImage: UIViewRepresentable { func makeUIView(context: Context) -> UIImageView { let view = UIImageView() // view.isUserInteractionEnabled = true // Fix view.image = UIImage(systemName: "plus") view.contentMode = .scaleAspectFit view.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) view.setContentCompressionResistancePriority(.defaultLow, for: .vertical) view.layoutMargins = .zero return view } public func updateUIView(_ uiView: UIImageView, context: Context) {} } This feels unexpected, is this a bug?
1
1
207
Jun ’24
Custom Domain deeplink
My SampleApp, named "myApp," already supports deep links such as "https://myApp.com/tab/record/10020." When this link is clicked, it navigates to myApp, and AppDelegate handles the further process. Now, I need to support another link (domain), "https://appcloud.com/tab/record/10020," so that clicking this link also navigates to myApp. Is there any way to solve this kind of problem without adding "apple-app-site-association"?
1
0
256
Jun ’24
SwiftUI popover not respecting arrow direction
When I try to change the arrow direction for SwiftUI popover it's not working at all, but in UIKit it seems to be ok Please check the sample code Button { showPopover.toggle() } label: { Text("Show Popover") .padding(60) .border(Color.yellow) } .popover( isPresented: $showPopover, arrowEdge: .bottom // issue here ) { Text("Popover conent") }
2
0
198
Jun ’24
UIPasteControl Button Appearing Disabled but Still Pasting Content
Hi everyone, I've implemented a UIPasteControl in my iOS app using the following code: func displayPasteControl() { if #available(iOS 16.0, *) { let pasteControlConfig = UIPasteControl.Configuration() let newPasteControlButton = UIPasteControl(configuration: pasteControlConfig) self.inputContainerView.addSubview(newPasteControlButton) newPasteControlButton.isEnabled = true // Set constraints for this button newPasteControlButton.translatesAutoresizingMaskIntoConstraints = false newPasteControlButton.topAnchor.constraint(equalTo: self.originalPasteView.topAnchor, constant: 0).isActive = true newPasteControlButton.centerXAnchor.constraint(equalTo: self.inputContainerView.centerXAnchor).isActive = true newPasteControlButton.widthAnchor.constraint(equalTo: self.originalPasteView.widthAnchor, multiplier: 0.5).isActive = true newPasteControlButton.bottomAnchor.constraint(equalTo: self.originalPasteView.bottomAnchor, constant: 0).isActive = true newPasteControlButton.target = self.inputTextView } } I call this function in viewWillAppear: override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) displayPasteControl() } Sometimes, I've noticed that the UIPasteControl button appears in a disabled state visually, but when I press it, the content from the clipboard is still pasted. I checked the state of UIPasteControl and it indicates that it is in an enabled state. For context, the UIPasteControl target is set to a UITextView (self.inputTextView). Has anyone experienced this issue or have any idea why this might be happening? Any help would be appreciated! Thank you!
0
0
118
Jun ’24
Inner UIScrollView and outer UIPanGestureRecognizer
Hi, If there are nested UIScrollViews, they will work together nicely; when the inner scroll view reaches the end of contentSize, the outer scroll view will start scrolling. Can we do the same with inner UIScrollView and outer UIView that has UIPanGestureRecognizer? I’ve tried using UIGestureRecognizerDelegate and return true in gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) but that will scroll the inner UIScrollView and fire the outer UIPanGestureRecognizer at the same time. Thanks!
1
0
157
Jun ’24
UIDocumentViewController based app built for iOS 17.5 unexpectedly uses new document launch experience under iOS 18 developer beta
In the WWDC24 session Evolve your document launch experience, it is mentioned that apps linked against the iOS 17 SDK would not get the new document launch experience. However, I found that the new document browser is active in my iOS 17 app when installed from the App Store on iOS 18, without rebuilding it. This (along with other iOS 18 UIKit behavioral regressions) renders the app unusable when running under iOS 18. To be clear, my app uses a UIDocumentViewController as the root view controller of a UINavigationController and is implemented primarily in Obj-C. I don't want to show the new document browser to users at app launch time. The current behavior of my app is that it always launches to either the current document or a new document and then allows the user to open a new document using the document picker if desired (this was accomplished by invoking the action associated with the Documents button on iOS 17; see related feedback FB13418866: ER: UIDocumentViewController should provide API to allow customization of Documents button behavior). The new UIDocumentViewController behavior is problematic because it has replaced the Documents button with a backAction that moves the user into the new document browser with no way to back out, aside from picking a document or creating a new document. Previously, the user could choose Cancel to exit the document picker and get back to the currently-open document without choosing a new one. While the new UIDocumentViewController behavior looks nice for apps like Swift Playgrounds, it is problematic for apps that want to take advantage of the UIDocument infrastructure without forcing the user to deal with a more complicated browser-centric app UI. I would expect there to be some way to maintain the previous behavior as it existed on iOS 17, but I don't see any way to do this. Suggestions welcome. Thanks!
7
0
370
2w
UIDevice: Main actor-isolated class property 'current' can not be referenced from a non-isolated context
I have a Safari Web Extension for visionOS that reads from UIDevice.current.systemVersion in order to provide the OS version number back to the JavaScript context utilizing beginRequest(with:). When switching my project to use Swift 6, I received this obscure error: Main actor-isolated class property 'current' can not be referenced from a non-isolated context Class property declared here (UIKit.UIDevice) Add '@MainActor' to make instance method 'beginRequest(with:)' part of global actor 'MainActor' Adding @MainActor causes another issue (Main actor-isolated instance method 'beginRequest(with:)' cannot be used to satisfy nonisolated protocol requirement) which suggests adding @preconcurrency to NSExtensionRequestHandling which then breaks at Non-sendable type 'NSExtensionContext' in parameter of the protocol requirement satisfied by main actor-isolated instance method 'beginRequest(with:)' cannot cross actor boundary. What's the proper solution here? Here's a simplified snippet of my code: class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { func beginRequest(with context: NSExtensionContext) { // ... var systemVersionNumber = "" systemVersionNumber = UIDevice.current.systemVersion // ... } }
1
0
349
Jun ’24
iOS 18 beta REGRESSION: UIDocumentViewController is no longer in responder chain for title menu item actions?
In testing my app with the WWDC24 iOS 18 beta, I have noticed that most of the menu items in the navigation bar and title menu are either missing, disabled, or nonfunctional. The structure of my app's UI is a UIDocumentController subclass as the root view controller of a UINavigationController. In debugging the problem with title menu items, I noticed that the responder chain from the UICommand.sender now starts at the UINavigationBar and goes up from there, without passing through the UIDocumentViewController itself. Now, only the actions I've defined in the AppDelegate are accessible. I'm not exactly sure how this was organized on iOS 17, but the responder chain did include the UIDocumentViewController, where I have implemented most of the menu item actions. This seems like a UIKit bug, but I am investigating possible workarounds in case Apple does not fix it. Suggestions welcome.
5
1
341
3w
Mimic TV App back button in UIKit
Hi In my application I'm trying to recreate the behaviour of the back button in the Apple TV app on iOS. What I'm looking for is a way to have a material background but also making it possible to animate (with an interruptible animation) the transition when the user scrolls down in a scroll view. When searching around there seems to be 2 hacks which doesn't solve my problem. Either you add a static image for the back button, which doesn't solve any of the points I mentioned before. The other hack is to stop using the back button in the UINavigationBar and start leveraging the left button instead, which I don't want because you loose the swipe back gesture. Can you just pinpoint me what API I could use to get a similar look and feel?
0
0
185
Jun ’24
uialertviewcontroller presented reset's my tableview cells, font size / attributed text (iOS18)
when presenting an uialertviewcontroller either an actionsheet or alert it seems to have some weird interaction with my tableview cells. For example, i have custom font sizes a user can set so when im loading my cell i set the font size. It looks good on load but the second i preset a uialertviewcontroller it 'reset's all the cells to the default interface builder set fontsize. Some cells i use attributed text programmatically and that all gets reset as well to 'default' interface builder label settings. Its very odd. this is in iOS 18 b1. Funny enough it seems like every beta 1 (if i recall maybe in iOS 17 or iOS 16) it did the same thing there attributed text would like 'reset' its very odd. I have a hunch this is a bug and filed a feedback, but curious if there are any workarounds, or simply just wait until its fixed :D . Thanks all !
3
0
229
Jun ’24
SwiftUI Tap Gestures Not Responding in SwiftUI View After UIKit Interactive Transition Cancelled
I am using a custom UINavigationController with a custom pop animation and an interactive transition. The custom navigation controller works well for standard UIKit view controllers. However, when I push a UIHostingController that hosts a SwiftUI view, the SwiftUI view becomes unresponsive to tap gestures if the interactive transition is cancelled. The issue seems to occur specifically after the interactive transition is started and then cancelled. This is interactive transition code class CustomPopAnimator: NSObject, UIViewControllerAnimatedTransitioning { func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 0.3 } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { let containerView = transitionContext.containerView guard let fromView = transitionContext.view(forKey: .from), let toView = transitionContext.view(forKey: .to) else { return } containerView.insertSubview(toView, belowSubview: fromView) let screenWidth = UIScreen.main.bounds.width toView.transform = CGAffineTransform(translationX: -screenWidth / 3, y: 0) UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: { fromView.transform = CGAffineTransform(translationX: screenWidth, y: 0) toView.transform = .identity }) { finished in fromView.transform = .identity toView.transform = .identity fromView.isUserInteractionEnabled = true transitionContext.completeTransition(!transitionContext.transitionWasCancelled) } } } class CustomInteractiveTransition: UIPercentDrivenInteractiveTransition { var hasStarted = false var shouldFinish = false override func cancel() { super.cancel() reset() } override func finish() { super.finish() reset() } private func reset() { hasStarted = false shouldFinish = false } } @objc class CustomNavigationController: UINavigationController, UINavigationControllerDelegate { private let customAnimator = CustomPopAnimator() private let customInteractiveTransition = CustomInteractiveTransition() override func viewDidLoad() { super.viewDidLoad() delegate = self setupGesture() } private func setupGesture() { let edgeSwipeGesture = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(handleEdgeSwipe(_:))) edgeSwipeGesture.edges = .left view.addGestureRecognizer(edgeSwipeGesture) } @objc private func handleEdgeSwipe(_ gesture: UIScreenEdgePanGestureRecognizer) { let translation = gesture.translation(in: view) let progress = translation.x / view.bounds.width switch gesture.state { case .began: customInteractiveTransition.hasStarted = true popViewController(animated: true) case .changed: customInteractiveTransition.shouldFinish = progress > 0.5 customInteractiveTransition.update(progress) case .ended: customInteractiveTransition.hasStarted = false customInteractiveTransition.shouldFinish ? customInteractiveTransition.finish() : customInteractiveTransition.cancel() case .cancelled: customInteractiveTransition.hasStarted = false customInteractiveTransition.cancel() default: break } } func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { return operation == .pop ? customAnimator : nil } func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { return customInteractiveTransition.hasStarted ? customInteractiveTransition : nil } func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) { if let hostingController = viewController as? AIMAHostingController<SwiftUIView> { DispatchQueue.main.async { hostingController.view.setNeedsLayout() hostingController.view.layoutIfNeeded() } } } } SwiftUI code struct SwiftUIView: View { var body: some View { VStack { Spacer() Text("Hello, World!") .id("123") .background(Color.green) .padding() .onTapGesture { print("===onclick") } Spacer() } } } let hostingController = UIHostingController(rootView: SwiftUIView()) navigationController?.pushViewController(hostingController, animated: true)
0
0
176
Jun ’24