Post

Replies

Boosts

Views

Activity

Is there any plans to isolate alignmentGuide's computeValue closure?
Hello. I am developing an application using Swift 6 and SwiftUI. I have custom implemented a BottomSheet that animates from bottom to top, and I attempted to achieve this animation by changing the alignmentGuide like this. ZStack(alignment: .bottom) { dimView .opacity(isVisible ? 1 : 0) .transaction { transaction in transaction.animation = .easeInOut(duration: 0.35) } bottomSheetView .alignmentGuide(VerticalAlignment.bottom) { dimension in // compile error occur because isVisible property is state of MainActor isolated View! isVisible ? dimension[.bottom] : dimension[.top] } } There were no issues in Swift 5, but now I am encountering compile errors because the computeValue closure of the alignmentGuide is not isolated to the MainActor, preventing me from calling view state values or functions. So I am curious if there are any plans to isolate this closure to the MainActor. From my observation, this closure is always called on the main thread. Thank you.
1
0
420
Dec ’24
Setting multiple alignment guides in SwiftUI behaves strangely
Hello. Recently, while studying alignmentGuide, I had questions about it behaving differently from the documentation when setting multiple alignment guides. For example, the document states that only the alignmentGuide modifier with a first parameter matching the container's alignment will function. Therefore, I thought that writing the Swift code below would result in the yellow color's center alignment being aligned with the HStack's bottom alignment. struct TestView: View { var body: some View { HStack(alignment: .bottom) { Color.yellow .frame(height: 50) .alignmentGuide(VerticalAlignment.center) { dim in dim[.top] } .alignmentGuide(VerticalAlignment.top) { dim in dim[.bottom] } .alignmentGuide(VerticalAlignment.bottom) { dim in dim[VerticalAlignment.center] } Text("Hello, world") } .border(.green) } } Expect However, in reality, I observed that the top of the yellow color aligns with the HStack's bottom alignment. From this, I inferred that the 3rd alignmentGuide is applied first, and this also causes the first alignmentGuide to work, which makes me curious about how this is possible. If I leave only the 3rd alignmentGuide, it behaves as I expected. Real Behavior Could anybody help me to figure it out this behavior? Thank you
1
0
372
Dec ’24
Crash occur with "Attempting to attach window to an invalidated scene" message
Hello. Recently, our app has been experiencing crashes with the message 'Attempting to attach window to an invalidated scene' when creating a UIWindow. Our code stores the UIWindowScene provided in the scene(:willConnectTo:options:) function in a global variable and does not change the set scene until the scene(:willConnectTo:options:) function is called again. Additionally, we do not perform any actions related to the disconnect event. func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } hudManager.setup(windowScene: windowScene) // ... } func sceneDidDisconnect(_ scene: UIScene) { // do nothing } In all crash logs, the activationState of the WindowScene is "unattached", so I initially thought that creating a UIWindow with a scene in the 'unattached' state should be avoided. However, in the scene(_:willConnectTo:options:) function, the scene's state is also 'unattached', yet the UIWindow is created successfully here, which makes me think that deciding whether to create a window based on the activationState is incorrect. I did find that trying to create a UIWindow with a scene after it has been disconnected causes a crash. func sceneDidDisconnect(_ scene: UIScene) { // Crash occur here and scene's state is `unattached` let window = UIWindow(windowScene: scene as! UIWindowScene) } If the activationState alone cannot be used to determine the validity of a scene, is there another way to check the validity of a Scene? Thank you
Topic: UI Frameworks SubTopic: UIKit Tags:
1
0
384
Mar ’25
A crash occurs when fetching history when Model has preserveValueOnDeletion attribute and using inheritance
Hello, In our app, we’ve modeled our schema using inheritance introduced in iOS 26.0, and we’re implementing SwiftData History to re-fetch models only when necessary. @Model public class Transaction { @Attribute(.preserveValueOnDeletion) public var date: Date = Date() public var amount: Double = 0 public var memo: String? } @Model public final class Spending: Transaction { public var installmentIndex: Int = 1 public var installment: Int = 1 public var installmentID: UUID? } If data has been deleted from database, we need to check a date property to determine whether to re-fetch datas. To do this, we added the preserveValueOnDeletion attribute to date property so we could retrieve it from the History tombstone value. However, after adding this attribute, a crash occurs. There is a console log Could not cast value of type 'Swift.ReferenceWritableKeyPath<Shared.ModelSchemaV5.Transaction, Foundation.Date>' (0x106bf8328) to 'Swift.PartialKeyPath<Shared.ModelSchemaV5.Spending>' (0x1094f21d8). and error log attached StrictMoneyChecking-2025-11-07-105108.txt I also tried this in the recent SampleTrip app, and fetching all history after a deletion causes the same crash. Is this issue currently being worked on or under investigation?
1
0
287
Nov ’25
Combine delay & switchToLatest publisher don't emit value sometimes
Hello, I recently implemented a conditional debounce publisher using Swift's Combine. If a string with a length less than 2 is passed, the event is sent downstream immediately without delay. If a string with a length of 2 or more is passed, the event is emitted downstream with a 0.2-second delay. While writing test logic related to this, I noticed a strange phenomenon: sometimes the publisher, which should emit events with a 0.2-second delay, does not emit an event. The test code below should have all indices from 1 to 100 in the array, but sometimes some indices are missing, causing the assertion to fail. Even after observing completion, cancel, and output events through handleEvents, I couldn't find any cause. Am I using Combine incorrectly, or is there a bug in Combine? I would appreciate it if you could let me know. import Foundation import Combine var cancellables: Set<AnyCancellable> = [] @MainActor func text(index: Int, completion: @escaping () -> Void) { let subject = PassthroughSubject<String, Never>() let textToSent = "textToSent" subject .map { text in if text.count >= 2 { return Just<String>(text) .delay(for: .seconds(0.2), scheduler: RunLoop.main) .eraseToAnyPublisher() } else { return Just<String>(text) .eraseToAnyPublisher() } } .switchToLatest() .sink { if $0.count >= 2 { completion() } }.store(in: &cancellables) for i in 0..<textToSent.count { let stringIndex = textToSent.index(textToSent.startIndex, offsetBy: i) let stringToSent = String(textToSent[textToSent.startIndex...stringIndex]) subject.send(stringToSent) } } var array = [Int]() for i in 1...100 { text(index: i) { array.append(i) } } DispatchQueue.main.asyncAfter(deadline: .now() + 5) { for i in 1...100 { assert(array.contains(i)) } } RunLoop.main.run(until: .now + 10)
0
0
441
Feb ’25
PhaseAnimator doesn't reflect @Observable state changes after animation settles
I ran into a behavior with PhaseAnimator that I'm not sure is a bug or by design. I'd appreciate any insight. The Problem When an @Observable property is read only inside a PhaseAnimator content closure, changes to that property are ignored after the animation cycle completes and reaches its resting state. The UI gets stuck showing stale data. Minimal Reproduction I've put together a simple demo with two views side by side, both driven by the same ViewModel and toggled by the same button: BrokenView — receives an @Observable object and reads its property inside PhaseAnimator. After the animation completes, toggling the property has no visible effect. FixedView — receives the same value as a Bool parameter. Updates correctly every time because view's parameter has changed. import SwiftUI @Observable class ViewModel { var isError = false } struct BrokenView: View { let viewModel: ViewModel @State private var trigger = false var body: some View { VStack(spacing: 20) { Text("Broken (@Observable)").font(.headline) PhaseAnimator([false, true], trigger: trigger) { _ in if viewModel.isError { Text("Error!").foregroundStyle(.red).font(.largeTitle) } else { Text("OK").foregroundStyle(.green).font(.largeTitle) } } } .padding() .onAppear { trigger = true } } } struct FixedView: View { let isError: Bool @State private var trigger = false var body: some View { VStack(spacing: 20) { Text("Fixed (Value Type)").font(.headline) PhaseAnimator([false, true], trigger: trigger) { _ in if isError { Text("Error!").foregroundStyle(.red).font(.largeTitle) } else { Text("OK").foregroundStyle(.green).font(.largeTitle) } } } .padding() .onAppear { trigger = true } } } struct DemoView: View { @State private var viewModel = ViewModel() var body: some View { VStack(spacing: 40) { BrokenView(viewModel: viewModel) Divider() FixedView(isError: viewModel.isError) Divider() Button("Toggle isError: \(viewModel.isError)") { viewModel.isError.toggle() } .buttonStyle(.borderedProminent) } .padding() } } Run the preview, then tap the toggle button. FixedView updates instantly; BrokenView stays stuck. My Understanding It seems like PhaseAnimator only tracks @Observable access during active animation phases. Once it settles at rest, the content closure is not re-evaluated, so observation tracking is effectively lost. Passing a value type works because SwiftUI view diffing detects the input change and triggers a body re-evaluation, which in turn re-evaluates the PhaseAnimator content. Question Is this intended behavior? Or shouldn't I use phase animator in this way? I could not find any mention of this limitation in the documentation. If it is by design, it might be worth documenting — it is a subtle pitfall that is easy to miss. Thanks in advance for any input!
0
0
83
1d
Is there any plans to isolate alignmentGuide's computeValue closure?
Hello. I am developing an application using Swift 6 and SwiftUI. I have custom implemented a BottomSheet that animates from bottom to top, and I attempted to achieve this animation by changing the alignmentGuide like this. ZStack(alignment: .bottom) { dimView .opacity(isVisible ? 1 : 0) .transaction { transaction in transaction.animation = .easeInOut(duration: 0.35) } bottomSheetView .alignmentGuide(VerticalAlignment.bottom) { dimension in // compile error occur because isVisible property is state of MainActor isolated View! isVisible ? dimension[.bottom] : dimension[.top] } } There were no issues in Swift 5, but now I am encountering compile errors because the computeValue closure of the alignmentGuide is not isolated to the MainActor, preventing me from calling view state values or functions. So I am curious if there are any plans to isolate this closure to the MainActor. From my observation, this closure is always called on the main thread. Thank you.
Replies
1
Boosts
0
Views
420
Activity
Dec ’24
Setting multiple alignment guides in SwiftUI behaves strangely
Hello. Recently, while studying alignmentGuide, I had questions about it behaving differently from the documentation when setting multiple alignment guides. For example, the document states that only the alignmentGuide modifier with a first parameter matching the container's alignment will function. Therefore, I thought that writing the Swift code below would result in the yellow color's center alignment being aligned with the HStack's bottom alignment. struct TestView: View { var body: some View { HStack(alignment: .bottom) { Color.yellow .frame(height: 50) .alignmentGuide(VerticalAlignment.center) { dim in dim[.top] } .alignmentGuide(VerticalAlignment.top) { dim in dim[.bottom] } .alignmentGuide(VerticalAlignment.bottom) { dim in dim[VerticalAlignment.center] } Text("Hello, world") } .border(.green) } } Expect However, in reality, I observed that the top of the yellow color aligns with the HStack's bottom alignment. From this, I inferred that the 3rd alignmentGuide is applied first, and this also causes the first alignmentGuide to work, which makes me curious about how this is possible. If I leave only the 3rd alignmentGuide, it behaves as I expected. Real Behavior Could anybody help me to figure it out this behavior? Thank you
Replies
1
Boosts
0
Views
372
Activity
Dec ’24
Crash occur with "Attempting to attach window to an invalidated scene" message
Hello. Recently, our app has been experiencing crashes with the message 'Attempting to attach window to an invalidated scene' when creating a UIWindow. Our code stores the UIWindowScene provided in the scene(:willConnectTo:options:) function in a global variable and does not change the set scene until the scene(:willConnectTo:options:) function is called again. Additionally, we do not perform any actions related to the disconnect event. func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } hudManager.setup(windowScene: windowScene) // ... } func sceneDidDisconnect(_ scene: UIScene) { // do nothing } In all crash logs, the activationState of the WindowScene is "unattached", so I initially thought that creating a UIWindow with a scene in the 'unattached' state should be avoided. However, in the scene(_:willConnectTo:options:) function, the scene's state is also 'unattached', yet the UIWindow is created successfully here, which makes me think that deciding whether to create a window based on the activationState is incorrect. I did find that trying to create a UIWindow with a scene after it has been disconnected causes a crash. func sceneDidDisconnect(_ scene: UIScene) { // Crash occur here and scene's state is `unattached` let window = UIWindow(windowScene: scene as! UIWindowScene) } If the activationState alone cannot be used to determine the validity of a scene, is there another way to check the validity of a Scene? Thank you
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
1
Boosts
0
Views
384
Activity
Mar ’25
A crash occurs when fetching history when Model has preserveValueOnDeletion attribute and using inheritance
Hello, In our app, we’ve modeled our schema using inheritance introduced in iOS 26.0, and we’re implementing SwiftData History to re-fetch models only when necessary. @Model public class Transaction { @Attribute(.preserveValueOnDeletion) public var date: Date = Date() public var amount: Double = 0 public var memo: String? } @Model public final class Spending: Transaction { public var installmentIndex: Int = 1 public var installment: Int = 1 public var installmentID: UUID? } If data has been deleted from database, we need to check a date property to determine whether to re-fetch datas. To do this, we added the preserveValueOnDeletion attribute to date property so we could retrieve it from the History tombstone value. However, after adding this attribute, a crash occurs. There is a console log Could not cast value of type 'Swift.ReferenceWritableKeyPath<Shared.ModelSchemaV5.Transaction, Foundation.Date>' (0x106bf8328) to 'Swift.PartialKeyPath<Shared.ModelSchemaV5.Spending>' (0x1094f21d8). and error log attached StrictMoneyChecking-2025-11-07-105108.txt I also tried this in the recent SampleTrip app, and fetching all history after a deletion causes the same crash. Is this issue currently being worked on or under investigation?
Replies
1
Boosts
0
Views
287
Activity
Nov ’25
Combine delay & switchToLatest publisher don't emit value sometimes
Hello, I recently implemented a conditional debounce publisher using Swift's Combine. If a string with a length less than 2 is passed, the event is sent downstream immediately without delay. If a string with a length of 2 or more is passed, the event is emitted downstream with a 0.2-second delay. While writing test logic related to this, I noticed a strange phenomenon: sometimes the publisher, which should emit events with a 0.2-second delay, does not emit an event. The test code below should have all indices from 1 to 100 in the array, but sometimes some indices are missing, causing the assertion to fail. Even after observing completion, cancel, and output events through handleEvents, I couldn't find any cause. Am I using Combine incorrectly, or is there a bug in Combine? I would appreciate it if you could let me know. import Foundation import Combine var cancellables: Set<AnyCancellable> = [] @MainActor func text(index: Int, completion: @escaping () -> Void) { let subject = PassthroughSubject<String, Never>() let textToSent = "textToSent" subject .map { text in if text.count >= 2 { return Just<String>(text) .delay(for: .seconds(0.2), scheduler: RunLoop.main) .eraseToAnyPublisher() } else { return Just<String>(text) .eraseToAnyPublisher() } } .switchToLatest() .sink { if $0.count >= 2 { completion() } }.store(in: &cancellables) for i in 0..<textToSent.count { let stringIndex = textToSent.index(textToSent.startIndex, offsetBy: i) let stringToSent = String(textToSent[textToSent.startIndex...stringIndex]) subject.send(stringToSent) } } var array = [Int]() for i in 1...100 { text(index: i) { array.append(i) } } DispatchQueue.main.asyncAfter(deadline: .now() + 5) { for i in 1...100 { assert(array.contains(i)) } } RunLoop.main.run(until: .now + 10)
Replies
0
Boosts
0
Views
441
Activity
Feb ’25
PhaseAnimator doesn't reflect @Observable state changes after animation settles
I ran into a behavior with PhaseAnimator that I'm not sure is a bug or by design. I'd appreciate any insight. The Problem When an @Observable property is read only inside a PhaseAnimator content closure, changes to that property are ignored after the animation cycle completes and reaches its resting state. The UI gets stuck showing stale data. Minimal Reproduction I've put together a simple demo with two views side by side, both driven by the same ViewModel and toggled by the same button: BrokenView — receives an @Observable object and reads its property inside PhaseAnimator. After the animation completes, toggling the property has no visible effect. FixedView — receives the same value as a Bool parameter. Updates correctly every time because view's parameter has changed. import SwiftUI @Observable class ViewModel { var isError = false } struct BrokenView: View { let viewModel: ViewModel @State private var trigger = false var body: some View { VStack(spacing: 20) { Text("Broken (@Observable)").font(.headline) PhaseAnimator([false, true], trigger: trigger) { _ in if viewModel.isError { Text("Error!").foregroundStyle(.red).font(.largeTitle) } else { Text("OK").foregroundStyle(.green).font(.largeTitle) } } } .padding() .onAppear { trigger = true } } } struct FixedView: View { let isError: Bool @State private var trigger = false var body: some View { VStack(spacing: 20) { Text("Fixed (Value Type)").font(.headline) PhaseAnimator([false, true], trigger: trigger) { _ in if isError { Text("Error!").foregroundStyle(.red).font(.largeTitle) } else { Text("OK").foregroundStyle(.green).font(.largeTitle) } } } .padding() .onAppear { trigger = true } } } struct DemoView: View { @State private var viewModel = ViewModel() var body: some View { VStack(spacing: 40) { BrokenView(viewModel: viewModel) Divider() FixedView(isError: viewModel.isError) Divider() Button("Toggle isError: \(viewModel.isError)") { viewModel.isError.toggle() } .buttonStyle(.borderedProminent) } .padding() } } Run the preview, then tap the toggle button. FixedView updates instantly; BrokenView stays stuck. My Understanding It seems like PhaseAnimator only tracks @Observable access during active animation phases. Once it settles at rest, the content closure is not re-evaluated, so observation tracking is effectively lost. Passing a value type works because SwiftUI view diffing detects the input change and triggers a body re-evaluation, which in turn re-evaluates the PhaseAnimator content. Question Is this intended behavior? Or shouldn't I use phase animator in this way? I could not find any mention of this limitation in the documentation. If it is by design, it might be worth documenting — it is a subtle pitfall that is easy to miss. Thanks in advance for any input!
Replies
0
Boosts
0
Views
83
Activity
1d