Keyboard shortcuts that use the Command key modifier are not handled properly, and the UIKeyCommand action and pressesBegan and pressesEnded methods are not called at all or are called unreliably.
It is easy to reproduce using this snippet:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let textView = MyTextView()
textView.font = UIFont.systemFont(ofSize: 24)
textView.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec efficitur eros vitae dui consectetur molestie. Integer sed massa rutrum, pharetra orci eget, molestie sem. Fusce vestibulum massa nisi, vitae viverra purus condimentum et. Sed nec turpis aliquam, tempus enim sit amet, gravida libero. Praesent scelerisque venenatis nunc, vel convallis nisl auctor vitae. Mauris malesuada tempus pharetra. Nullam ornare venenatis ullamcorper. In viverra feugiat tincidunt. Nullam iaculis urna eu semper rutrum. "
textView.isEditable = true
textView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(textView)
NSLayoutConstraint.activate([
textView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
textView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
textView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
textView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
])
}
}
class MyTextView: UITextView {
override var keyCommands: [UIKeyCommand]? {
[
UIKeyCommand(input: "[", modifierFlags: .command, action: #selector(commandAction(_:)))
]
}
override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
print("pressesBegan")
super.pressesBegan(presses, with: event)
}
override func pressesEnded(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
print("pressesEnded")
super.pressesEnded(presses, with: event)
}
@objc private func commandAction(_ sender: Any?) {
print("commandAction")
}
}
Run the code in a Simulator or on a Device with an external keyboard connected. Observe the console for a string "commandAction" when pressing the combination Command + [ on the keyboard. Result it not predictable, the UIKeyCommand is not called at all, or called in a loop, or sometimes called after change selection in the UITextView. The same with pressesBegan and pressesEnded. Compare results with the change where instead of Command modifier, we use Control modifier eg.: "UIKeyCommand(input: "[", modifierFlags: .command, action: #selector(commandAction(_:))" - now each keyboard shortcut is properly reported to methods.
The UIKeyCommand.wantsPriorityOverSystemBehavior property changes nothing.
Behavior reproducible in the Simulator and on the Device (iPad)
(the issue was confirmed during online WWDC24 Labs)
Reported as FB13897415
Post
Replies
Boosts
Views
Activity
I'm seeing many apps, when restoring their state from a previous launch, have trouble opening windows to the space and minimized state they were last.
What do I need to do so my AppKit app doesn't have this problem?
I am directed from https://discuss.appium.io/t/create-multiple-instances-of-the-same-app/41266/14?u=lxnm, the context is that Appium max2 driver is implementing the activating of MacOS app using XCTest API methods. There are 2 ways to implement the activating of the app, using app path (calling initWithURL) and bundle id (calling initWithBundleIdentifier). This pull request shows how the XCTest methods are called when using the Mac2 driver, specifically in the file WebDriverAgentMac/WebDriverAgentLib/Routing/FBSession.m.
The problem is that I am able to launch my MacOS app(it is a company app) using bundle id, but when I launch the app with app path, I receive XcodeBuild errors:
[WebDriverAgentMac] [xcodebuild] XCTExpectFailure: matcher accepted Assertion Failure: Failed to launch com.company.companyApp: You do not have permission to run the application “companyApp”. You don’t have permission. To view or change permissions, select the item in the Finder and choose File > Get Info. (Underlying Error: The operation couldn’t be completed. Operation not permitted)
I followed this to enable R+W permissions to all users, but the same error is displayed.
Summary
Hello Apple Developers,
I've made a custom UITableViewCell that includes a UITextField and UILabel. When I run the simulation the UITableViewCells pop up with the UILabel and the UITextField, but the UITextField isn't clickable so the user can't enter information. Please help me figure out the problem.
Thank You!
Sampson
What I want:
What I have:
Screenshot Details:
As you can see when I tap on the cell the UITextField isn't selected. I even added placeholder text to the UITextField to see if I am selecting the UITextField and the keyboard just isn't popping up, but still nothing.
Relevant Code:
UHTextField
import UIKit
class UHTextField: UITextField {
override init(frame: CGRect) {
super.init(frame: frame)
configure()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
convenience init(placeholder: String) {
self.init(frame: .zero)
self.placeholder = placeholder
}
private func configure() {
translatesAutoresizingMaskIntoConstraints = false
borderStyle = .none
textColor = .label
tintColor = .blue
textAlignment = .left
font = UIFont.preferredFont(forTextStyle: .body)
adjustsFontSizeToFitWidth = true
minimumFontSize = 12
backgroundColor = .tertiarySystemBackground
autocorrectionType = .no
}
}
UHTableTextFieldCell
import UIKit
class UHTableTextFieldCell: UITableViewCell, UITextFieldDelegate {
static let reuseID = "TextFieldCell"
let titleLabel = UHTitleLabel(textAlignment: .center, fontSize: 16, textColor: .label)
let tableTextField = UHTextField()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
configure()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func set(title: String) {
titleLabel.text = title
tableTextField.placeholder = "Enter " + title
}
private func configure() {
addSubviews(titleLabel, tableTextField)
let padding: CGFloat = 12
NSLayoutConstraint.activate([
titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: padding),
titleLabel.heightAnchor.constraint(equalToConstant: 20),
titleLabel.widthAnchor.constraint(equalToConstant: 80),
tableTextField.centerYAnchor.constraint(equalTo: centerYAnchor),
tableTextField.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: 24),
tableTextField.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -padding),
tableTextField.heightAnchor.constraint(equalToConstant: 20)
])
}
}
LoginViewController
class LoginViewController: UIViewController, UITextFieldDelegate {
let tableView = UITableView()
let loginTableTitle = ["Username", "Password"]
override func viewDidLoad() {
super.viewDidLoad()
configureTableView()
updateUI()
createDismissKeyboardTapGesture()
}
func createDismissKeyboardTapGesture() {
// create the tap gesture recognizer
let tap = UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing))
// add it to the view (Could also add this to an image or anything)
view.addGestureRecognizer(tap)
}
func configureTableView() {
view.addSubview(tableView)
tableView.layer.borderWidth = 1
tableView.layer.borderColor = UIColor.systemBackground.cgColor
tableView.layer.cornerRadius = 10
tableView.clipsToBounds = true
tableView.rowHeight = 44
tableView.delegate = self
tableView.dataSource = self
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.removeExcessCells()
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: loginTitleLabel.bottomAnchor, constant: padding),
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding),
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding),
tableView.heightAnchor.constraint(equalToConstant: 88)
])
tableView.register(UHTableTextFieldCell.self, forCellReuseIdentifier: UHTableTextFieldCell.reuseID)
}
func updateUI() {
DispatchQueue.main.async {
self.tableView.reloadData()
self.view.bringSubviewToFront(self.tableView)
}
}
}
extension LoginViewController: UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: UHTableTextFieldCell.reuseID, for: indexPath) as! UHTableTextFieldCell
let titles = loginTableTitle[indexPath.row]
cell.set(title: titles)
cell.titleLabel.font = UIFont.systemFont(ofSize: 16, weight: .bold)
cell.tableTextField.delegate = self
return cell
}
}
Again thank you all so much for your help. If you need more clarification on this let me know.
I'm reworking my app and update code and design. Because my app is one both iPhone and iPad, i'm using Splitview to handle the configurations. But my app has 4 section that I manage using a Tab bar and each tab has a SplitView.
As you can see in images, the problem is that if I attach directly the UISplitViewController to UITabBarController you don't see two columns but only one (the primary or secondary view) both iPhone landscape orientation and iPad.
A solution that I found is to attach the splitviewcontroller to a view that contains a ContainerViewController e connect the split view to this container. If you do this, you see the split view work correctly ma the problem is the customization of appearance (look at image 3)
So may questions are:
why I have to embed a split view in a container view controller and i can't connect it directly to tabbar as we done until now?
Is there an other better solution then put a split view in a containerView?
Thank you
)
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?