Post not yet marked as solved
In iOS 15 SDK you added the new FocusState API in SwiftUI. However there is no discussion or explanation anywhere that I could find, which explains:
What exactly is "focus"?
What isn't focus?
What is the relationship between FocusState and accessibility focus?
What is the relationship between whether a SecureField is being edited, and whether it's "focused"?
Example:
Lets say my tvOS app has an on-screen keyboard, where the user uses the remote's directional controls to move focus around to the letter buttons. To enter their password, they focus the password field, then click the center button to activate it. Now that it's active, they move focus to each letter of their password and click on each one: P... A... S... S... W... R... D... !... then they move focus to the "Submit" button and click.
In this case, while the SecureField is being edited, focus moves around to a bunch of different buttons.
The point of this example is that, if SecureField had a public "isBeingEdited" property, then it would be TRUE even while the field is not focused.
However most Workday's designers interpret "focused" as being totally equivalent to "isBeingEdited" because in a web browser, tabbing out of a field makes it stop being edited.
What is Apple's intent here? When not using a remote or physical keyboard or screen-reader, how is focus supposed to relate to whether a field is being edited? Does this relationship change when a user now has a bluetooth keyboard connected and Full Keyboard Access is turned ON? How does this correlate with accessibility focus?
I cannot find any documentation from Apple that explains what focus is, or how this is supposed to work in SwiftUI in the various different scenarios where the concept of "focus" is relevant. Do you have a link to something current that explains how it's supposed to work so that we will know if there's a bug?
Last question: how can we make the iOS simulator treat the physical keyboard as if it was a bluetooth keyboard to be used for focus-based keyboard navigation?
Post not yet marked as solved
I am trying to set the focus on the .searchable text entry field using @FocuseState and .focused($focusedField, equals: .search) technique demonstrated by Tanu in her WWDC21-10023 talk, but I'm not sure if it is a focusable element or how to programmatically set it. My attempt:
//based on a technique presented in https://developer.apple.com/videos/play/wwdc2021/1002 and Paul Hudson's article https://www.hackingwithswift.com/quick-start/swiftui/how-to-add-a-search-bar-to-filter-your-data
import SwiftUI
enum Field: Hashable {
case search
}
struct ContentView: View {
let itemsToSearch = ["John", "Mark", "Adam", "Carol", "Ismael", "Vanessa", "Aniq"]
@FocusState private var focusedField: Field?
@State private var searchText = ""
var body: some View {
NavigationView {
List {
ForEach(searchResults, id: \.self) { itemsToSearch in
NavigationLink(destination: Text(itemsToSearch)) {
Text(itemsToSearch)
}
}
}
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always)) {
ForEach(searchResults, id: \.self) { result in
Text("\(result)").searchCompletion(result)
}
.focused($focusedField, equals: .search)
.onAppear {
focusedField = .search
}
}
}
}
var searchResults: [String] {
if searchText.isEmpty {
return itemsToSearch
} else {
return itemsToSearch.filter { $0.contains(searchText) }
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Can someone clarify if this is possible, and if so, where I am going wrong? Thanks in advance.
Laith
Post not yet marked as solved
On a MAC, the lost focus event is not triggered when the focus
shifts away from the browser (This happens on all browsers (Safari, Chrome or
Firefox))to another window when clicking on a search textbox or notification
panel. This has been observed in:
MAC OS Big SUR Version 11.2.1
MAC OS Big SUR Version 11.5.1
MAC OS Big SUR Version 11.6
MAC OS Monterey 12.1
MAC OS High Sierra
Version 10.13.6 is the only MAC OS where the lost focus event is triggered when
clicking away from the browser to an OS component such as a textbox or
notification panel. Is it possible to restore the lost focus event on the above
versions of MAC OS?
Post not yet marked as solved
struct ModelsByCategoryGrid: View {
@Binding var showBrowse: Bool
let models = Models()
var body: some View {
VStack { [ONE ERROR HERE SAYS "Type'(_) -> ()' cannot conform to 'View']
ForEach(ModelCategory.allCases, id: .self); { category in [2 ERRORS HERE SAY 1: "Generic parameter 'Content' could not be inferred" 2: "Missing argument for parameter 'content' in call
//Only display the grid if the category contains items
if let modelsByCategory = models.get(category: category) {
HorizontalGrid(showbrowse: $showBrowse, title: category.label, items: modelsByCategory)
}
}
}
}
}
Post not yet marked as solved
I want implement a UI in tvOS. The hierarchy is like this:
App -> Tab Bar -> <Home, Search, Settings>
When I'm in Home and want to play a VOD, I want to hide tab bar (top menu) so the video is playing without overlay.
Using .isHidden on TabView result in hiding eveything because of the hierarchy.
Using .focused also do nothing.
How to achieve it?
Post not yet marked as solved
I wanted to use SwiftUI to manage dynamic forms for one of my apps. The dynamic forms aren't compatible with enum, and every single usage demo or blog post on iOS 15's FocusState is using an enum.
Official docs use enum
My example without Enum, for you see that it's possible. But should it be done?
// Focus State Example
//
// Created by Michael Robert Ellis on 12/7/21.
//
import SwiftUI
struct MyObject: Identifiable, Equatable {
var id: String
public var value: String
init(name: String, value: String) {
self.id = name
self.value = value
}
}
struct ContentView: View {
@State var myObjects: [MyObject] = [
MyObject(name: "aa", value: "1"),
MyObject(name: "bb", value: "2"),
MyObject(name: "cc", value: "3"),
MyObject(name: "dd", value: "4")
]
@State var focus: MyObject?
var body: some View {
ScrollView(.vertical) {
VStack {
Text("Header")
ForEach(self.myObjects) { obj in
Divider()
FocusField(displayObject: obj, focus: $focus, nextFocus: {
guard let index = self.myObjects.firstIndex(of: $0) else {
return
}
self.focus = myObjects.indices.contains(index + 1) ? myObjects[index + 1] : nil
})
}
Divider()
Text("Footer")
}
}
}
}
struct FocusField: View {
@State var displayObject: MyObject
@FocusState var isFocused: Bool
@Binding var focus: MyObject?
var nextFocus: (MyObject) -> Void
var body: some View {
TextField("Test", text: $displayObject.value)
.onChange(of: focus, perform: { newValue in
self.isFocused = newValue == displayObject
})
.focused(self.$isFocused)
.submitLabel(.next)
.onSubmit {
self.nextFocus(displayObject)
}
}
}
Am I being dumb? Am I missing something or am I on to something?
Post not yet marked as solved
I am designing a SwiftUI view, which is meant to be presented modally (using a sheet modifier). I want the view to have two buttons inside its own navigation bar and this somehow forced me to use NavigationView inside the body of the view.
The view is going to be a simple form and one of its components is a TextField, which I want to automatically activate (set focus on), when the view appears. For that, I used the @FocusState property wrapper.
In spite of using almost the same view's body structure as in another file before, this new form kept crashing whenever my preview updated, yielding a long report.
Here are some essentials of that report:
Code Type: X86-64 (Native)
Role: Non UI
Parent Process: launchd_sim [30182]
Responsible Process: SimulatorTrampoline [872]
Exception Type: EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes: 0x0000000000000001, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: SIGNAL 4 Illegal instruction: 4
Terminating Process: exc handler [30404]
Thread 0 Crashed:: Dispatch queue: BSXPCCnx:com.apple.dt.xcode-previews.systemservices (BSCnx:client:com.apple.dt.uv.agent-preview-nonui-service)
0 SwiftUI 0x7fff5c970f89 static FocusState._makeProperty<A>(in:container:fieldOffset:inputs:) + 160
1 SwiftUI 0x7fff5c97141e protocol witness for static DynamicProperty._makeProperty<A>(in:container:fieldOffset:inputs:) in conformance FocusState<A> + 25
I immediately saw that there was a problem with @FocusState. Indeed, removing it stopped crashing the app. But how was the other view I mentioned working completely fine? I started comparing them.
The old view's body started with a Form and that view was embedded in a NavigationView in its preview. In the new view, the NavigationView was moved into its body itself. That was the key!
I prepared a little example view to illustrate this issue. This version crashes when you try to launch the preview:
import SwiftUI
struct Test: View {
@FocusState var focusedFieldNumber: Int?
@State private var comment = ""
var body: some View {
NavigationView {
Form {
TextEditor(text: $comment)
.focused($focusedFieldNumber, equals: 1)
}
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.75) {
self.focusedFieldNumber = 1
}
}
}
}
}
struct Test_Previews: PreviewProvider {
static var previews: some View {
Test()
}
}
And this version (extract) solves the problem:
import SwiftUI
struct Test: View {
// ...
var body: some View {
// Removed NavigationView.
Form {
// ...
}
// ...
}
}
struct Test_Previews: PreviewProvider {
static var previews: some View {
// Added NavigationView.
NavigationView {
Test()
}
}
}
Why does the position of NavigationView decide whether the preview crashes or not? Where does this behavior come from? I would love to hear something from Apple Developers. Thank you!
Post not yet marked as solved
Message send failure for send previewInstances message ?
Post not yet marked as solved
In a SwiftUI lab, I was asking about setting the focus state down a view hierarchy. The answer I got was to pass the focus state down the views as a binding. Conceptually, that made sense, so I moved on to other questions. But now that I am trying to implement it, I am having problems.
In the parent view, I have something like this:
@FocusState private var focusElement: UUID?
Then I am setting a property like this in the child view:
@Binding var focusedId: UUID?
When I try to create the detail view, I'm trying this:
DetailView(focusedId: $focusElement)
But this doesn't work. The error I get is:
Cannot convert value of type 'FocusState<UUID?>.Binding' to expected argument type 'Binding<UUID?>'
What is the right way to pass down the focus state to a child view so that it can update back up to the parent view?
I am trying to update from one child view, and have a TextField in a sibling view get focus.
Post not yet marked as solved
Let's say I have a SwiftUI view that's a compose experience, like composing a new email in Mail, an iMessage in Messages, or a Tweet in Twitter.
When the view is loaded, I want the soft keyboard to appear automatically so that the user can type immediately without needing to manually put focus in the TextField or TextEditor by tapping on it.
With the new @FocusState feature in iOS 15, I can programmatically put focus on different TextFields when the user interacts elsewhere in the UI (like pressing a button), but I can't seem to set a default focus.
I tried initializing focus in the SwiftUI view's init method as well as the onAppear method attached to other parts of the view, but this didn't seem to have any effect.
How can I put default focus on a TextField or TextEditor when a view is loaded?