Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.

All subtopics
Posts under UI Frameworks topic

Post

Replies

Boosts

Views

Activity

Alert structure and playing sound
Hello, I'm working on an SwiftUI iOS app that shows a list of timers. When the timer is up then I pop up an alert struct. The user hits "ok" to dismiss the alert. I am trying to include an alarm sound using AVFoundation. I can get the sounds to play if I change the code to play when a button clicks so I believe I have the url path correct. But I really want it to play during the alert pop up. I have not been able to find examples where this is done using an alert so I suspect I need a custom view but thought I'd try the alert route first. Anyone try this before? @State var audioPlayer: AVAudioPlayer? .alert(isPresented: $showAlarmAlert) { playSound() -- Calls AVFoundation return Alert(title: Text("Time's Up!")) } func playSound() { let alertSoundPath = Bundle.main.url(forResource: "classicAlarm", withExtension: "mp3")! do { audioPlayer = try AVAudioPlayer(contentsOf: alertSoundPath) audioPlayer?.play() } catch { appData.logger.debug("Error playing sound: \(alertSoundPath)") } }
4
0
174
Jun ’25
Additional Questions Regarding App Launch Timing
I found the following statement on the site TN3187: Migrating to the UIKit scene-based life cycle | Apple Developer Documentation: "Soon, all UIKit based apps will be required to adopt the scene-based life-cycle, after which your app won’t launch if you don’t. While supporting multiple scenes is encouraged, only adoption of scene life-cycle is required." In this post, you mentioned that the timing is undecided. https://developer.apple.com/forums/thread/785588 I would like to confirm the following two points additionally. Could you please confirm whether the timing when the app will not be able to launch is during an iOS update or at another specific time? This will change our response policy. Does "your app won’t launch" mean that already distributed apps will also not be able to launch? Or does it mean that newly developed apps will fail to build or be rejected during app review?
Topic: UI Frameworks SubTopic: UIKit Tags:
2
0
347
Jun ’25
iOS UILabel textAlignment .justified results in wrong rect by layoutManager.boundingRect
I have a UILabel subclass showing NSAttributedString in which I need to draw a rounded rectangle background color around links: import UIKit class MyLabel: UILabel { private var linkRects = [[CGRect]]() private let layoutManager = NSLayoutManager() private let textContainer = NSTextContainer(size: .zero) private let textStorage = NSTextStorage() override func draw(_ rect: CGRect) { let path = UIBezierPath() linkRects.forEach { rects in rects.forEach { linkPieceRect in path.append(UIBezierPath(roundedRect: linkPieceRect, cornerRadius: 2)) } } UIColor.systemGreen.withAlphaComponent(0.4).setFill() path.fill() super.draw(rect) } override init(frame: CGRect) { super.init(frame: frame) setup() } required init?(coder: NSCoder) { super.init(coder: coder) setup() } private func setup() { numberOfLines = 0 adjustsFontForContentSizeCategory = true isUserInteractionEnabled = true lineBreakMode = .byWordWrapping contentMode = .redraw clearsContextBeforeDrawing = true isMultipleTouchEnabled = false backgroundColor = .red.withAlphaComponent(0.1) textContainer.lineFragmentPadding = 0 textContainer.maximumNumberOfLines = numberOfLines textContainer.lineBreakMode = lineBreakMode textContainer.layoutManager = layoutManager layoutManager.textStorage = textStorage layoutManager.addTextContainer(textContainer) textStorage.addLayoutManager(layoutManager) } override func layoutSubviews() { super.layoutSubviews() calculateRects() } private func calculateRects(){ linkRects.removeAll() guard let attributedString = attributedText else { return } textStorage.setAttributedString(attributedString) let labelSize = frame.size textContainer.size = labelSize layoutManager.ensureLayout(for: textContainer) let textBoundingBox = layoutManager.usedRect(for: textContainer) print("labelSize: \(labelSize)") print("textBoundingBox: \(textBoundingBox)") var wholeLineRanges = [NSRange]() layoutManager.enumerateLineFragments(forGlyphRange: NSRange(0 ..< layoutManager.numberOfGlyphs)) { _, rect, _, range, _ in wholeLineRanges.append(range) print("Whole line: \(rect), \(range)") } attributedString.enumerateAttribute(.link, in: NSRange(location: 0, length: attributedString.length)) { value, clickableRange, _ in if value != nil { var rectsForCurrentLink = [CGRect]() wholeLineRanges.forEach { wholeLineRange in if let linkPartIntersection = wholeLineRange.intersection(clickableRange) { var rectForLinkPart = layoutManager.boundingRect(forGlyphRange: linkPartIntersection, in: textContainer) rectForLinkPart.origin.y = rectForLinkPart.origin.y + (textContainer.size.height - textBoundingBox.height) / 2 // Adjust for vertical alignment rectsForCurrentLink.append(rectForLinkPart) print("Link rect: \(rectForLinkPart), \(linkPartIntersection)") } } if !rectsForCurrentLink.isEmpty { linkRects.append(rectsForCurrentLink) } } } print("linkRects: \(linkRects)") setNeedsDisplay() } } And I use this as such: let label = MyLabel() label.setContentHuggingPriority(.required, for: .vertical) label.setContentHuggingPriority(.required, for: .horizontal) view.addSubview(label) label.snp.makeConstraints { make in make.width.lessThanOrEqualTo(view.safeAreaLayoutGuide.snp.width).priority(.required) make.horizontalEdges.greaterThanOrEqualTo(view.safeAreaLayoutGuide).priority(.required) make.center.equalTo(view.safeAreaLayoutGuide).priority(.required) } let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.alignment = .justified let s = NSMutableAttributedString(string: "Lorem Ipsum: ", attributes: [.font: UIFont.systemFont(ofSize: 17, weight: .regular), .paragraphStyle: paragraphStyle]) s.append(NSAttributedString(string: "This property controls the maximum number of lines to use in order to fit the label's text into its bounding rectangle.", attributes: [.link: URL(string: "https://news.ycombinator.com/") as Any, .foregroundColor: UIColor.link, .font: UIFont.systemFont(ofSize: 14, weight: .regular), .paragraphStyle: paragraphStyle])) label.attributedText = s Notice the paragraphStyle.alignment = .justified This results in: As you can see, the green rect background is starting a bit further to the right and also ending much further to the right. If I set the alignment to be .left or .center, then it gives me the correct rects: Also note that if I keep .justified but change the font size for the "Lorem Ipsom:" part to be a bit different, lets say 16 instead of 17, then it gives me the correct rect too: Also note that if we remove some word from the string, then also it starts giving correct rect. It seems like if the first line is too squished, then it reports wrong rects. Why is .justified text alignment giving me wrong rects? How can I fix it?
Topic: UI Frameworks SubTopic: UIKit
0
0
116
May ’25
StoreKit not returning products after IAP localization was re-approved (Adapty: noProductIDsFound)
🔹 Description of the issue: My app uses Adapty to fetch and display in-app subscription products on a paywall. The system has worked perfectly until recently. After I edited the localizations of the subscriptions in App Store Connect, they were temporarily rejected. Since that moment, the products no longer show in the app. Even though I re-submitted the localizations and they were approved, StoreKit still does not return any products, and Adapty returns the error: less CopyEdit AdaptyError(code: 1000, message: "No products were found for provided product ids") 🔹 Error Message: noProductIDsFound — from Adapty SDK when attempting to load paywall products. 🔹 Steps to Reproduce: Open the Aida Nena app (App ID: 6737695739). Sign in with a test account or create a new one. Go to Profile → Subscription. The paywall will show but no products will appear. Logs show Adapty attempting to fetch product IDs but none are found in StoreKit. 🔹 What I’ve Tried: Re-activating the Adapty SDK. Forcing a cache reset via app reinstall. Re-checking App Store Connect: all subscriptions and localizations now show Approved (green). Waiting several hours in case of propagation. Verifying correct product identifiers are in use — they haven’t changed. 🔹 My Hypothesis: The StoreKit product metadata is still not properly refreshed after the rejection and re-approval of the localizations. This is preventing Adapty (and StoreKit) from returning the product data even though the products are live and approved. 🔹 Additional Info: SDK: @adapty/react-native + Adapty iOS SDK under the hood. This seems to be a known edge case among developers after a product's metadata/localization is changed and re-approved. Thanks, I appreciate any help.
1
0
203
Jun ’25
Conditionally Adding and Deleting a Row in a UITableView
Hello! I wanted to see if someone with more UIKit experience than me can help me out on guiding me in the right direction for conditionally adding and deleting a row in a UITableView. What I Want to Accomplish I have a tip slider with percentages (0% - 20%) with a custom option on the end. I'm wanting to, when the custom option is tapped, bring up a row immediately below there and have a UITextField. When another option, let's say 10%, is tapped, I want the text field row to go away. Can someone explain to me how this would work? And if so, provide an example? Thank you!
Topic: UI Frameworks SubTopic: UIKit Tags:
3
0
133
Jun ’25
.roundedCorners instead of .cornerRadius(?)
In WWDC 25's session Get to Know the Design system, Maria mentions that corner radius should match it's parent view or the iPhone's corners if its the outermost view. Rather than trying to figure out what number to pass into .cornerRadius(15), why not have a .roundedCorner modifier and have the system do this geometry work? See my feedback also FB17947241
Topic: UI Frameworks SubTopic: SwiftUI
2
2
200
Jun ’25
Best practices for accessing NavigationPath in child views
Hi all I'm reworking our app in SwiftUI. My ultimate goal is to access the NavigationPath from a child view which is used throughout different NavgationStacks. While searching for I came across different ways of achieving this. As I'm relatively new to SwiftUI it is hard to understand what the actual best practice seems to be. So for the use case. My app has a TabView and each Tab has its own NavigationStack which looks something like this struct TabNavigation: View { @State private var selectedProductType: StaticProductType = .all @StateObject private var appRouter = AppRouter() var body: some View { TabView(selection: $appRouter.selectedTab) { Overview(activeType: $selectedProductType) .tabItem { Label("Home", systemImage: "house") } .tag(Tab.home) AssortmentView(router: $appRouter.assortmentRouter, activeType: $selectedProductType) .tabItem { Label(String(localized: "assortment"), systemImage: "list.bullet") } .tag(Tab.assortment) } } The AssortmenView holds the NavigationStack and defines the routes. struct AssortmentView: View { @Binding var router: AssortmentRouter @Binding var activeType: StaticProductType var body: some View { NavigationStack(path: $router.navigationPath) { VStack { ProductTypeNavigation(activeType: $activeType) .padding(.top, 10) .padding(.horizontal, 10) Spacer() TabView(selection: $activeType) { ListNavigation(type: .all) .tag(StaticProductType.all) ListNavigation(type: .games) .tag(StaticProductType.games) ListNavigation(type: .digital) .tag(StaticProductType.digital) ListNavigation(type: .toys) .tag(StaticProductType.toys) ListNavigation(type: .movies) .tag(StaticProductType.movies) ListNavigation(type: .books) .tag(StaticProductType.books) } .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) } .addToolbar() .navigationDestination(for: AssortmentRouter.Route.self) { route in switch route { case .overview(let type): OverviewTypeView(type: type) case .productDetail(let productId): ProductDetailView(productId: productId) .environmentObject(router) case .productList: ProductList() } } } } } Through my app I often use a view to displaying products. This view is reused over different NavigationStacks. struct ProductDetailView: View { var productId: Int @StateObject private var viewModel: ProductDetailViewModel = ProductDetailViewModel() @State private var showErrorAlert = false @EnvironmentObject var router: AssortmentRouter var body: some View { VStack { if !viewModel.isRefreshing { let product = viewModel.product VStack { Text("Product: \(product.title)") NavigationLink(destination: ProductDetailView(productId: Product.preview.productId)) { Text("Test") } } .navigationTitle(product.title) } else { ProgressView() } }.task { await loadProduct() } .alert("Error", isPresented: $showErrorAlert, presenting: viewModel.localizedError) { _ in Button("Try again") { Task { await loadProduct() } } Button("Go Back", role: .cancel) { // access navigationPath } } message: { errorMessage in Text(errorMessage) } } @MainActor private func loadProduct() async { await viewModel.loadProduct(productId: productId) showErrorAlert = viewModel.localizedError != nil } } In this example I created an AppRouter which holds all information for the routes and some functions to accessing the NavigationPath. class AppRouter: ObservableObject { var assortmentRouter = AssortmentRouter() var selectedTab: Tab = .home func navigateTo(tab: Tab) { selectedTab = tab } } class AssortmentRouter: ObservableObject { var navigationPath = NavigationPath() enum Route: Hashable { case overview(type: StaticProductType) case productList case productDetail(productId: Int) } func navigateTo(route: Route) { navigationPath.append(route) } } This works fine as it is. The pro of this solution is that I don't have to pass the NavigationPath down each subview to use it as I can define it as EnvrionmentObject. The problem with this though, I like to reuse ProductDetailView also in my other NavigationStack which won't have a router binding of type AssortmentRouter as you can imagine. To come back to my initial question, what would be the best way to design this? Passing down a NavigationPath Binding and using different typing for navigationDestinaion values Define a callback which is passed as function parameter to the detail view Using dismiss, but I read that this is can lead to weird behaviour and bugs Any other option? Maybe changing the app architecture to handle this a better way Apolgize the long post, but I would be really glad to get some feedback on this, so I can do it the right way. Thank you very much
3
0
125
May ’25
chartXAxis AxisMark consisting of Month:Year
I have a Chart displaying Counts per Date over 2-3 years. I'd like to have the XAxis mark consist of MM-yy or even MM/nyy. Is this possible? OK, just saw AxisValueLabel(format: .dateTime.month().year()) which gives e.g. Mar 2024. This is good. Better might be Mar 24 (maybe a Y3K problem ;-) or even better Mar. OR Mar 24. 2024 Or best increment the year when it changes. Are any of these alternate formats possible? Thanks, David PS, my current .chartXAxis code .chartXAxis { AxisMarks(values: .stride(by: .month, count: 3)) { value in if value.as(Date.self) != nil { AxisValueLabel(format: .dateTime.month().year()) AxisGridLine() AxisTick() } } }
1
0
203
Jun ’25
CPGridTemplate in CPTabBarTemplate: Second Item Not Selecting in CarPlay Simulator
I am experiencing an issue while using CPGridTemplate within CPTabBarTemplate in my CarPlay app running in the simulator. On app launch, when I select the second item in the grid, it does not visually reflect as selected in the UI. This behavior is unexpected, as the grid item selection should update accordingly. Has anyone encountered this issue or found a solution to ensure proper item selection?
1
0
83
May ’25
ScrollPosition.scrollTo(id:, anchor:) not behaving as expected
While trying the new ScrollPosition API I noticed that scrollTo(id: anchor:) behaves different than ScrollViewProxy.scrollTo(_: anchor:). Consider the following example: struct ContentView: View { @State private var position = ScrollPosition(edge: .top) var body: some View { NavigationStack { ScrollViewReader { proxy in ScrollView { VStack(spacing: 8) { ForEach(1..<100) { index in Text(verbatim: index.formatted()) .frame(maxWidth: .infinity) .background(.gray) .id(index) } } } .scrollPosition($position) .toolbar { ToolbarItemGroup(placement: .bottomBar) { Spacer() Button("50 (T)") { withAnimation { position.scrollTo(id: 50, anchor: .top) // proxy.scrollTo(50, anchor: .top) } } Button("50 (B)") { withAnimation { position.scrollTo(id: 50, anchor: .bottom) // proxy.scrollTo(50, anchor: .bottom) } } Spacer() } } } } } } The position methods don't align top and bottom edges, but the proxy ones do. Is this expected or is it a bug?
2
0
160
May ’25
NSPredicateEditorRowTemplate subviews layout
Hello everyone, I’d appreciate if anyone can tell me if there’s a way to actually control visual layout of subviews in a predicate editor row template. I have a predicate editor with custom row template subclasses, all created in code (not in IB) and it all works fine, but the problem are template (sub)views, which are not NSPopUpButton(s). As I select different items of popup buttons, effectively changing editor’s predicate property, those buttons seem to get resized according to some strange own logic, but the general the problem is that size (width) of controls, such are text fields and date pickers, gets unpredictable and they usually shrink, even though there is still a plenty of room in the template row width. Trying to resize any control in a row template by force (setFrame: or setFrameSize:) has no effect. I can show some screenshots and videos of the behaviour, as well as code samples, if necessary, but I’d like to ask first, maybe someone already knows what I’m talking about and provide some insights and solutions. Thanks in advance.
Topic: UI Frameworks SubTopic: AppKit
0
0
113
May ’25
Application crashes when using TextEditor(text, selection)
I have a TextEditor, to the constructor of which in addition to the text I pass an object of the TextSelection? type. I check on the Simulator with iOS 18.2. An attempt to clear the text leads to a crash with the message "Thread 1: Fatal error: String index is out of bounds" in Xcode. More about the error: libswiftCore.dylib`_swift_runtime_on_report: -> 0x194f32024 <+0>: ret More about the reproduction conditions: struct MyView: View { @Bindable private var viewModel = MyViewModel() @State var myTextSelection: TextSelection? = nil var body: some View { ZStack { // Some other code myEditor // Some other code } .toolbar { ToolbarItem(placement: .primaryAction) { Button { viewModel.clear() } label: { Label("Clear", systemImage: "eraser") } } } } var myEditor: some View { ZStack(alignment: .topLeading) { TextEditor(text: $viewModel.text, selection: $myTextSelection) .disableAutocorrection(true) .autocapitalization(.sentences) } // Some other code } } MyViewModel: @Observable final class MyViewModel: ObservableObject { var text: String = "" func clear() { text = "" } }
1
0
142
May ’25
How to get the date range of the data that is currently displayed in a Apple Chart?
I have a Swiftui app, and I'm using the Apple Chart framework to chart user transactions over time. I'd like to be able to show an annotation at the top of the chart that shows the date range of the records currently visible on the chart. Much like Apple does in their Heath App charts. But I just can't seem to find a method to read the current date range displayed on the chart once the user has scrolled though the chart. Has anyone done anything similar, or maybe seen some sample code? So far I'm striking out on this... Thanks in advance
1
0
246
May ’25
NWPathMonitor Failing
I need to check the network connection with NWPathMonitor. import Foundation import Network class NetworkViewModel: ObservableObject { let monitor = NWPathMonitor() let queue = DispatchQueue(label: "NetworkViewModel") @Published var isConnected = false var connectionDescription: String { if isConnected { return "You are connected." } else { return "You are NOT connected." } } init() { monitor.pathUpdateHandler = { path in DispatchQueue.main.async { self.isConnected = path.status == .satisfied } } monitor.start(queue: queue) } } import SwiftUI struct ContentView: View { @StateObject private var networkViewModel = NetworkViewModel() var body: some View { VStack { } .onAppear { if networkViewModel.isConnected { print("You are connected.") } else { print("You are NOT connected.") } } } } So there is nothing special, not at all. Yet, if I test it with a totally new Xcode project for iOS, it fails and return !isConnected. I've tested it with a macOS application. And it fails. I've tested it with an actual device. It fails. I've tested it with an old project. It still does work. I have no mere idea why new Xcode projects all fail to detect the WiFi connection. This is a total nightmare. Does anybody have a clue? thanks.
7
0
302
May ’25
Dock tile plugin and app groups
In one of my apps I use an app group to share data between the app and a command line tool. This works as expected. The app also contains a Dock Tile plugin and I wonder if there's a way to access the group container from this plugin? Thanks in advance for your help. Best regards, Marc
5
0
470
May ’25
InspectorCommands available on visionOS?
The inspector(isPresented:content:) modifier is not available on visionOS while the InspectorCommands struct is marked available on visionOS. Should inspector work on visionOS as well or is this an oversight?
Replies
1
Boosts
1
Views
91
Activity
Jun ’25
Alert structure and playing sound
Hello, I'm working on an SwiftUI iOS app that shows a list of timers. When the timer is up then I pop up an alert struct. The user hits "ok" to dismiss the alert. I am trying to include an alarm sound using AVFoundation. I can get the sounds to play if I change the code to play when a button clicks so I believe I have the url path correct. But I really want it to play during the alert pop up. I have not been able to find examples where this is done using an alert so I suspect I need a custom view but thought I'd try the alert route first. Anyone try this before? @State var audioPlayer: AVAudioPlayer? .alert(isPresented: $showAlarmAlert) { playSound() -- Calls AVFoundation return Alert(title: Text("Time's Up!")) } func playSound() { let alertSoundPath = Bundle.main.url(forResource: "classicAlarm", withExtension: "mp3")! do { audioPlayer = try AVAudioPlayer(contentsOf: alertSoundPath) audioPlayer?.play() } catch { appData.logger.debug("Error playing sound: \(alertSoundPath)") } }
Replies
4
Boosts
0
Views
174
Activity
Jun ’25
Additional Questions Regarding App Launch Timing
I found the following statement on the site TN3187: Migrating to the UIKit scene-based life cycle | Apple Developer Documentation: "Soon, all UIKit based apps will be required to adopt the scene-based life-cycle, after which your app won’t launch if you don’t. While supporting multiple scenes is encouraged, only adoption of scene life-cycle is required." In this post, you mentioned that the timing is undecided. https://developer.apple.com/forums/thread/785588 I would like to confirm the following two points additionally. Could you please confirm whether the timing when the app will not be able to launch is during an iOS update or at another specific time? This will change our response policy. Does "your app won’t launch" mean that already distributed apps will also not be able to launch? Or does it mean that newly developed apps will fail to build or be rejected during app review?
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
2
Boosts
0
Views
347
Activity
Jun ’25
iOS UILabel textAlignment .justified results in wrong rect by layoutManager.boundingRect
I have a UILabel subclass showing NSAttributedString in which I need to draw a rounded rectangle background color around links: import UIKit class MyLabel: UILabel { private var linkRects = [[CGRect]]() private let layoutManager = NSLayoutManager() private let textContainer = NSTextContainer(size: .zero) private let textStorage = NSTextStorage() override func draw(_ rect: CGRect) { let path = UIBezierPath() linkRects.forEach { rects in rects.forEach { linkPieceRect in path.append(UIBezierPath(roundedRect: linkPieceRect, cornerRadius: 2)) } } UIColor.systemGreen.withAlphaComponent(0.4).setFill() path.fill() super.draw(rect) } override init(frame: CGRect) { super.init(frame: frame) setup() } required init?(coder: NSCoder) { super.init(coder: coder) setup() } private func setup() { numberOfLines = 0 adjustsFontForContentSizeCategory = true isUserInteractionEnabled = true lineBreakMode = .byWordWrapping contentMode = .redraw clearsContextBeforeDrawing = true isMultipleTouchEnabled = false backgroundColor = .red.withAlphaComponent(0.1) textContainer.lineFragmentPadding = 0 textContainer.maximumNumberOfLines = numberOfLines textContainer.lineBreakMode = lineBreakMode textContainer.layoutManager = layoutManager layoutManager.textStorage = textStorage layoutManager.addTextContainer(textContainer) textStorage.addLayoutManager(layoutManager) } override func layoutSubviews() { super.layoutSubviews() calculateRects() } private func calculateRects(){ linkRects.removeAll() guard let attributedString = attributedText else { return } textStorage.setAttributedString(attributedString) let labelSize = frame.size textContainer.size = labelSize layoutManager.ensureLayout(for: textContainer) let textBoundingBox = layoutManager.usedRect(for: textContainer) print("labelSize: \(labelSize)") print("textBoundingBox: \(textBoundingBox)") var wholeLineRanges = [NSRange]() layoutManager.enumerateLineFragments(forGlyphRange: NSRange(0 ..< layoutManager.numberOfGlyphs)) { _, rect, _, range, _ in wholeLineRanges.append(range) print("Whole line: \(rect), \(range)") } attributedString.enumerateAttribute(.link, in: NSRange(location: 0, length: attributedString.length)) { value, clickableRange, _ in if value != nil { var rectsForCurrentLink = [CGRect]() wholeLineRanges.forEach { wholeLineRange in if let linkPartIntersection = wholeLineRange.intersection(clickableRange) { var rectForLinkPart = layoutManager.boundingRect(forGlyphRange: linkPartIntersection, in: textContainer) rectForLinkPart.origin.y = rectForLinkPart.origin.y + (textContainer.size.height - textBoundingBox.height) / 2 // Adjust for vertical alignment rectsForCurrentLink.append(rectForLinkPart) print("Link rect: \(rectForLinkPart), \(linkPartIntersection)") } } if !rectsForCurrentLink.isEmpty { linkRects.append(rectsForCurrentLink) } } } print("linkRects: \(linkRects)") setNeedsDisplay() } } And I use this as such: let label = MyLabel() label.setContentHuggingPriority(.required, for: .vertical) label.setContentHuggingPriority(.required, for: .horizontal) view.addSubview(label) label.snp.makeConstraints { make in make.width.lessThanOrEqualTo(view.safeAreaLayoutGuide.snp.width).priority(.required) make.horizontalEdges.greaterThanOrEqualTo(view.safeAreaLayoutGuide).priority(.required) make.center.equalTo(view.safeAreaLayoutGuide).priority(.required) } let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.alignment = .justified let s = NSMutableAttributedString(string: "Lorem Ipsum: ", attributes: [.font: UIFont.systemFont(ofSize: 17, weight: .regular), .paragraphStyle: paragraphStyle]) s.append(NSAttributedString(string: "This property controls the maximum number of lines to use in order to fit the label's text into its bounding rectangle.", attributes: [.link: URL(string: "https://news.ycombinator.com/") as Any, .foregroundColor: UIColor.link, .font: UIFont.systemFont(ofSize: 14, weight: .regular), .paragraphStyle: paragraphStyle])) label.attributedText = s Notice the paragraphStyle.alignment = .justified This results in: As you can see, the green rect background is starting a bit further to the right and also ending much further to the right. If I set the alignment to be .left or .center, then it gives me the correct rects: Also note that if I keep .justified but change the font size for the "Lorem Ipsom:" part to be a bit different, lets say 16 instead of 17, then it gives me the correct rect too: Also note that if we remove some word from the string, then also it starts giving correct rect. It seems like if the first line is too squished, then it reports wrong rects. Why is .justified text alignment giving me wrong rects? How can I fix it?
Topic: UI Frameworks SubTopic: UIKit
Replies
0
Boosts
0
Views
116
Activity
May ’25
StoreKit not returning products after IAP localization was re-approved (Adapty: noProductIDsFound)
🔹 Description of the issue: My app uses Adapty to fetch and display in-app subscription products on a paywall. The system has worked perfectly until recently. After I edited the localizations of the subscriptions in App Store Connect, they were temporarily rejected. Since that moment, the products no longer show in the app. Even though I re-submitted the localizations and they were approved, StoreKit still does not return any products, and Adapty returns the error: less CopyEdit AdaptyError(code: 1000, message: "No products were found for provided product ids") 🔹 Error Message: noProductIDsFound — from Adapty SDK when attempting to load paywall products. 🔹 Steps to Reproduce: Open the Aida Nena app (App ID: 6737695739). Sign in with a test account or create a new one. Go to Profile → Subscription. The paywall will show but no products will appear. Logs show Adapty attempting to fetch product IDs but none are found in StoreKit. 🔹 What I’ve Tried: Re-activating the Adapty SDK. Forcing a cache reset via app reinstall. Re-checking App Store Connect: all subscriptions and localizations now show Approved (green). Waiting several hours in case of propagation. Verifying correct product identifiers are in use — they haven’t changed. 🔹 My Hypothesis: The StoreKit product metadata is still not properly refreshed after the rejection and re-approval of the localizations. This is preventing Adapty (and StoreKit) from returning the product data even though the products are live and approved. 🔹 Additional Info: SDK: @adapty/react-native + Adapty iOS SDK under the hood. This seems to be a known edge case among developers after a product's metadata/localization is changed and re-approved. Thanks, I appreciate any help.
Replies
1
Boosts
0
Views
203
Activity
Jun ’25
Conditionally Adding and Deleting a Row in a UITableView
Hello! I wanted to see if someone with more UIKit experience than me can help me out on guiding me in the right direction for conditionally adding and deleting a row in a UITableView. What I Want to Accomplish I have a tip slider with percentages (0% - 20%) with a custom option on the end. I'm wanting to, when the custom option is tapped, bring up a row immediately below there and have a UITextField. When another option, let's say 10%, is tapped, I want the text field row to go away. Can someone explain to me how this would work? And if so, provide an example? Thank you!
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
3
Boosts
0
Views
133
Activity
Jun ’25
.roundedCorners instead of .cornerRadius(?)
In WWDC 25's session Get to Know the Design system, Maria mentions that corner radius should match it's parent view or the iPhone's corners if its the outermost view. Rather than trying to figure out what number to pass into .cornerRadius(15), why not have a .roundedCorner modifier and have the system do this geometry work? See my feedback also FB17947241
Topic: UI Frameworks SubTopic: SwiftUI
Replies
2
Boosts
2
Views
200
Activity
Jun ’25
Best practices for accessing NavigationPath in child views
Hi all I'm reworking our app in SwiftUI. My ultimate goal is to access the NavigationPath from a child view which is used throughout different NavgationStacks. While searching for I came across different ways of achieving this. As I'm relatively new to SwiftUI it is hard to understand what the actual best practice seems to be. So for the use case. My app has a TabView and each Tab has its own NavigationStack which looks something like this struct TabNavigation: View { @State private var selectedProductType: StaticProductType = .all @StateObject private var appRouter = AppRouter() var body: some View { TabView(selection: $appRouter.selectedTab) { Overview(activeType: $selectedProductType) .tabItem { Label("Home", systemImage: "house") } .tag(Tab.home) AssortmentView(router: $appRouter.assortmentRouter, activeType: $selectedProductType) .tabItem { Label(String(localized: "assortment"), systemImage: "list.bullet") } .tag(Tab.assortment) } } The AssortmenView holds the NavigationStack and defines the routes. struct AssortmentView: View { @Binding var router: AssortmentRouter @Binding var activeType: StaticProductType var body: some View { NavigationStack(path: $router.navigationPath) { VStack { ProductTypeNavigation(activeType: $activeType) .padding(.top, 10) .padding(.horizontal, 10) Spacer() TabView(selection: $activeType) { ListNavigation(type: .all) .tag(StaticProductType.all) ListNavigation(type: .games) .tag(StaticProductType.games) ListNavigation(type: .digital) .tag(StaticProductType.digital) ListNavigation(type: .toys) .tag(StaticProductType.toys) ListNavigation(type: .movies) .tag(StaticProductType.movies) ListNavigation(type: .books) .tag(StaticProductType.books) } .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) } .addToolbar() .navigationDestination(for: AssortmentRouter.Route.self) { route in switch route { case .overview(let type): OverviewTypeView(type: type) case .productDetail(let productId): ProductDetailView(productId: productId) .environmentObject(router) case .productList: ProductList() } } } } } Through my app I often use a view to displaying products. This view is reused over different NavigationStacks. struct ProductDetailView: View { var productId: Int @StateObject private var viewModel: ProductDetailViewModel = ProductDetailViewModel() @State private var showErrorAlert = false @EnvironmentObject var router: AssortmentRouter var body: some View { VStack { if !viewModel.isRefreshing { let product = viewModel.product VStack { Text("Product: \(product.title)") NavigationLink(destination: ProductDetailView(productId: Product.preview.productId)) { Text("Test") } } .navigationTitle(product.title) } else { ProgressView() } }.task { await loadProduct() } .alert("Error", isPresented: $showErrorAlert, presenting: viewModel.localizedError) { _ in Button("Try again") { Task { await loadProduct() } } Button("Go Back", role: .cancel) { // access navigationPath } } message: { errorMessage in Text(errorMessage) } } @MainActor private func loadProduct() async { await viewModel.loadProduct(productId: productId) showErrorAlert = viewModel.localizedError != nil } } In this example I created an AppRouter which holds all information for the routes and some functions to accessing the NavigationPath. class AppRouter: ObservableObject { var assortmentRouter = AssortmentRouter() var selectedTab: Tab = .home func navigateTo(tab: Tab) { selectedTab = tab } } class AssortmentRouter: ObservableObject { var navigationPath = NavigationPath() enum Route: Hashable { case overview(type: StaticProductType) case productList case productDetail(productId: Int) } func navigateTo(route: Route) { navigationPath.append(route) } } This works fine as it is. The pro of this solution is that I don't have to pass the NavigationPath down each subview to use it as I can define it as EnvrionmentObject. The problem with this though, I like to reuse ProductDetailView also in my other NavigationStack which won't have a router binding of type AssortmentRouter as you can imagine. To come back to my initial question, what would be the best way to design this? Passing down a NavigationPath Binding and using different typing for navigationDestinaion values Define a callback which is passed as function parameter to the detail view Using dismiss, but I read that this is can lead to weird behaviour and bugs Any other option? Maybe changing the app architecture to handle this a better way Apolgize the long post, but I would be really glad to get some feedback on this, so I can do it the right way. Thank you very much
Replies
3
Boosts
0
Views
125
Activity
May ’25
Reader Mode for new WebView & WebPage APIs
I am curious if the new WebView and WebPage APIs have a way to programmatically set if the web page should be shown in Reader Mode like you could with SFSafariViewController. I did not see a way to do this, but I'm curious if I may be missing something.
Replies
1
Boosts
0
Views
114
Activity
Jun ’25
chartXAxis AxisMark consisting of Month:Year
I have a Chart displaying Counts per Date over 2-3 years. I'd like to have the XAxis mark consist of MM-yy or even MM/nyy. Is this possible? OK, just saw AxisValueLabel(format: .dateTime.month().year()) which gives e.g. Mar 2024. This is good. Better might be Mar 24 (maybe a Y3K problem ;-) or even better Mar. OR Mar 24. 2024 Or best increment the year when it changes. Are any of these alternate formats possible? Thanks, David PS, my current .chartXAxis code .chartXAxis { AxisMarks(values: .stride(by: .month, count: 3)) { value in if value.as(Date.self) != nil { AxisValueLabel(format: .dateTime.month().year()) AxisGridLine() AxisTick() } } }
Replies
1
Boosts
0
Views
203
Activity
Jun ’25
.fullScreenCover does not work in iOS26
Basically when showing a view using the .fullScreenCover modifier, it has no background anymore, any other UI elements are still shown but the view under it is also still shown.
Replies
1
Boosts
4
Views
205
Activity
Jun ’25
CPGridTemplate in CPTabBarTemplate: Second Item Not Selecting in CarPlay Simulator
I am experiencing an issue while using CPGridTemplate within CPTabBarTemplate in my CarPlay app running in the simulator. On app launch, when I select the second item in the grid, it does not visually reflect as selected in the UI. This behavior is unexpected, as the grid item selection should update accordingly. Has anyone encountered this issue or found a solution to ensure proper item selection?
Replies
1
Boosts
0
Views
83
Activity
May ’25
Understanding how to make focusedImage work on CPMapButton
When my CPMapButton is selected/focused, I would like to be able to provide a focusedImage to correctly show the button when the blue focus is shown. Currently I have: What do I need to do to create an image that works more like the panning interface buttons?
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
0
Boosts
0
Views
260
Activity
Jun ’25
ScrollPosition.scrollTo(id:, anchor:) not behaving as expected
While trying the new ScrollPosition API I noticed that scrollTo(id: anchor:) behaves different than ScrollViewProxy.scrollTo(_: anchor:). Consider the following example: struct ContentView: View { @State private var position = ScrollPosition(edge: .top) var body: some View { NavigationStack { ScrollViewReader { proxy in ScrollView { VStack(spacing: 8) { ForEach(1..<100) { index in Text(verbatim: index.formatted()) .frame(maxWidth: .infinity) .background(.gray) .id(index) } } } .scrollPosition($position) .toolbar { ToolbarItemGroup(placement: .bottomBar) { Spacer() Button("50 (T)") { withAnimation { position.scrollTo(id: 50, anchor: .top) // proxy.scrollTo(50, anchor: .top) } } Button("50 (B)") { withAnimation { position.scrollTo(id: 50, anchor: .bottom) // proxy.scrollTo(50, anchor: .bottom) } } Spacer() } } } } } } The position methods don't align top and bottom edges, but the proxy ones do. Is this expected or is it a bug?
Replies
2
Boosts
0
Views
160
Activity
May ’25
NSPredicateEditorRowTemplate subviews layout
Hello everyone, I’d appreciate if anyone can tell me if there’s a way to actually control visual layout of subviews in a predicate editor row template. I have a predicate editor with custom row template subclasses, all created in code (not in IB) and it all works fine, but the problem are template (sub)views, which are not NSPopUpButton(s). As I select different items of popup buttons, effectively changing editor’s predicate property, those buttons seem to get resized according to some strange own logic, but the general the problem is that size (width) of controls, such are text fields and date pickers, gets unpredictable and they usually shrink, even though there is still a plenty of room in the template row width. Trying to resize any control in a row template by force (setFrame: or setFrameSize:) has no effect. I can show some screenshots and videos of the behaviour, as well as code samples, if necessary, but I’d like to ask first, maybe someone already knows what I’m talking about and provide some insights and solutions. Thanks in advance.
Topic: UI Frameworks SubTopic: AppKit
Replies
0
Boosts
0
Views
113
Activity
May ’25
Application crashes when using TextEditor(text, selection)
I have a TextEditor, to the constructor of which in addition to the text I pass an object of the TextSelection? type. I check on the Simulator with iOS 18.2. An attempt to clear the text leads to a crash with the message "Thread 1: Fatal error: String index is out of bounds" in Xcode. More about the error: libswiftCore.dylib`_swift_runtime_on_report: -> 0x194f32024 <+0>: ret More about the reproduction conditions: struct MyView: View { @Bindable private var viewModel = MyViewModel() @State var myTextSelection: TextSelection? = nil var body: some View { ZStack { // Some other code myEditor // Some other code } .toolbar { ToolbarItem(placement: .primaryAction) { Button { viewModel.clear() } label: { Label("Clear", systemImage: "eraser") } } } } var myEditor: some View { ZStack(alignment: .topLeading) { TextEditor(text: $viewModel.text, selection: $myTextSelection) .disableAutocorrection(true) .autocapitalization(.sentences) } // Some other code } } MyViewModel: @Observable final class MyViewModel: ObservableObject { var text: String = "" func clear() { text = "" } }
Replies
1
Boosts
0
Views
142
Activity
May ’25
How to get the date range of the data that is currently displayed in a Apple Chart?
I have a Swiftui app, and I'm using the Apple Chart framework to chart user transactions over time. I'd like to be able to show an annotation at the top of the chart that shows the date range of the records currently visible on the chart. Much like Apple does in their Heath App charts. But I just can't seem to find a method to read the current date range displayed on the chart once the user has scrolled though the chart. Has anyone done anything similar, or maybe seen some sample code? So far I'm striking out on this... Thanks in advance
Replies
1
Boosts
0
Views
246
Activity
May ’25
NWPathMonitor Failing
I need to check the network connection with NWPathMonitor. import Foundation import Network class NetworkViewModel: ObservableObject { let monitor = NWPathMonitor() let queue = DispatchQueue(label: "NetworkViewModel") @Published var isConnected = false var connectionDescription: String { if isConnected { return "You are connected." } else { return "You are NOT connected." } } init() { monitor.pathUpdateHandler = { path in DispatchQueue.main.async { self.isConnected = path.status == .satisfied } } monitor.start(queue: queue) } } import SwiftUI struct ContentView: View { @StateObject private var networkViewModel = NetworkViewModel() var body: some View { VStack { } .onAppear { if networkViewModel.isConnected { print("You are connected.") } else { print("You are NOT connected.") } } } } So there is nothing special, not at all. Yet, if I test it with a totally new Xcode project for iOS, it fails and return !isConnected. I've tested it with a macOS application. And it fails. I've tested it with an actual device. It fails. I've tested it with an old project. It still does work. I have no mere idea why new Xcode projects all fail to detect the WiFi connection. This is a total nightmare. Does anybody have a clue? thanks.
Replies
7
Boosts
0
Views
302
Activity
May ’25
Dock tile plugin and app groups
In one of my apps I use an app group to share data between the app and a command line tool. This works as expected. The app also contains a Dock Tile plugin and I wonder if there's a way to access the group container from this plugin? Thanks in advance for your help. Best regards, Marc
Replies
5
Boosts
0
Views
470
Activity
May ’25
Found a bug in ios26 UI on iphone 12
In keyboard shortcuts this buttons at the bottom are overlappin. Any one else?
Topic: UI Frameworks SubTopic: General
Replies
0
Boosts
0
Views
85
Activity
Jun ’25