Make Nstextfield in Nstablecellview Firstresponder()

make NSTextField in NSTableCellView firstResponder()

Don't subclass NSTextField. You can make the text field in a view based table view first responder right out of the box.

It's pretty easy.

Assuming you know row and column (in your example row 0 and column 0) get the table cell view with view(atColumn: 0, row and make the text field first responder.

let keyView = tableView.view(atColumn: 0, row: 0, makeIfNecessary: false) as! NSTableCellView
view.window!.makeFirstResponder(keyView.textField)

And what is the second outlet for? Just use the standard default textField.

How to programmatically initiate NSTextFieldCell editing (make it firstResponder)

When the editing started ,fieldEditor comes into picture thats why not able to set the firstResponder.

Implemented the textDidEndEditing delegate of the tableView. It solved the isssue.

NSTextField as FirstResponder has no stringValue unless manually clicking elsewhere

As Willeke asked in comments how I set and removed first responder I noticed that I had, incorrectly set it as:

[self.textfield becomeFirstResponder]

The docs state that this should not be used and the correct method is:

if ([self.textfield acceptsFirstResponder])
[self.textfield.window makeFirstResponder:self.textfield];

Thanks Willeke!

NSTextField in NSTableCellView

Probably the easiest way to accomplish this would be to subclass NSTextField and to override the drawRect: method in your subclass. There you can determine whether the NSTableCellView instance containing your NSTextField instances is currently selected by using this code (which I use with a NSOutlineView, but it should also work with NSTableView):

BOOL selected = NO;
id tableView = [[[self superview] superview] superview];
if ([tableView isKindOfClass:[NSTableView class]]) {
NSInteger row = [tableView selectedRow];
if (row != -1) {
id cellView = [tableView viewAtColumn:0 row:row makeIfNecessary:YES];
if ([cellView isEqualTo:[self superview]]) selected = YES;
}
}

Then draw the view like this:

if (selected) {
// set your color here
// draw [self stringValue] here in [self bounds]
} else {
// call [super drawRect]
}

NSTextfield renaming implementation on custom button in NSTableView

Well, the answer is actually very easy, it's the lack of related information that makes it kinda hard.
So, in case anybody's looking for the same thing, that's how I implemented this feature(it's actually one-liner):

in your action outlet just call

cell.textField?.selectText(self)

and the text's gonna get selected. After that just keep implementing it as usual.

Cocoa: Get Notified after Text Cell (NSTextField) is Edited & Start Editing Text Cell after Adding it in NSTableView in Swift 4?

Use Cocoa Bindings, it's very powerful and saves a lot of boilerplate code.

Short tutorial:

Edit: To take full advantage of KVC the data source must be an NSObject subclass with dynamic properties

  • Create a simple class Dream (the description property is optional)

    class Dream : NSObject {
    @objc dynamic var name : String
    init(name : String) { self.name = name }
    override var description : String { return "Dream " + name }
    }
  • In the view controller declare the data source array

    var dreams = [Dream]()
  • and replace var selectedRow:Int = 0 with

    @objc dynamic var selectedIndexes = IndexSet()
  • Go to Interface Builder

    • Select the table view, press ⌥⌘7 to go to the Bindings Inspector.

      Bind Selection Indexes to View Controller Model Key Path selectedIndexes.

      Press ⌥⌘6 and connect the dataSource (by drag&drop) to the view controller (Sample Image) .

    • Select the text field File 1 in Table Cell View in the table column. The easiest way is to ⌃⇧click in the text field area.

      Press ⌥⌘7 and bind Value to Table Cell View Model Key Path objectValue.name (!)

  • In the view controller populate the data source array in viewDidLoad ( I don't know that framework so I leave it out) and reload the table view.

    override func viewDidLoad() {
    super.viewDidLoad()
    let dreamNames = ["Hit the gym", "Run daily", "Become a millionaire", "Become a better programmer", "Achieve your dreams"]
    dreams = dreamNames.map{Dream(name: $0)}
    table.reloadData()
    }
  • Delete acceptsFirstResponder

  • Delete tableViewSelectionDidChange
  • Delete tableView:viewFor:row:
  • Add

    func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
    return dreams[row]
    }
  • Replace addNewDream with

    func addNewDream() {
    let last = dreams.count
    dreams.append(Dream(name: "Double Click or Press Enter to Add Item"))
    table.insertRows(at: IndexSet(integer: last), withAnimation: .effectGap)
    table.scrollRowToVisible(last)
    table.selectRowIndexes([last], byExtendingSelection: false)

    saveDreams()
    }
  • Replace removeDream() with

    func removeDream() {
    guard let selectedRow = selectedIndexes.first else { return }
    dreams.remove(at: selectedRow)
    table.removeRows(at: IndexSet(integer: selectedRow), withAnimation: .effectFade)

    saveDreams()
    }

To save the array when the text was edited afterwards you have to implement the delegate method controlTextDidEndEditing(_:)

override func controlTextDidEndEditing(_ obj: Notification) {
saveDreams()
}

and in Interface Builder connect the delegate of the text field in the table view to the view controller.



Related Topics



Leave a reply



Submit