Hi,
I came across the following API:
@MainActor
func placeCursor(at position: UITextPosition!, animated: Bool)
From the signature, it seems intended to move the insertion point (caret) to a given UITextPosition, with an option for animation.
However, UITextView and UITextField don’t seem to expose this method as a public member — calling it gives the error:
Value of type 'UITextView' has no member 'placeCursor'
My questions are:
Is placeCursor(at:animated:) a public, supported API that we can safely use in apps?
If not, what is the Apple-recommended way to programmatically move the cursor without animation?
Right now, I only know of updating selectedTextRange, which works but doesn’t involve this placeCursor method. I want to confirm if placeCursor is meant for developer use or is an internal/private API.
Thanks!
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hello,
I am building a UIKit application where I need to handle key events in a UITextField with the following requirements:
Normal key presses (e.g. A, B, etc.) should insert characters into the text field.
A hotkey combination (Ctrl+K) should trigger a custom computation that runs on a background thread, and once completed, its result (e.g. $) should be inserted into the text field.
All events (normal keys and hotkeys) must appear in the exact order they were pressed by the user. For example:
If the user types A, B, then Ctrl+K, the field should show AB$.
If the user types A, Ctrl+K, C, the field should show A$C, even if the computation for $ takes longer.
I want strict sequential processing: no later keystroke should be inserted until an earlier hotkey computation finishes.
I have tried overriding pressesBegan(_:with:) in a custom UITextField subclass, and I can detect both normal keys and Ctrl+K.
Questions:
Is there a recommended UIKit API or pattern for handling this kind of ordered key event processing with hotkeys?
Are there best practices for mixing UI updates with background computations in this context, while preserving event order?
Thanks!
Hi,
I’m working with custom text input handling in a UITextView. For simulating user typing programmatically, the documented way is to call:
textView.insertText("H")
This correctly inserts text, triggers delegate callbacks, updates the caret, and behaves as expected.
However, since physical keyboard input normally goes through pressesBegan(:with:) before being translated into insertText(:), I was wondering:
Is it possible (or supported) to call pressesBegan ourselves with a constructed UIPress/UIKey to simulate key input events in the same way the system does?
Or
Is the intended approach strictly to use insertText(_:) for simulating text entry, and pressesBegan should only ever be used for listening to actual hardware key presses?
Thanks!
Topic:
UI Frameworks
SubTopic:
UIKit
Hi all,
I’m subclassing UITextView and overriding insertText(_:) to intercept and log input:
class TWTextView: UITextView {
override func insertText(_ text: String) {
print("insertText() : \(text)")
super.insertText(text)
}
}
This works fine, but I’ve noticed that insertText(_:) is invoked both when:
The user types something in the text view (via hardware/software keyboard).
I programmatically call myTextView.insertText("Hello") from my own code.
I’d like to be able to distinguish between these two cases — i.e., know whether the call was triggered by the user or by my own programmatic insert.
Is there any recommended way or system-provided signal to differentiate this?
Thanks in advance!
Hi all,
In my AppKit app, I sometimes simulate events programmatically, for example:
func simulateKeyPress(characters: String, keyCode: UInt16) {
guard let keyDown = NSEvent.keyEvent(
with: .keyDown,
location: .zero,
modifierFlags: [],
timestamp: 0,
windowNumber: NSApp.mainWindow?.windowNumber ?? 0,
context: nil,
characters: characters,
charactersIgnoringModifiers: characters,
isARepeat: false,
keyCode: keyCode
) else { return }
NSApp.postEvent(keyDown, atStart: false)
}
At the same time, I install a local event monitor:
NSEvent.addLocalMonitorForEvents(matching: .any) { event in
// Ideally, detect whether this event came from a real user
// (mouse, keyboard, trackpad, etc.)
// or was programmatically generated via NSEvent + postEvent.
return event
}
The problem:
Events I generate with NSEvent.* factory methods and post using NSApp.postEvent look the same as real system events when received in the monitor.
My question:
Is there a supported way to tell whether an incoming NSEvent is system/user-generated vs programmatically posted?
I’m trying to transform user keyboard input in a TextField so that, for example, whenever the user types the letter "a" it is stored and shown as the Greek letter "α".
I created a custom Binding to intercept and modify the typed text before saving it to my observable model.
Here’s a simplified version of my code:
import SwiftUI
class User: ObservableObject {
@Published var username: String = ""
}
struct ContentView: View {
@ObservedObject var user = User()
var usernameBinding: Binding<String> {
Binding(
get: { user.username },
set: { newValue in
// Replace all "a" with "α"
user.username = newValue.replacingOccurrences(of: "a", with: "α")
}
)
}
var body: some View {
TextField("Username", text: usernameBinding)
.padding()
.onChange(of: user.username) { newValue in
print("username changed to:", newValue)
}
}
}
When I type "a", I can see in the console that the onChange handler prints the transformed string ("α"), and the model (user.username) is updated.
However, the TextField on screen still shows the original "a" instead of updating to "α" immediately.
I expected the text field to update its displayed value whenever the bound property changes (since username is @Published on an ObservableObject), but that doesn’t seem to happen when I modify the text in the binding’s set closure.
Is this a known limitation of SwiftUI TextField?
Is there a better way to transform user input so the field shows the transformed text based on some processing?
Any advice or explanation would be appreciated.
I’m running into an issue with TextField focus behavior in SwiftUI.
By default, when I set focus to a TextField programmatically (using @FocusState), SwiftUI behaves like AppKit — the entire contents of the text field are selected. This is causing problems for my use case, because I want the caret placed at the end of the text without selecting everything.
How I solved this in AppKit
In AppKit, I worked around this by subclassing NSTextField and overriding becomeFirstResponder to adjust the editor’s selection:
override func becomeFirstResponder() -> Bool {
let responderStatus = super.becomeFirstResponder()
// Ensure caret is placed at the end, no text selected
if let editor = self.currentEditor() {
let selectedRange = editor.selectedRange
editor.selectedRange = NSRange(location: selectedRange.length, length: 0)
}
return responderStatus
}
This successfully prevented AppKit from auto-selecting the entire string when focus changed.
The problem in SwiftUI
Now I see the same auto-select behavior in SwiftUI when I toggle focus with @FocusState. But unlike AppKit, SwiftUI doesn’t expose the underlying NSTextView or UITextField APIs, so I can’t directly adjust the selection or caret position.
Questions:
Is there a way in SwiftUI to control the caret/selection behavior when a TextField becomes focused?
Is there a built-in modifier or @FocusState trick I’m missing?
Has anyone found a reliable SwiftUI-idiomatic approach to ensure the caret is placed at the end of the text instead of selecting all text?
update:
adding my swiftUI code below:
struct TextFieldUI: View {
@ObservedObject var pModel:TextFieldModel
@FocusState private var pIsFocusedState: Bool
var body: some View {
VStack(spacing: 20) {
TextField(pModel.placeholder, text: $pModel.text)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
.focused($pIsFocusedState)
.onChange(of: pModel.isFocused) { old, newValue in
pIsFocusedState = newValue
}
.onChange(of: pIsFocusedState) { old, newValue in
pModel.isFocused = newValue
}
.onAppear {
pIsFocusedState = pModel.isFocused
}
Toggle("Secure Mode", isOn: $pModel.isSecure)
.padding()
}
.padding()
}
}
Hi all,
I’m working on a UIKit app where I embed a SwiftUI TextField using UIHostingController. I’m using an ObservableObject model to drive the textfield content:
class TextFieldModel: ObservableObject {
@Published var text: String
@Published var placeholder: String
@Published var isSecure: Bool
@Published var isFocused: Bool
init(pText: String, pPlaceholder: String, pIsSecure: Bool, pIsFocused: Bool) {
self.text = pText
self.placeholder = pPlaceholder
self.isSecure = pIsSecure
self.isFocused = pIsFocused
}
}
And my SwiftUI view:
struct TextFieldUI: View {
@ObservedObject var pModel: TextFieldModel
@FocusState private var pIsFocusedState: Bool
var body: some View {
TextField(pModel.placeholder, text: $pModel.text)
.focused($pIsFocusedState)
}
}
I embed it in UIKit like this:
let swiftUIContentView = TextFieldUI(pModel: model)
let hostingController = UIHostingController(rootView: swiftUIContentView)
addChild(hostingController)
view.addSubview(hostingController.view)
hostingController.didMove(toParent: self)
Question:
In UIKit, if I subclass UITextField, I can override insertText(_:) and choose not to call super, effectively preventing the textfield from updating when the user types.
Is there a SwiftUI equivalent to intercept and optionally prevent user input in a TextField, especially when it’s embedded inside UIKit?
What is the recommended approach in SwiftUI for this?
Hi everyone,
In UIKit, I can detect which key and modifier keys are pressed from an external hardware keyboard using the pressesBegan method in a UIResponder:
override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
for press in presses {
if let key = press.key {
print("Key: \(key.charactersIgnoringModifiers ?? "")")
print("Modifiers: \(key.modifierFlags)")
}
}
}
I am now working in SwiftUI (iOS), and I couldn’t find a direct equivalent for pressesBegan.
What is the recommended way in SwiftUI to detect modifier keys + key presses from an external keyboard? Is there a built-in API, or should I always wrap a UIKit view/controller for this purpose?
Thanks in advance!
in iOS, user can set focus on UItextField and tapping a key in the virtual keyboard updates the text in the textfield. This user action causes the relevant delegates of UITextFieldDelegate to get invoked, i.e the handlers associated with action of user entering some text in the textfield.
I m trying to simulate this user action where I am trying to do this programatically. I want to simulate it in a way such that all the handlers/listeners which otherwise would have been invoked as a result of user typing in the textfield should also get invoked now when i am trying to do it programatically. I have a specific usecase of this in my application.
Below is how I m performing this simulation.
I m manually updating the text field associated(UITextField.text) and updating its value.
And then I m invoking the delegate manually as textField.delegate?.textField?(textField, shouldChangeCharactersIn: nsRange, replacementString: replacementString)
I wanted to know If this is the right way to do this. Is there something better available that can be used, such that simulation has the same affect as the user performing the update?
I have added an "App Intents Extension" target to my main application in macOS. This generated the below two files:
TWAppIntent.swift
import AppIntents
struct TWAppIntent: AppIntent {
static var title: LocalizedStringResource = "TWAppIntentExtension"
static var parameterSummary: some ParameterSummary {
Summary("Get information on \(\.$TWType)")
}
//launch app on running action
static var openAppWhenRun: Bool = true
// we can have multiple parameter of diff types
@Parameter(title: "TWType")
var TWType: String
func perform() async throws -> some IntentResult & ReturnsValue<String> & ProvidesDialog {
return .result(value: TWType, dialog: "Logged break.")
}
}
TWAppIntentExtension.swift
import AppIntents
@main
struct TWAppIntentExtension: AppIntentsExtension {
}
I m able to build the extension target and I my intent action is available in the shortcuts app. However, on launching a shortcut with the above created intent action. I m getting the below popups:
I have identified what is causing this error. Setting the openAppWhenRun to true is causing this error. I don't get this when it is set to false. This property is supposed to launch the application, but can someone help me understand why is it happening? This is only causing the error when using this property for AppIntent Extension and not for In app handling for the AppIntent.
Can we not launch our application from AppIntent extension?