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

Post

Replies

Boosts

Views

Activity

The button click for real-time activity did not work.
We added a button in the real-time activity that responds within the app upon clicking. Now we're encountering an issue where, if you immediately click this button after swiping down to enter the notification center, it only opens the app without any scheme response. You have to wait for about 1 second after swiping down before the button can respond normally. Could you please tell us why this is happening?
0
0
12
6h
Handling of dates with no value when creating a date bar chart in Charts
Some data have skipped dates, as in the following data. TrainingSession(date: formatter.date(from: "2024-05-12 07:37:30 +0000")!, maxRM: 10.0, totalVolume: 0.0), TrainingSession(date: formatter.date(from: "2024-06-01 15:00:00 +0000")!, maxRM: 10.5, totalVolume: 105.0), TrainingSession(date: formatter.date(from: "2024-06-03 15:00:00 +0000")!, maxRM: 10.0, totalVolume: 100.0) In this case, the graph shows nothing for the corresponding date as shown in the image. s it possible to create a continuous graph by displaying only the data with values and not the dates with no values? The source code is as follows // ContentView.swift // GraphSample // // Created by 齋藤卓馬 on 2024/06/09. // import SwiftUI import Charts struct TrainingSession { var date: Date var maxRM: Double var totalVolume: Double } struct GraphView: View { var sessions: [TrainingSession] var body: some View { ScrollView { VStack(alignment: .leading) { // 最大RMのグラフ VStack(alignment: .leading) { Text("最大RM") .font(.headline) .padding() Chart(sessions, id: \.date) { session in BarMark( x: .value("Date", session.date), y: .value("Max RM", session.maxRM) ) } .chartXAxis { AxisMarks(values: .stride(by: .day, count:7)) // 日付の表示間隔を調整 } .chartScrollableAxes(.horizontal) // 横スクロールを有効にする .padding([.leading, .trailing, .bottom]) } // 総負荷量のグラフ VStack(alignment: .leading) { Text("総負荷量") .font(.headline) .padding() Chart(sessions, id: \.date) { session in BarMark( x: .value("Date", session.date), y: .value("Total Volume", session.totalVolume) ) } .chartXAxis { AxisMarks(values: .stride(by: .day, count:7)) // 日付の表示間隔を調整 } .chartScrollableAxes(.horizontal) // 横スクロールを有効にする .padding([.leading, .trailing, .bottom]) } } } } } struct ContentView: View { var body: some View { GraphView(sessions: sampleData) } var sampleData: [TrainingSession] { let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z" return [ TrainingSession(date: formatter.date(from: "2024-05-12 07:37:30 +0000")!, maxRM: 10.0, totalVolume: 0.0), TrainingSession(date: formatter.date(from: "2024-06-01 15:00:00 +0000")!, maxRM: 10.5, totalVolume: 105.0), TrainingSession(date: formatter.date(from: "2024-06-03 15:00:00 +0000")!, maxRM: 10.0, totalVolume: 100.0) ] } } struct MyApp: App { var body: some Scene { WindowGroup { ContentView() } } }
2
0
135
2w
Creating a navigation link within a chart?
I’d like to create a simple Gantt chart where each horizontal BarMark is a navigation link to a detail view. When I embed a navigation link within a chart, I get the error “Static method 'buildExpression' requires that 'some ChartContent' conform to 'View’” NavigationLink(value: taskGroup) { BarMark( xStart: .value("Start", taskGroup.start), xEnd: .value("End", taskGroup.end), y: .value("Event", taskGroup.taskGroupName), height: barHeight ) } I could use a chart overlay and manage the navigation from there, but it appears I can only grab published chart data at a given tap gesture. I need the object itself to inject into the detail view (in this case TaskGroup) and the data I’m plotting in the chart isn’t unique - so no obvious way to identify which TaskGroup the user tapped.
3
0
230
2w
How can Charts display sales data for a full month and support monthly paging?
Due to the varying number of days in each month, I am unsure how to enable monthly paging in Charts. In Apple's official example, SwiftChartsExample, there is only an example showing the sales of the "last 30 days": .chartXVisibleDomain(length: 3600 * 24 * 30) I have tried using scrollPosition to calculate the number of days in the current month, like this: var days: Int { let current = Calendar.current let dateRange = current.range(of: .day, in: .month, for: scrollPosition) return dateRange?.count ?? 0 } ... .chartXVisibleDomain(length: 3600 * 24 * days) ... .chartScrollPosition(x: $scrollPosition) ... But I found that it does not work as expected. 😢
2
0
181
3w
SwiftUI chart - take screenshot of the chart view on macOS
Hello all, if I enable the .chartScrollableAxes(.horizontal) and .chartXVisibleDomain(length: length) for a chart view to zoom in the screenshot of the view misses the graphs. I use this extension: `extension View { @MainActor func snapshot() { let renderer = ImageRenderer(content: self) if let exportImage = renderer.nsImage { let pasteboard = NSPasteboard.general pasteboard.clearContents() pasteboard.writeObjects([exportImage]) } } }` The screenshot is taken with: Button("Snap") { let view = ChartView(text: $statusText, length: $chartLength) .padding() .frame(width: 1500, height: 500) view.snapshot() } If I omit .chartScrollableAxes(.horizontal) the snapshot is ok and the graphs are visible in the image but then a zoom is not possible and the whole range is shown. Any ideas?
1
1
239
Apr ’24
quickLookPreview keyboard issues on macOS
I'm trying to add QuickLook previews to a SwiftUI app which uses Table(). I've added the .quickLookPreview() modifier to my Table(), and added a menu command for invoking it, and if I select that menu item manually, it works fine, but I have two keyboard related issues which are making it difficult to actually ship this functionality: When using the .quickLookPreview() variant for a set of URLs, keyboard navigation between the quicklook previews only works with left/right arrows, but being invoked by a Table, it would make much more sense for up/down arrows to navigate through the previews I set a .keyboardShortcut() on the menu command to use Space, since that's the normally-expected shortcut for quicklook, and it doesn't work. If I set it to some random other key (like "a") it does work, but .space doesn't do anything.
2
0
27
3h
Deep Link to Files app
Is there a system deep link URI to the built in files app? I would like to direct users to my apps location in the files app. For example files://myApp The only exposed deep links for system I can find are the ones for mail, sms, FaceTime etc. Thank you (tag used for post was because I couldn’t find a deep link tag)
3
0
243
May ’24
View appears transparent over tableView, whatever alpha channel
I have a view in storyboard, with a tableView and a coloured UIView. The UIView is declared after tableView, so it appears on top of tableView. However, it appears semi transparent over the tableView. In addition, I cannot set its alpha channel to values other than 1 or 0 (e.g., 0.9) But if I create the view programmatically, the view if fully opaque as expected. What am I missing ?
1
0
516
Dec ’23
SwiftData Update Item View from Background Thread
I have a background thread that is updating a swift data model Item using a ModelActor. The background thread runs processing an Item and updates the Item's status field. I notice that if I have a view like struct ItemListView: View { @Query private var items: [Items] var body: some View { VStack { ForEach(items) { item in ItemDetailView(item) } } } } struct ItemDetailView: View { var item: Item var body: some View { // expected: item.status automatically updates when the background thread updates the `Item`'s `status`. Text(item.status) // actual: This text never changes } } Then background updates to the Item's status in SwiftData does not reflect in the ItemDetailView. However, if I inline ItemDetailView in ItemListView like this: struct ItemListView: View { @Query private var items: [Items] var body: some View { VStack { ForEach(items) { item in // Put the contents of ItemDetailView directly in ItemListView Text(item.status) // result: item.status correctly updates when the background thread updates the item. } } } } Then the item's status text updates in the UI as expected. I suspect ItemDetailView does not properly update the UI because it just takes an Item as an input. ItemDetailView would need additional understanding of SwiftData, such as a ModelContext. Is there a way I can use ItemDetailView to show the Item's status and have the UI show the status as updated in the background thread? In case details about my background thread helps solve the problem, my thread is invoked from another view's controller like @Observable class ItemCreateController { func queueProcessingTask() { Task { let itemActor = ItemActor(modelContainer: modelContainer) await itemActor.setItem(item) await itemActor.process() } } } @ModelActor actor ItemActor { var item: Item? func setItem(_ item: Item) { self.item = modelContext.model(for: item.id) as? Item } func process() async { // task that runs processing on the Item and updates the Item's status as it goes. }
0
0
68
19h
UIGraphicsImageRenderer memory issue (iOS 17.5.1)
Testing on iPhone 12 mini, I have encountered a weird situation. I am try to take snapshot of my view, which works fine but the memory is never released after the snapshot is taken. func screenshot(view: UIView, scale:Double) -> URL? { guard let containerView = view.superview, let containerSuperview = containerView.superview else { return nil } let rendererFormat = UIGraphicsImageRendererFormat() rendererFormat.scale = scale var renderer = UIGraphicsImageRenderer(bounds: containerView.frame, format: rendererFormat) let image = autoreleasepool { return renderer.image { context in containerSuperview.drawHierarchy(in: containerSuperview.layer.frame, afterScreenUpdates: true) //memory hog starts from here } } guard let data = image.heicData() else { return nil } //more code to save data to file URL and return it } initially it appears to work normally but as soon as I change the scale: rendererFormat.scale = 10 I can see a spike in memory but the problem is then the memory is never released even after the image is saved. so initially, the app uses: 35MB memory -> when processing the memory usage jumps to expected 250MB to 300MB to process large image -> after processing the memory goes down to around 90MB to 120MB but it never really returns to it's original 35MB state. Is this a bug or this is expected? If this is expected behaviour then is there any low level API to free the memory after it's job is done.
0
0
63
1d
scrollPosition(id:anchor:) freeze UI when show/hide keyboard
Hello ! This will be my first blog post. I hope I will find the solution. So, I try to use the new iOS 17+ API for ScrollView. I have an array of messages that I want to show in scroll view. And I need to scroll to bottom when I tap to Send button. When I use scrollPosition(id:anchor:), it freeze the UI. The link to the screencast to demonstrate. I think the problem might be the keyboard when it shows and hides. But I can't understand what can I do. struct ChatView: View { @ObservedObject var viewModel: CoachViewModel @State private var scrollTo: Message.ID? var body: some View { ScrollView { LazyVStack { ForEach(viewModel.messages) { message in MessageView(viewModel: viewModel, message: message) } } .scrollTargetLayout() } .scrollPosition(id: $scrollTo) .background(.primaryBackground) .onChange(of: viewModel.scrollToBottom) { if $1, let lastMessage = viewModel.messages.last { withAnimation { scrollTo = lastMessage.id } viewModel.scrollToBottom = false } } } } struct Message: Identifiable, Hashable { let id: UUID let author: MessageAuthor let text: String } final class CoachViewModel: ObservableObject { @Published var messageTextInput = "" @Published var scrollToBottom = false @Published var messages: [Message] = [...] // ... more code ... func sendMessage() { messages.append( .init( id: .init(), author: .user, text: messageTextInput ) ) messageTextInput.removeAll() scrollToBottom = true } } struct CoachView: View { @StateObject private var viewModel = CoachViewModel() @State private var isSearching = false var body: some View { VStack(spacing: 0) { Group { CoachTitleView(viewModel: viewModel, isSearching: $isSearching) ChatView(viewModel: viewModel) } .onTapGesture { UIApplication.shared.endEditing() } if isSearching { MatchboxView(viewModel: viewModel) } else { InputTextFieldView(viewModel: viewModel) } } } }
0
0
56
1d
View with 2 labels of dynamic height
Hello, I try to do the same as the UIListContentConfiguration. Because I want to have a UITableViewCell with an image at beginning, then 2 Labels and an image at the end (accessoryView/Type should also be usable). I also want to have the dynamic behavior of the two labels, that if one or both of them exceeds a limit, that they are put under each under. But I cannot use the UIListContentConfiguration.valueCell, because of the extra image at the end. So I have tried to make a TextWrapper as an UIView, which contains only the two UILabels and the TextWrapper should take care of the dynamic height of the UILabels and put them side to side or under each other. But here in this post Im only concentrating on the issue with the labels under each other, because I have managed it to get it working, that I have two sets of Constraints and switch the activeStatus of the constraints, depending on the size of the two labels. But currently only the thing with the labels under each under makes problems. Following approaches I have tried for the TextWrapper: Using only constraints in this Wrapper (results in ambiguous constraints) Used combinations of constraints + intrinsicContentSize (failed because it seems that invalidateIntrinsicContentSize doesn't work for me) Approach with constraints only Following code snippet results in ambiguous vertical position and height. Because I have 3 constraints (those with the defaultHigh priorities). class TextWrapper: UIView { let textLabel = UILabel() let detailLabel = UILabel() init() { super.init(frame: .zero) self.addSubview(self.textLabel) self.addSubview(self.detailLabel) self.textLabel.numberOfLines = 0 self.detailLabel.numberOfLines = 0 self.directionalLayoutMargins = .init(top: 8, leading: 16, bottom: 8, trailing: 8) self.translatesAutoresizingMaskIntoConstraints = false self.textLabel.translatesAutoresizingMaskIntoConstraints = false self.detailLabel.translatesAutoresizingMaskIntoConstraints = false // Content Size self.textLabel.setContentCompressionResistancePriority(.required, for: .vertical) self.detailLabel.setContentCompressionResistancePriority(.required, for: .vertical) // Constraints self.textLabel.leadingAnchor.constraint(equalTo: self.layoutMarginsGuide.leadingAnchor).isActive = true self.textLabel.topAnchor.constraint(equalTo: self.layoutMarginsGuide.topAnchor).constraint(with: .defaultHigh) self.textLabel.widthAnchor.constraint(lessThanOrEqualTo: self.layoutMarginsGuide.widthAnchor).isActive = true self.detailLabel.leadingAnchor.constraint(equalTo: self.layoutMarginsGuide.leadingAnchor).isActive = true self.detailLabel.topAnchor.constraint(equalTo: self.textLabel.bottomAnchor, constant: 2).constraint(with: .defaultHigh) self.detailLabel.bottomAnchor.constraint(equalTo: self.layoutMarginsGuide.bottomAnchor).constraint(with: .defaultHigh) self.detailLabel.widthAnchor.constraint(lessThanOrEqualTo: self.layoutMarginsGuide.widthAnchor).isActive = true } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } Approach with intrinsicContentSize Pretty similar to the above, with only difference that I invalidate the intrinsicContentSize in the layoutSubviews, because at the first call of the intrinsicContentSize the width of the View is zero. I also tried different things like setNeedsLayout with layoutIfNeeded but nothing really works. After I invalidate the intrinsicContentSize in the layoutSubviews the intrinsicContentSize is called with the correct width of the View and calculates the correct height, but the TableView doesn't update the height accordingly. class TextWrapper: UIView { let textLabel = UILabel() let detailLabel = UILabel() init() { super.init(frame: .zero) self.addSubview(self.textLabel) self.addSubview(self.detailLabel) self.textLabel.numberOfLines = 0 self.detailLabel.numberOfLines = 0 self.directionalLayoutMargins = .init(top: 8, leading: 16, bottom: 8, trailing: 8) self.translatesAutoresizingMaskIntoConstraints = false self.textLabel.translatesAutoresizingMaskIntoConstraints = false self.detailLabel.translatesAutoresizingMaskIntoConstraints = false // Content Size self.textLabel.setContentCompressionResistancePriority(.required, for: .vertical) self.detailLabel.setContentCompressionResistancePriority(.required, for: .vertical) // Constraints self.textLabel.leadingAnchor.constraint(equalTo: self.layoutMarginsGuide.leadingAnchor).isActive = true self.textLabel.topAnchor.constraint(equalTo: self.layoutMarginsGuide.topAnchor).constraint(with: .defaultHigh) self.textLabel.widthAnchor.constraint(lessThanOrEqualTo: self.layoutMarginsGuide.widthAnchor).isActive = true self.detailLabel.leadingAnchor.constraint(equalTo: self.layoutMarginsGuide.leadingAnchor).isActive = true self.detailLabel.topAnchor.constraint(equalTo: self.textLabel.bottomAnchor, constant: 2).constraint(with: .defaultHigh) self.detailLabel.widthAnchor.constraint(lessThanOrEqualTo: self.layoutMarginsGuide.widthAnchor).isActive = true } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override var intrinsicContentSize: CGSize { let maxLabelWidth = self.bounds.width guard maxLabelWidth > 0 else { // The first time it has a width of 0, so we are giving a default height in this case, to dont produce a error in TableView return CGSize(width: UIView.noIntrinsicMetric, height: 44) } let textLabelSize = self.textLabel.sizeThatFits(CGSize(width: maxLabelWidth, height: .greatestFiniteMagnitude)) let detailLabelSize = self.detailLabel.sizeThatFits(CGSize(width: maxLabelWidth, height: .greatestFiniteMagnitude)) let totalHeight = textLabelSize.height + detailLabelSize.height + 16 return CGSize(width: UIView.noIntrinsicMetric, height: totalHeight) } override func layoutSubviews() { super.layoutSubviews() self.invalidateIntrinsicContentSize() } I also tried to use the intrinsicContentSize with only layoutSubviews, but this haven't worked also. Does anybody have ran into such issues? And know how to fix that?
2
0
53
2d
SwiftUI SideMenu Navigation Issue
I am currently refactoring my app's side menu to be more like Twitter's. I have the UI down in terms of how the side menu looks and appears, but the issue is navigating to a view from the side menu. The views that a user can go to from the side menu are a mix of SwiftUI views & UIKit View Controllers. As of right now, when a user navigates to a view from the side menu, it presents it modally as a sheet. I want it to have regular navigation, where the user goes to the view displayed in full screen and can tap on the back button to go back to the previous view. Here is the associated code: SideMenuView.swift SideMenuViewModel.swift How can I modify the navigation logic to be like Twitter's? I've been stuck for days trying to find a fix but it has been a struggle.
0
0
91
1d
Questions Tags Saves Users Companies LABS Jobs Discussions COLLECTIVES Communities for your favorite technologies. Explore all Collectives TEAMS Ask questions, find answers and collaborate at work with Stack Overflow for Teams. Looking for your
0 I'm trying to make a list of trips that a person has gone on, and when someone has no trips in their list, it will display a ContentUnavailableView with a NavigationLink to take them to a new view. I am encountering strange issues when using the ContentUnavailableView with the NavigationLink, such as the back button being unaligned and not being able to swipe back to the previous view. I expected the ContentUnavailableView to link without any of these issues. Any guidance would be greatly appreciated.
0
0
64
1d