Posts

Post not yet marked as solved
0 Replies
314 Views
I have a project where I wanted to display a custom input field for a numeric code. UIKeyInput seems the right tool for this, so I implemented a UIViewRepresentable single digit view. So far so good. on iOS this works nicely. On iPadOS however it doesn't ever become the first responder = gets focused. Tested in iOS 15-17 and iPadOS 15-17. Here is the entire code for testing. You can drop it into a blank iOS app and run it as is on iPad or iPhone simulators/devices. The field should get focus on tapping. On iOS it does - on iPad it doesn't. The lines print("DigitBoxView focused is \(focused)") focused = true print("DigitBoxView tap gesture sets focus to \(focused)") print DigitBoxView focused is false DigitBoxView tap gesture sets focus to false even though I unconditionally set it to true. Am I doing something wrong? How can I achieve the KeyInput view getting focused on iPadOS? // Created by Thomas Krajacic on 13.11.23. // import SwiftUI @main struct KeyInputTestApp: App { var body: some Scene { WindowGroup { ContentView() } } } struct ContentView: View { @State var char: Character? var body: some View { DigitBoxView(character: $char) { _ in // } .frame(width: 100) .padding() } } #Preview { ContentView() } struct DigitBoxView: View { /// The represented character (output) @Binding var character: Character? @FocusState var focused: Bool /// Triggered on pressing enter in any of the textfields var onSubmit: (String?) -> Void @State private var size: CGSize = .zero var body: some View { KeyInput { input in switch input { case let .text(text): guard let valid = text.first else { return } self.character = valid case .enter: self.onSubmit(nil) case .delete: self.character = nil case .tab: self.onSubmit(nil) } } hasText: { self.character != nil } .focused($focused) .aspectRatio(0.75, contentMode: .fit) .cornerRadius(10) .background { ZStack { // The outline RoundedRectangle(cornerRadius: 10) .strokeBorder(Color.secondary, lineWidth: 1) // The digit Text(character.map(String.init) ?? "") .minimumScaleFactor(0.5) .font(.system(size: 72, weight: .regular, design: .monospaced)) } } .overlay { ZStack { // The selection outline RoundedRectangle(cornerRadius: 10) .strokeBorder(Color.primary, lineWidth: 2) } .opacity(focused ? 1 : 0) } // so the entire area is tappable .contentShape(RoundedRectangle(cornerRadius: 10)) .onTapGesture { print("DigitBoxView focused is \(focused)") focused = true print("DigitBoxView tap gesture sets focus to \(focused)") } } } public struct KeyInput: UIViewRepresentable { public enum Input { case text(String) case delete case tab case enter } var onInput: (Input) -> Void var hasText: () -> Bool final public class InputView: UIView, UIKeyInput { var _onInput: (Input) -> Void var _hasText: () -> Bool init(onInput: @escaping (Input) -> Void, hasText: @escaping () -> Bool) { self._onInput = onInput self._hasText = hasText super.init(frame: .zero) } required init?(coder: NSCoder) { fatalError() } public var hasText: Bool { _hasText() } public func insertText(_ text: String) { if text == "\t" { _onInput(.tab) } else if text == "\n" { _onInput(.enter) } else { _onInput(.text(text)) } } public func deleteBackward() { _onInput(.delete) } public override var canBecomeFirstResponder: Bool { true } } public func makeUIView(context: Context) -> InputView { InputView( onInput: onInput, hasText: hasText ) } public func updateUIView(_ uiView: InputView, context: Context) { // Crickets… } }
Posted
by tkrajacic.
Last updated
.
Post not yet marked as solved
7 Replies
2.6k Views
I am trying to understand how an NSTextField reacts to changes of its cell's backgroundStyle.The reason is that I want to use the automatic handling of the text color be used when I set the backgroundStyle of the text field that's inside a table cell.From what I have gathered so far, the textfield's cell has a backgroundStyle property and when this is set, and the textColor is `labelColor` (or any of the other control colors) the text color should be automatically updated to be fitting for the backgroundStyle.Given a tableView with a custom row class and a custom cell:class RowView: NSTableRowView { override func drawSelection(in dirtyRect: NSRect) { if isSelected { NSColor.white.set() var rects: UnsafePointer<NSRect>? = nil var count: Int = 0 self.getRectsBeingDrawn(&rects, count: &count) for i in 0..<count { let rect = NSIntersectionRect(bounds, rects![i]) __NSRectFillUsingOperation(rect, NSCompositingOperation.sourceOver) } } } override var interiorBackgroundStyle: NSView.BackgroundStyle { return isSelected ? .light : .dark } }andclass CustomCellView: NSTableCellView { @IBOutlet weak var label: NSTextField! override var backgroundStyle: NSView.BackgroundStyle { didSet { Swift.print("Style set to \(backgroundStyle == .light ? "light" : "dark")") Swift.print("Label Style set to \(label.cell!.backgroundStyle == .light ? "light" : "dark")") } } }I would expect the label to be drawn in black, when I select the row.I can see that the backgroundStyle is forwarded correctly when I select the row, but the label doesn't change color at all. In fact, being seemingly blended with my white selection, the label disappears entirely.Why is the label color not changing?P.S.: I know that I can manually set the label's color based on the background style of the cell. That's not what I am asking. I want to use the convenience of the `controlTextColor`s or at least understand why they are not working in this case. (They do seem to work if I don't draw my custom selection in the row and use the standard blue selection)
Posted
by tkrajacic.
Last updated
.
Post marked as solved
5 Replies
1.2k Views
I am using runtime loaded dynamic libraries (in an NSBundle) as a plugin system in my app.I would like to switch over to using XPC Services though, for various reasons. Is it possible to load plugins which are really xpc services from a user-specified folder? I have not yet figured out how I would go about dicovering that a plugin is present or put in the PlugIns folder.That folder would most likely be either under ~/Documents/MyApp/PlugIns or something else user-accessible.(I may also ship some plugins with the app, which are inside the app's bundle, but discovering/loading those seems trivial)Thank you for your help.Thomas
Posted
by tkrajacic.
Last updated
.