I use the effect in the picture to do the test, I want to achieve a habit of multiple punch card effect, click to complete a punch card, long press to cancel a punch card.
I'm having a problem right now. I want the long press gesture to only work on the trash icon, not extend to the entire item, causing the entire item to be highlighted.
What should I do about it? I tried a lot of methods, but I didn't achieve the effect.
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Posts under SwiftUI tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I'm building a SwiftUI+RealityKit app for visionOS, macOS and iOS. The main UI is a diorama-like 3D scene which is shown in orthographic projection on macOS and as a regular volume on visionOS, with some SwiftUI buttons, labels and controls above and below the RealityView.
Now I want to add UI that is positioned relative to some 3D elements in the RealityView, such as a billboarded name label over characters with a "show details" button and such.
However, it seems the whole RealityView Attachments API is visionOS only? The types don't even exist on macOS. Why is it visionOS only? And how would I overlay SwiftUI elements over a RealityView using SwiftUI code on macOS if not with attachments?
Hi! We added Spanish to the String Catalog. Turned out there are a lot of changes we should make to already localized text. How can we temporarily turn off / disable this language to fix all issues and then turn on Spanish support again?
Thank you!
Hi all,
Very new to this. Just getting into swift data, and am frustrated with the canvas not working with modelContainers in SwiftData. My understanding is that they work if inMemory = true, but not in the default case where data is persistent after an app is quit.
Can anyone tell me if it is possible to conditionally create the modelContainer type based on a flag... If Bool:Canvas then inMemory = True, Else False... Then using this flag for all data models so my list views populate on the canvas, without having to run the simulator each time... I would assume you could also pre-populate the inMemory option if it is empty also...
Or is there a simple and obvious solution that I am oblivious to.
If it is possible, is it worth the time, hassle, and any possible issues?
crash log
Anyone can understand the log? I really don't understand.
Please see the attachment crash and help to resolve it, thanks very much.
Hi,
When closing a WindowGroup, I want to show a prompt, and only dismiss the window when the user confirms.
How to do it?
WindowGroup(id: "A") {
ContentView()
}
Hi everyone,
I’m having trouble getting the correct horizontal slide transitions when navigating between multiple screens in my SwiftUI app. I have three screens (enum cases with an int assigned as index depending on the navigation order): .checkClient (index 0), .login(document: String) (index 1), and .register (index 2).
My goal is:
When moving forward (e.g., from .checkClient to .login, or from .login to any other with a greater index), the new screen should enter from the right (trailing) and the old one should exit to the left (leading).
When going backward (from .register back to .checkClient, for example), the new screen should enter from the left (leading) and the old one should exit to the right (trailing).
I’ve been using a state property isAdvancing to determine the direction of transitions (I use TCA, so my logic is in a Reducer body, my properties in a State and my views are normal SwiftUI Views):
case .updateCurrentScreen(let newScreen):
state.isAdvancing = newScreen.index > state.currentScreen.index
state.currentScreen = newScreen
return .none
I tried applying .transition directly inside each case:
.transition(
.asymmetric(
insertion: .move(edge: store.isAdvancing ? .trailing : .leading),
removal: .move(edge: store.isAdvancing ? .leading : .trailing)
)
)
This works correctly the first time I navigate forward. However, when I go to the .register screen and then hit back, the directions become inconsistent. Sometimes the removal happens in the wrong direction, and after returning to .checkClient, forward navigations stop working as intended.
Then, I tried placing the transition at a higher level, wrapping the switch in a ZStack and using a single .transition(...) outside:
ZStack {
switch store.currentScreen {
case .checkClient:
StartView(...)
case .login:
LoginView(...)
case .register:
RegisterView(...)
}
}
.transition(
.asymmetric(
insertion: .move(edge: store.isAdvancing ? .trailing : .leading),
removal: .move(edge: store.isAdvancing ? .leading : .trailing)
)
)
.animation(.easeInOut, value: store.currentScreen)
But doing this results in some transitions reverting to a fade instead of a horizontal slide.
I’ve also tried ensuring that isAdvancing updates before changing the currentScreen. Unfortunately, I still encounter inconsistent transitions when navigating back and forth between these screens.
Here is my complete view logic (even though is not finished nor polished yet):
var body: some View {
WithPerceptionTracking {
ZStack {
AdaptiveSheetView(
backgroundImage: Asset.AuthorizationDomain.background,
hasBackButton: store.showsBackButton,
isFullScreen: store.isFullScreen,
backAction: {
store.send(.goBack)
}
) {
if store.showsIATILogo {
Image(asset: Asset.iatiLogo)
.padding(spacing: .medium)
}
ZStack {
switch store.currentScreen {
case .checkClient:
StartView(store: store.scope(state: \.startState, action: \.startAction))
case .login:
if let newStore = store.scope(state: \.loginState, action: \.loginAction) {
LoginView(store: newStore)
}
case .register:
if let newStore = store.scope(state: \.registerState, action: \.registerAction) {
RegisterView(store: newStore)
}
}
}
.transition(
.asymmetric(
insertion: .move(edge: store.isAdvancing ? .trailing : .leading),
removal: .move(edge: store.isAdvancing ? .leading : .trailing)
)
)
}
.animation(.easeInOut, value: store.currentScreen)
if store.startState.checkUser == .loading { LoadingSpinner() }
PreloadView(store: store.scope(state: \.preloadState, action: \.preloadAction))
.opacity(store.preloadViewShown ? 1.0 : 0.0)
.animation(.linear(duration: 0.5), value: store.preloadViewShown)
.onChange(of: store.preloadViewShown) { shown in
if !shown { store.send(._checkPreviousSessions) }
}
}
}
}
Has anyone experienced similar issues or found a reliable pattern for achieving these “push/pop” style transitions in SwiftUI? Any guidance would be greatly appreciated!
My minimum target is iOS 16, so I can not make use of TabView with paginated style for this AFAIK.
Thanks in advance for any time and attention you dedicate to me 🙏🏼
Hey I wanted to see what this mean (Thread 1: SwiftUI Body (1)). It pops up every time I run my app. When it comes to the navigation view and typing in a login. The app freezes and, stops the animation. Does anyone know how to fix this?
Hello. I’ve encountered a strange issue with TimelineView and wanted to report it.
The following code runs without any problems:
// Example 1.
struct ContentView: View {
var body: some View {
TimelineView(.everyMinute) { _ in
List {
TimelineView(.everyMinute) { _ in
Text("Hello")
}
}
}
}
}
However, the code below causes the CPU usage to spike to 100%, and the screen displays a blank view:
// Example 2.
struct ContentView: View {
var body: some View {
TimelineView(.everyMinute) { _ in
List {
TimelineView(.everyMinute) { _ in
text
}
}
}
}
var text: some View {
Text("Hello")
}
}
The same issue occurs with the following code:
// Example 3.
struct MyTextView: View {
var body: some View {
Text("Hello")
}
}
struct ContentView: View {
var body: some View {
TimelineView(.everyMinute) { _ in
List {
TimelineView(.everyMinute) { _ in
MyTextView()
}
}
}
}
}
Replacing List with LazyVStack and ForEach resolves the hang issue, but I need to use List because I rely on the swipeActions().
Does anyone have insights or suggestions on how to address this issue?
When using conformance to ObservableObject and then doing async work in a Task, you will get a warning courtesy of Combine if you then update an @Published or @State var from anywhere but the main thread. However, if you are using @Observable there is no such warning.
Also, Thread.current is unavailable in asynchronous contexts, so says the warning. And I have read that in a sense you simply aren't concerned with what thread an async task is on.
So for me, that begs a question. Is the lack of a warning, which when using Combine is rather important as ignoring it could lead to crashes, a pretty major bug that Apple seemingly should have addressed long ago? Or is it just not an issue to update state from another thread, because Xcode is doing that work for us behind the scenes too, just as it manages what thread the async task is running on when we don't specify?
I see a lot of posts about this from around the initial release of Async/Await talking about using await MainActor.run {} at the point the state variable is updated, usually also complaining about the lack of a warning. But ow years later there is still no warning and I have to wonder if this is actually a non issue. On some ways similar to the fact that many of the early posts I have seen related to @Observable have examples of an @Observable ViewModel instantiated in the view as an @State variable, but in fact this is not needed as that is addressed behind the scenes for all properties of an @Observable type.
At least, that is my understanding now, but I am learning Swift coming from a PowerShell background so I question my understanding a lot.
Topic:
App & System Services
SubTopic:
Processes & Concurrency
Tags:
Concurrency
Swift
SwiftUI
Combine
Wrapping views with a VStack breaks animation, but using an extension to do the same thing fixes it.
I was having issues with views transitioning between being visible and not visible inside of List. They would appear, but the animation would be jerky. I switched to using a Section, and the animation looked much better. However, the spacing between views and padding wasn't what I wanted. So I wrapped some of the views inside the Section with a VStack.
But first, this is how my view SectionView looks:
struct SectionView<Content: View>: View {
let title: String
@ViewBuilder var content: () -> Content
var body: some View {
Section {
Text(title)
.font(.title3.bold())
content()
}
.listRowInsets(EdgeInsets(top: 10, leading: 20, bottom: 10, trailing: 20))
.listRowBackground(Color.clear)
.listRowSeparator(.hidden)
.contentShape(.rect)
}
}
Below was in a separate view:
SectionView(title: "Title") {
Group {
HStack {
// Stuff here
}
if let selectedMonth {
VStack(alignment: .leading, spacing: 10) {
// Stuff here
}
}
}
.animation(.smooth, value: selectedMonth)
}
This, however, broke the animations again when the VStack appears. It went back to being jerky. So instead of wrapping the content inside of a VStack, I created an extension to do the same thing.
extension View {
@ViewBuilder
func condensed() -> some View {
VStack(alignment: .leading, spacing: 10, content: {
self
})
}
}
So now instead of wrapping it in a VStack, I do this:
if let selectedMonth {
Group {
// Stuff here
}
.condensed()
}
The animations look good again. I just can't figure out why that is. Can anyone help me understand this?
My picker looks like this:
Picker("Color", selection: $backgroundColor.animation(), content: {
ForEach(TransactionCategory.Colors.allCases, id: \.self) { color in
Text(color.rawValue)
.tag(color)
.foregroundStyle(color.getColor())
}
})
This changes a tint color which is applied to the entire tabview. I can see that it's working because the buttons in the top tab bar are changing color as I change the picker value. However, the color of the text inside the picker is not changing until I go back one view and then come back to this view. I tried setting an ID on the picker and then updating it when the picker value changes, but that didn't work.
Any ideas?
This is a reproducible issue, create a blank project and put a cell inside a scrollview lazyVstack, I need to have the confirmation dialog on the button or else on iPad it will crash but having the .confirmationDialog inside the lazyVstack leads to unexpected behavior. If you try to click through the cells from 1-10 the .confirmationDialog will stop working after a few taps on the cells. Not sure what the workaround is I'm trying to do something similar in my app with post cells and it's just not working well. I've also noticed that a similar thing happens with .alert if you have it inside the LazyVStack.
struct ContentView: View {
var body: some View {
ScrollView {
LazyVStack {
ForEach(0..<10) { number in
cell(number: number)
}
}
}
}
}
struct cell: View {
@State private var isShowingDialog: Bool = false
let number : Int
var body : some View {
Button {
print("Tapped Cell")
isShowingDialog.toggle()
} label: {
Text("\(number)")
.frame(height: 200)
.frame(maxWidth: .infinity)
.border(.black)
}
.padding(.horizontal, 16)
.confirmationDialog("Options", isPresented: $isShowingDialog, titleVisibility: .visible) {
Button("Some Button", role: .destructive) {
print("Did Tap Option Button")
}
Button("Some Other Button") {
print("Did Tap Other Option Button")
}
}
}
}
Hi, need some help with an iOS application we are trying to make future safe. Basically, we know that our app would require SwiftUI so the app is made in that framework, however we require some important elements that are available only in UIKit, so we've made a bridge that allows us to pass UIKit views to SwiftUI to display them. So most of the app actually has UI made in UIKit, however, we now need to use the Charts framework present in SwiftUI, we've used SwiftUI buttons in our UIKit before by passing them through a HostingController (Passing SwiftUI buttons to UIKit to use). And we are currently considering to the same for SwiftUI Charts. Just to recap, it's a SwiftUI iOS app, that is mostly made in UIKit (through a bridge) but also has other SwiftUI elements injected into it. What we want to know that, is this the best way to do this? Or is there a better way to have UIKit and SwiftUI work more comfortably with eachother. The reason for such looping around is also because we interoping our C++ code to Swift for making this application, since we are making it for many other platforms and the business logic is in C++. Let me know if there are better ways to go about this!
I have ran into an issue that is illustrated by the code in the following GitHub repository.
https://github.com/dougholland/ColorTest
When a SwiftUI color originates from the ColorPicker it can be persisted correctly and renders the same as the original color. When the color originates from the MapFeature.backgroundColor, it is always rendered with the light appearance version of the color and not the dark appearance version. The readme in the GitHub repo has screenshots that show this.
Any assistance would be greatly appreciated as this is affecting an app that is in development and I'd like to resolve this before the app is released.
If this is caused by a framework bug, any possible workaround would be greatly appreciated also. I suspect it maybe a framework issue, possibly with some code related to the MapFeature.backgroundColor, because the issue does not occur when the color originates from the ColorPicker.
Hi,
I'm trying to build iOS app, but I found out that .onPreferenceChange has strange behaviour if the view contains an if statement below view which sets .preference.
Here is an repository with minimal reproduction: https://github.com/Mordred/swiftui-preference-key-bug
There should be displayed title text on the top and bottom of the screen. But the bottom is empty.
If you delete if statement if true { at https://github.com/Mordred/swiftui-preference-key-bug/blob/main/PreferenceKeyBug/PreferenceKeyBug.swift then it works fine.
Are there any differences (either performance or memory considerations) between removing an array of model objects directly using .removeAll() vs using modelContext? Or, are they identical?
Attached below is an example to better illustrate the question (i.e., First Way vs Second Way)
// Model Definition
@Model
class GroupOfPeople {
let groupName: String
@Relationship(deleteRule: .cascade, inverse: \Person.group)
var people: [Person] = []
init() { ... }
}
@Model
class Person {
let name: String
var group: GroupOfPeople?
init() { ... }
}
// First way
struct DemoView: View {
@Query private groups: [GroupOfPeople]
var body: some View {
List(groups) { group in
DetailView(group: group)
}
}
}
struct DetailView: View {
let group: GroupOfPeople
var body: some View {
Button("Delete All Participants") {
group.people.removeAll()
}
}
// Second way
struct DemoView: View {
@Query private groups: [GroupOfPeople]
var body: some View {
List(groups) { group in
DetailView(group: group)
}
}
}
struct DetailView: View {
@Environment(\.modelContext) private var context
let group: GroupOfPeople
var body: some View {
Button("Delete All Participants") {
context.delete(model: Person.self, where: #Predicate { $0.group.name == group.name })
} // assuming group names are unique. more of making a point using modelContext instead
}
I am developing a library for RichTextEditor for SwiftUI, and I am facing issues with implementing NSParagraphStyle related features like nested bullet lists and text alignment. I have searched a lot and personally feel that the documentation is not enough on this topic, so here I want to discuss how we can achieve the nested list with UI/NSTextView and natively available NSTextList in NSParagraphStyle.textLists. The problem is I am not able to understand how I can use this text list and how to manage adding list and removing list with my editor
I have seen code that work adding attributes to each string and then merge them, but I don't want that, I want to add/update/remove attributes from selected text and if text is not selected then want to manage typing attributes to keep applied attributes to current position
I'm playing around with using an app to automate some of my personal work flows, and one of the things I wanted to do was to be able to drag a .webloc file onto my app icon in the dock, to launch it.
I've got public.data set up as a document type for it in Xcode, which translated to
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Default</string>
<key>LSItemContentTypes</key>
<array>
<string>public.data</string>
</array>
</dict>
</array>
in the Info.plist for it, which seems correct. When I drag a .webloc file onto the Dock icon, it appears to be willing to accept it, but nothing seems to happen.
In the app, I've got an AppDelegate.swift file which has
extension Notification.Name {
static let receivedURLsNotification = Notification.Name("ReceivedURLsNotification")
}
class AppDelegate: NSObject, NSApplicationDelegate {
func application(_ application: NSApplication, open urls: [URL]) {
guard !urls.isEmpty else { return }
NotificationCenter.default.post(name: .receivedURLsNotification, object: nil, userInfo: ["URLs": urls])
}
}
(I copied it almost verbatim from a Medium post.)
In the app swift file, I have
@main
struct LoggerApp: App, DropDelegate {
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
I set a breakpoint on application(_:NSApplication, open:[URL]), and did my drag, and the breakpoint never triggered.
I added the application(didFinishLaunching(_:Notification) method, and that does get invoked when the app launches, so the app delegate does seem to be working. That seems to indicate the problem is somewhere else?
Hi, I have pretty much finished my app's layout but realized I needed to scale it for different devices. I have read online that hardcoding values (esp in frames) is a big no-no, and GeometryReader should be heavily utilized. Also was recommended ViewThatFits. The problem is, I want the app to look the exact same across all devices. What is the best way to get started?
Also, when testing, do I only have to test on an iPad and iPhone or are the dimensions significantly different amongst each class of devices?