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?
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.
Post
Replies
Boosts
Views
Activity
The new ios 18 UI of photos applications is the worst and so confusing. I had beta so i showed to many friends they hated it as well.
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()
}
}
}
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.
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. 😢
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?
When will SwiftUI plot will support dates on the x-axes (hrs, month, years) and when will the plot library supports logarithmic scales.
Great progress so far.
Thanks.
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.
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)
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 ?
App is Xcode swiftUI on iPad using textview. The cursor is invisible yet it moves "underneath". How to make it visible. The app textview input is button characters and coexists with a Magic Keyboard where the cursor is visible.
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.
}
I’m migrating my UIPopoverPresentationController to SwiftUI’s .popover modifier.
In doing so, I hit a stumbling block. Previously, I had used passthroughViews to avoid the popover closing on certain taps.
How could I replicate this behavior with SwiftUI?
See FB13917278 (App Becomes Unresponsive for iOS/iPadOS 18 Regular Size Class Interactions When Selecting One Particular View in Sidebar).
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.
Hi,
How to hide the Chevron icon from a list rows in SwiftUI ?
Kindest Regards
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)
}
}
}
}
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?
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
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.