Adjust your app’s behavior and filter incoming notifications based on the user's Focus settings.

Posts under Focus tag

14 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

How to disable the default focus effect and detect keyboard focus in SwiftUI?
I’m trying to customize the keyboard focus appearance in SwiftUI. In UIKit (see WWDC 2021 session Focus on iPad keyboard navigation), it’s possible to remove the default UIFocusHaloEffect and change a view’s appearance depending on whether it has focus or not. In SwiftUI I’ve tried the following: .focusable() // .focusable(true, interactions: .activate) .focusEffectDisabled() .focused($isFocused) However, I’m running into several issues: .focusable(true, interactions: .activate) causes an infinite loop, so keyboard navigation stops responding .focusEffectDisabled() doesn’t seem to remove the default focus effect on iOS Using @FocusState prevents Space from triggering the action when the view has keyboard focus My main questions: How can I reliably detect whether a SwiftUI view has keyboard focus? (Is there an alternative to FocusState that integrates better with keyboard navigation on iOS?) What’s the recommended way in SwiftUI to disable the default focus effect (the blue overlay) and replace it with a custom border? Any guidance or best practices would be greatly appreciated! Here's my sample code: import SwiftUI struct KeyboardFocusExample: View { var body: some View { // The ScrollView is required, otherwise the custom focus value resets to false after a few seconds. I also need it for my actual use case ScrollView { VStack { Text("First button") .keyboardFocus() .button { print("First button tapped") } Text("Second button") .keyboardFocus() .button { print("Second button tapped") } } } } } // MARK: - Focus Modifier struct KeyboardFocusModifier: ViewModifier { @FocusState private var isFocused: Bool func body(content: Content) -> some View { content .focusable() // ⚠️ Must come before .focused(), otherwise the FocusState won’t be recognized // .focusable(true, interactions: .activate) // ⚠️ This causes an infinite loop, so keyboard navigation no longer responds .focusEffectDisabled() // ⚠️ Has no effect on iOS .focused($isFocused) // Custom Halo effect .padding(4) .overlay( RoundedRectangle(cornerRadius: 18) .strokeBorder( isFocused ? .red : .clear, lineWidth: 2 ) ) .padding(-4) } } extension View { public func keyboardFocus() -> some View { modifier(KeyboardFocusModifier()) } } // MARK: - Button Modifier /// ⚠️ Using a Button view makes no difference struct ButtonModifier: ViewModifier { let action: () -> Void func body(content: Content) -> some View { content .contentShape(Rectangle()) .onTapGesture { action() } .accessibilityAction { action() } .accessibilityAddTraits(.isButton) .accessibilityElement(children: .combine) .accessibilityRespondsToUserInteraction() } } extension View { public func button(action: @escaping () -> Void) -> some View { modifier(ButtonModifier(action: action)) } }
1
0
102
6h
FocusedBinding and selecting item in the List issue
Hello dear community! I'm still new to SwiftUI and going through the official Introducing SwiftUI Tutorials (basically, building the Landmarks app) And I'm struggle with some behavior I noticed in the macOS version of the Landmarks app. So, here is the idea, there is a list of Landmarks (the simplified version from the tutorial): struct LandmarkList: View { @Environment(ModelData.self) var modelData @State private var selectedLandmark: Landmark? var index: Int? { modelData.landmarks.firstIndex(where: { $0.id == selectedLandmark?.id }) } var body: some View { @Bindable var modelData = modelData NavigationSplitView { List(selection: $selectedLandmark) { ForEach(modelData.landmarks) { landmark in NavigationLink { LandmarkDetail(landmark: landmark) } label: { LandmarkRow(landmark: landmark) } .tag(landmark) } } .navigationTitle("Landmarks") .frame(minWidth: 300) } detail: { Text("Select a landmark") } .focusedValue(\.selectedLandmark, $modelData.landmarks[index ?? 0]) } } And there are a few helper structs which makes the possibility of the Marking a selected landmark as favorite (or remove) via shortcut and via menu: struct LandmarkCommands: Commands { @FocusedBinding(\.selectedLandmark) var selectedLandmark var body: some Commands { SidebarCommands() CommandMenu("Landmark") { Button("\(selectedLandmark?.isFavorite == true ? "Remove" : "Mark") as Favorite") { selectedLandmark?.isFavorite.toggle() } .keyboardShortcut("f", modifiers: [.shift, .option]) .disabled(selectedLandmark == nil) } } } private struct SelectedLandmarkKey: FocusedValueKey { typealias Value = Binding<Landmark> } extension FocusedValues { var selectedLandmark: Binding<Landmark>? { get { self[SelectedLandmarkKey.self] } set { self[SelectedLandmarkKey.self] = newValue } } } So, with this setup which is presented in the tutorial I notice 3 issues: On the first launch of the app, if I try to select a landmark — it's get unselected instantly. It I try to select it again — it works Marking a selected Landmark as favorite via shortcut (f+shift+opt) or via menu makes the selected Landmark unselected On the Landmark details — marking a Landmark as Favorite also makes the landmark unselected. You can check it on your own if you download the completed project from this page: https://developer.apple.com/tutorials/swiftui/creating-a-macos-app But could someone please explain why it's happening? And how to avoid such a bad UX with unselecting items in the list?
Topic: UI Frameworks SubTopic: SwiftUI Tags:
1
0
170
Jul ’25
Notification interruptions
My app Balletrax is a music player for people to use while they teach ballet. Used to be you could silence notifications during use, but now the customer seems to have to know how to use Focus mode, remember to turn it on and off, and have to check the notifications one does and doesn't want to use. Is there no way to silence all notifications when the app is in use?
0
0
32
Apr ’25
VisionOS - Gamepad steals focus
I am developing a vision os app for controlling an underwater ROV. I have ornaments with telemetry and buttons around a central video view feed. I have custom buttons mappings, such as "A" for locking the depth of the drone. However, when I look at buttons or certain ornaments, my custom gamepad logic is kept from running. This means that when a SwiftUI Button gains focus on visionOS, pressing the controller’s A button triggers the system’s default “click” on that Button rather than my custom buttonA handler. Essentially, focus interception by the system is stealing my A-press events and preventing my custom gamepad logic from running. Is there a way to disable the built in gamepad interaction and only allow my custom gamepad mappings?
1
0
115
Apr ’25
SwiftUI: TextField not getting focus changes inside Button
I have a SwiftUI List (on macOS) where I want to display a few TextFields in each row, and observe how the focus changes as an individual text field is selected or unselected. This seems to work fine if I just have the List display a pure TextField in each row, but if I embed the TextField inside a Button view, the focus change notifications stop working. I want the 'button' functionality so that the user can tap anywhere on the row and have the text field activated, instead of tapping exactly on the text field boundary. Here is some code to demonstrate the problem. In the List if you have RowView uncommented out (1), then the focus change notifications work. If you comment that out and uncomment the RowViewWithButton (2), then the button functionality works, but I can't get focus change notifications anymore. Here is the code to reproduce the issue. Interestingly, when I test this on iOS, it works fine in both cases. But I need the solution for macOS. import SwiftUI // test on macOS target struct ContentView: View { @State private var textFields = Array(repeating: "", count: 4) @FocusState private var focusedField: Int? var body: some View { List(0..<4, id: \.self) { index in // 1. works with focus notification changes RowView(index: index, text: $textFields[index], focusedField: $focusedField) // 2. button works, but no focus notifications on text field //RowViewWithButton(index: index, text: $textFields[index], focusedField: $focusedField) } } } struct RowView: View { let index: Int @Binding var text: String @FocusState.Binding var focusedField: Int? var body: some View { HStack { Text("Row \(index + 1):") TextField("", text: $text) .multilineTextAlignment(.leading) .focused($focusedField, equals: index) } .onChange(of: focusedField) { newFocus in if newFocus == index { print("TextField \(index) is in focus") } else { print("TextField \(index) lost focus") } } .padding(.vertical, 4) } } struct RowViewWithButton: View { let index: Int @Binding var text: String @FocusState.Binding var focusedField: Int? var body: some View { Button (action: { print("RowView - button selected at index \(index)") focusedField = index }) { HStack { Text("Row \(index + 1):") TextField("", text: $text) .multilineTextAlignment(.leading) .focused($focusedField, equals: index) } .onChange(of: focusedField) { newFocus in if newFocus == index { print("TextField \(index) is in focus") } else { print("TextField \(index) lost focus") } } .foregroundColor(.primary) } .buttonStyle(BorderlessButtonStyle()) .padding(.vertical, 4) } } #Preview { ContentView() .frame(width: 320, height: 250) }
2
0
269
Mar ’25
Shortcuts Automatic, App Shortcuts and FocusStatus in Playground work
Hello everyone, I’m currently developing a Playground App for the Swift Student Challenge, and its core functionality relies heavily on Shortcuts Automation, App Shortcuts, and interactions with the Focus Mode status (e.g., reading Focus Status or execute Focus Filter). Before finalizing my submission, I’d like to clarify whether these features will function as expected during the review process. Specifically: Shortcuts Automation: My app uses custom shortcuts to trigger actions within the Playground. Will reviewers be able to test these shortcuts seamlessly, or do I need to provide explicit instructions for enabling/setting them up? App Shortcuts: The app integrates system-level App Shortcuts (via App Intents). Are these supported in the test environment, and will reviewers see them during testing? Focus Status Interaction: The app dynamically responds to changes in the device’s Focus Mode (e.g., adjusting UI and function based on FocusStatus). Does the evaluation environment allow access to Focus Status data, and are there restrictions on simulating Focus Mode changes? I want to ensure these features are testable and don’t lead to unexpected issues during review. Any insights or advice from past participants, mentors, or Apple experts would be greatly appreciated! Thank you in advance for your guidance!
1
1
416
Feb ’25
Change anchor position of view for the tvOS focus engine
I'm developing a grid of focusable elements in SwiftUI with different sizes for tvOS (similar to a tv channel grid). Because the Focus Engine calculates the next view to focus based on the center of the currently focused view, sometimes it changes focus to an unexpected view. Here's an example: Actual: Expected: Is it possible to customize the anchor point from which the focus engine traces a ray to the next view? I would prefer the leading edge in my case.
0
0
368
Jan ’25
Focus more evolved
This message only to know your feeling on my project. Not to discuss what is feasible or not. Just on the interest of the functionality. I use 5 Focus profiles, Do Not Disturb, Holiday, Work, Personal and Sleep. I find that the native solutions for changing modes are not powerful enough. I'd like an app to configure automatically when each Focus profile should be activated. Eg : -Holiday : when holiday is found in my calendar -Work : when I'm not on holiday, when we are not on the weekend, and after 7ham but before 7pm. Personal : when I'm not on holiday when we are on the weekend of after 7pm -Dot Not Disturb: When I'm not in holiday, only on the working week when I have an event in my agenda with the status accepted". These are just some examples. the idea is that everything will be configurable. (my app is almost finished.) What do you think?
0
0
420
Nov ’24
$FocusState and Lists with rows containing TextFields
While I've seen examples of using $FocusState with Lists containing "raw" TextFields, in my use case, the List rows are more complex than that and contain multiiple elements, including TextFields. I obviously don't understand something fundamental here, because I am completely unable to get TextField-to-TextField tabbing to work. Can someone set me straight? Sample code demonstrating the issues: // // ContentView.swift // ListElementFocus // // Created by Richard Aurbach on 10/12/24. // import SwiftUI /// NOTE: in my actual app, the data model is actually a set of SwiftData /// PresistentModel objects. Here, I'm simulating them with an Observable. @Observable final class TestModel: Identifiable { public var id: UUID public var checked: Bool = false public var title: String = "Test" public var subtitle: String = "Subtitle" init(checked: Bool = false, title: String, subtitle: String) { self.id = UUID() self.checked = checked self.title = title self.subtitle = subtitle } } struct ContentView: View { /// Instead of a @Query... @State var records: [TestModel] = [ TestModel(title: "First title", subtitle: "blah, blah, blah"), TestModel(title: "Second title", subtitle: "more nonsense"), TestModel(title: "Third title", subtitle: "even more nonsense"), ] @FocusState var focus: UUID? var body: some View { Form { Section { HStack(alignment: .top) { Text("Goal:").font(.headline) Text( "If a user taps in the TextField in any row, they should be able to tab from row to row using any keyboard which supports a tab key." ) } HStack(alignment: .top) { Text("#1:").font(.headline) Text( "While I will admit that this code is probaby total garbage, I haven't been able to find any way to make tabbing from row to row to work at all." ) } HStack(alignment: .top) { Text("#2:").font(.headline) Text( "Tapping the checkbox button causes the row to flash with the current accent color, and I can't find any way to turn that off." ) } } header: { Text("Problems").font(.title3).bold() }.headerProminence(.increased) Section { List(records) { record in ListRow(record: record, focus: focus) .onKeyPress(.tab) { focus = next(record) return .handled } } } header: { Text("Example: Selector of Editable Items").font(.title3).bold() }.headerProminence(.increased) } .padding() } private func next(_ record: TestModel) -> UUID { guard !records.isEmpty else { return UUID() } if record.id == records.last!.id { return records.first!.id } if let index = records.firstIndex(where: { $0.id == record.id }) { return records[index + 1].id } return UUID() } } struct ListRow: View { @Bindable var record: TestModel var focus: UUID? @FocusState var focusState: Bool init(record: TestModel, focus: UUID?) { self.record = record self.focus = focus self.focusState = focus == record.id } var body: some View { HStack(alignment: .top) { Button { record.checked.toggle() } label: { record.checked ? Image(systemName: "checkmark.square.fill") : Image(systemName: "square") }.font(.title2).focusable(false) VStack(alignment: .leading) { TextField("title", text: $record.title).font(.headline) .focused($focusState) Text("subtitle").italic() } } } } #Preview { ContentView() }
0
0
456
Oct ’24
Focus fails when TextField includes axis: .vertical
I've found another interesting issue with the Focus system. My text case is SwiftUI in Preview or Simulator (using an iPad mini case) -- I haven't tried this on other environments, so your mileage may vary. I have a Form including several TextFields. Adding the usual @FocusState logic, I observe that if I type a TAB key, then (a) If the TextFields are specified using TextField(“label”, text: $text), typing the tab key switches focus from field to field as expected, BUT (b) If the TextFields are specified using TextField(“label”, text: $text, axis: .vertical), typing the tab key adds whitespace to the field and does NOT change focus. In the latter case, I need to use an .onKeyPress(.tab) {….} modifier to achieve the desired result. Reported as FB15432840
0
0
513
Oct ’24
10162: The SwiftUI cookbook for focus - does not work as expected with iOS 18
I try to create a sheet that shows a textfield and the textfield should gain the focus immediately after the sheet is presented. This use case is explained in Session 10162 at 11:21 and at 13:31 my desired behavior is shown. I could not get this to work in my own code and downloaded the sample code from here: https://developer.apple.com/documentation/swiftui/focus-cookbook-sample Then I opened the sample code and run it in the simulator. It does not focus when the sheet appears in a iOS 18 simulator using Xcode 16 installed via the AppStore. It does gain focus if I use the "add" Button. No changes made on the sample code. Just adjusted the Team setting to get a clean build. The behavior I get locally under iOS 18 is not what is shown in the session and I can't understand why. I tried the following Simulators (and platforms) iPhone 16, iPad Pro (M4, 11inch) and my Mac. On none of those the last item got focus just by presenting the sheet. Is it not possible to test this in a simulator? Could I have a configuration error? Given all the information I found yet, this seems like a Bug. It would be very helpful if someone could replicate my problem. Thank you for your help. Programm Versions: Xcode: Version 16.0 (16A242d) MacOS: 15.0 (24A335)
0
0
510
Sep ’24
Apps cannot be on multiple screens in iOS 18
Since using the iOS 18 beta in July I am unable to add apps to multiple screens at a time. For example, I have a screen for my work focus and I cannot add the calculator app to this screen while it is on another screen. If I try to add it to a screen it is removed from the other screen. Has anyone else noticed this? Is this expected to be fixed in iOS 18 or could it be a retrogressive feature?
0
0
585
Sep ’24
SetFocusFilterIntent `perform()` method is not called on iOS 18 beta
I’ve set up a focus filter, but the perform() method in SetFocusFilterIntent isn't called when the focus mode is toggled on or off on my iPhone since I updated to iOS 18 beta (22A5326f). I can reproduce the issue for my app, but focus filters are also broken for any third-party apps installed on my phone, so I guess it's not specific to how I've implemented my filter intent. This used to work perfectly on iOS 17. I didn't change a single line of code, and it broke completely on the latest iOS 18 beta. I've filed a bug report including a sysdiagnose (FB14715113). To the developers out there, is this something you are also observing in your apps?
3
0
700
Mar ’25