How to Make First Responder in Swiftui Macos

How to make first responder in SwiftUI macOS

If your MyField is a NSTextField the following works. Tested with Xcode 11.4 / macOS 10.15.4

  func makeNSView(context: Context) -> MyField {
let view = MyField()

// ... other properties set up here

// wait for next cycle, so field be already in window
DispatchQueue.main.async {
view.window?.makeFirstResponder(view)
}
return view
}

SwiftUI: How to make TextField become first responder?

iOS 15.0+

macOS 12.0+,

Mac Catalyst 15.0+,

tvOS 15.0+,

watchOS 8.0+

Use focused(_:) if you have a single TextField.

focused(_:)

Modifies this view by binding its focus state to the given Boolean state value.

struct NameForm: View {

@FocusState private var isFocused: Bool

@State private var name = ""

var body: some View {
TextField("Name", text: $name)
.focused($isFocused)

Button("Submit") {
if name.isEmpty {
isFocued = true
}
}
}
}

Use focused(_:equals:) should you have multiple TextFields.

focused(_:equals:)

Modifies this view by binding its focus state to the given state value.

struct LoginForm: View {
enum Field: Hashable {
case usernameField
case passwordField
}

@State private var username = ""
@State private var password = ""
@FocusState private var focusedField: Field?

var body: some View {
Form {
TextField("Username", text: $username)
.focused($focusedField, equals: .usernameField)

SecureField("Password", text: $password)
.focused($focusedField, equals: .passwordField)

Button("Sign In") {
if username.isEmpty {
focusedField = .usernameField
} else if password.isEmpty {
focusedField = .passwordField
} else {
handleLogin(username, password)
}
}
}
}
}

SwiftUI Documentation

  • focused(_:)
  • focused(_:equals:)
  • @FocusState


Update

I tested this in xCode version 13.0 beta 5 (13A5212g). It works

Disable autofocus on TextField in SwiftUI after App launch

This really looks like a bug (file a feedback to Apple if you want).

A found workaround is to disable temporary control on launch (disabled TextField cannot get focus) and reenable it in next event cycle.

Tested with Xcode 13.3 / macOS 12.2

Here is main part:

TextField("", text: $txt)
.disabled(disabled) // << here !!
.onAppear {
DispatchQueue.main.async { disabled = false } // << here !!
}

Complete code in project is here

How to move cursor when new NSTextView becomes FirstResponder (MacOS)?

I was able to get the desired behaviour by doing this:

  func makeNSView(context: NSViewRepresentableContext<TextView>) -> TextView.NSViewType {
let textView = NSTextView()
textView.textContainer?.lineFragmentPadding = 10
textView.textContainerInset = .zero
textView.font = NSFont.systemFont(ofSize: 12)
DispatchQueue.main.async {textView.window?.makeFirstResponder(textView)
textView.setSelectedRange(NSMakeRange(0, 0)) }

print("\(textView) is first responder") //proof that the first responder is shifting, but the cursor does not for some reason
return textView
}

The answer originally comes from here: How to make first responder in SwiftUI macOS

Thanks for all the help!

Get the current first responder without using a private API

In one of my applications I often want the first responder to resign if the user taps on the background. For this purpose I wrote a category on UIView, which I call on the UIWindow.

The following is based on that and should return the first responder.

@implementation UIView (FindFirstResponder)
- (id)findFirstResponder
{
if (self.isFirstResponder) {
return self;
}
for (UIView *subView in self.subviews) {
id responder = [subView findFirstResponder];
if (responder) return responder;
}
return nil;
}
@end

iOS 7+

- (id)findFirstResponder
{
if (self.isFirstResponder) {
return self;
}
for (UIView *subView in self.view.subviews) {
if ([subView isFirstResponder]) {
return subView;
}
}
return nil;
}

Swift:

extension UIView {
var firstResponder: UIView? {
guard !isFirstResponder else { return self }

for subview in subviews {
if let firstResponder = subview.firstResponder {
return firstResponder
}
}

return nil
}
}

Usage example in Swift:

if let firstResponder = view.window?.firstResponder {
// do something with `firstResponder`
}

MacOS swiftUI Custom ui TextField field with rounded edge

Try to use rounded rectangle in background (with needed parameters, like corner radius, color, etc) instead of border, like

.background(
RoundedRectangle(cornerRadius: 8)
.stroke(your_color_here)
)

MacOs SwiftUI textfield focus effect color change

It is possible to use background with focused dependent state, like

.background(RoundedRectangle(cornerRadius: 4)
.stroke(Color.gray, lineWidth: 0.5).cornerRadius(4)
.background(focused ? .black : .clear) // << here !!
.clipShape(RoundedRectangle(cornerRadius: 4))
)

demo

Complete test module is here



Related Topics



Leave a reply



Submit