I would like to add copy (Command + C) functionality to my NSTableView for a row (or multiple rows) that the user has selected. Based on what I read the copy functionality in the Menu Item should be active automatically if you implement copy in your TableView Controller Delegate.
I've tried adding in the NSTableViewController (is the delegate and data source of the table view) the following things with no luck, the copy menu item still appears greyed out:
override func copy() -> AnyObject {
print("TEST: copytriggered") /Here i would copy to clipboard the selected rows/
return true
}
2.
Conforming to NSCopying, implementing copyWithZone...
3.
Trying 1 and 2 in the window controller and app delegate.
Adding func tableView(_ tableView: NSTableView,
pasteboardWriterForRow row: Int) -> NSPasteboardWriting? in the TableView data source.
I have no clue what to do at this point, any help appreciated.
Thanks,
Marc
Just got the answer, publishing here for future reference.
You are confusing the Copy edit action method with the methods for making a duplicate of an object. The NSCopying protocol and the copyWithZone() method are for the latter, enabling an object to create a copy of itself. Likewise, the copy() method is just a convenience cover method for copyWithZone().
The action method for the Copy edit menu item is subtly different. It's "func copy(_ sender: AnyObject?)". That's the general form for all action methods, taking a sender argument and not returning anything. You need to implement that method.
Finally, tableView(_:pasteboardWriterForRow:) is generally only used for drag-and-drop, when the user drags a row.
Related
I'm trying to modifyt this repository which I forked https://github.com/vinnytwice/BicycleSpeed
but without the use of the tableviews because i'm interested in display the data like speed cadence and distance inside a more graphically designed InfoSpeedoViewController.
I don't manage tableviews controller yet so I can't understand how and where to modify the project.
Can anybody help to point me in the right direction?
my version will have just two ViewControllers :
MainViewController with a ScanButton and SpeedoViewController
So far I deleted the InfoTableViewController.swift, that is just drawing the tableview. but I'm stuck in modifying MainViewController according to my needs. I don't understand the override function prepare(for segue ) part of the code. it passes data to the InfoTableViewController with the first if statement so I don't need it, but with the second if statement it starts the scan function bluetoothManager.startScan() and passes data to ScanViewcontroller via it's UINAvigationController and than to the tableView in the ScanViewController. Am I right?
If so, could I just call the scan function and pass data to my SpeedoViewController instead?
#IBAction func scanButton(_ sender: UIBarButtonItem) {
bluetoothManager.startscan()
performSegue(withIdentifier identifier: MainToSpeedoSegue, sender: self)
}
I don't really understand the relationship with scanViewController I guess. does data end to the infoTableView anyway?
thank
Finally found the solution. it was to change the tableViewController for a normal ViewController having labels to display values. Change the references from the tableViewController to the ViewController, and link the returned values to the labels inside the function that was receiving the continuously updated values.
Pretty easy once decoded the data flow.
The documentation for the NSTableViewDataSource protocol says
This method is mandatory
and if you create a new NSTableViewDataSource the compiler asks you to provide this method as well as numberOfRows(in tableView: NSTableView).
So far, so good. And if you provide it, it promptly gets called once for every row... but if you delete it, the table seems to work every bit as well as it does without. There seems to be absolutely no connections in a view-based table to this method: in the NSTableViewDelegate's tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) method, I return new views based on the content array of my datasource, and if I stick a bunch of nonsense data into objectValueFor: row (up to and including returning the same string - my table objects are not strings) is has no effect whatsoever because I'm setting the values of my NSTableViewCells in viewFor tableColumn:.
If I'm handling selection changes (and anything I want to do with objects) by retrieving the corresponding value from the datasource directly (e.g.)
func tableViewSelectionDidChange(_ notification: Notification) {
print(dataSource.allItems[tableView.selectedRow])
}
is there any reason to implement this method? I cannot see any point where that object is actually used, and it feels like an artefact from cell-based tables.
I don't want to break my code by leaving out a necessary method, but since I'm about to try something weird and wonderful with a custom datasource, I also don't want to overcomplicate my code with a method that gets called, but the result of which seems completely meaningless.
If the cell view responds to setObjectValue:, then the table view calls that method and passes in the object value for the row that was obtained from tableView(_:objectValueFor:row:).
NSTableCellView does respond to that method and is a common cell view class. NSTextField does, too; it actually inherits it from NSControl.
In your case, your cell view either doesn't have an objectValue property or, more likely, you're just not using it.
One common configuration is to use NSTableCellView as the cell view and then use bindings to bind the subviews to key paths going through its objectValue property.
I am new to iOS development, and I wonder how to do the following task:
I want the user to navigate through a multi-level menu. I have UITableViewController with two different kinds of cells.
When clicked on cell type number one I want to reload the UITableViewController with different data. (A click on the other cell does something else.)
Do I have to set up a different UITableViewController in the StoryBoard or can I reuse the existing one and segue from and to the same one? I don't know how many levels I will have in the end because the data comes from a remote source. I could have two different UITableViewControllers (because there is one different button), but I'd prefer to do it all in one (and try to hide and show the button when needed).
Anyway, I need to reuse the same class but change the data for each instance. How can I do that? I also need to restore the old state (last used data) of the controller when going back - or does this happen automatically - is it an "unwind" anyway?
Which methods should I override to delegate the new data?
I tried several tutorials but couldn't yet find the information needed.
Thanks in advance
Read up on Nav Controllers, I'm pretty sure this is what you'll use.
Add UITableViewDelegate to your ViewController press command and click on it for more information.
You can always just use a simple variable to keep track.
Declare a variable var step = 0
Then in your
override func prepareForSegue(){
step += 1 //and pass that variable to the next view and so one, incrementing by one each time.
}
Then in your
viewDidLoad(){
switch step{
case 0:
//add this data
case 1:
//add this data
case 2:
//add this data
default: break
}
I've been migrating my code to Swift and now I'm trying to modernize the UI by switching to view-based table views (OS X). With the cell-based tableview, providing accessibility title, etc. was as easy as overriding the func accessibilityTitle() on the cell (it was a subclass of NSTextFieldCell) - but unfortunately, with NSTableRowView, it's not as easy.
I've overridden pretty much everything I can think of, but the VoiceOver still reads "Table View Cell" and nothing else. The overridden methods don't even get called.
I've also overridden func isAccessibilityElement() -> Bool, func isAccessibilitySelectorAllowed(selector: Selector) -> Bool, func accessibilityIsAttributeSettable(attribute: String) -> Bool to always return true. These methods don't even get called.
I've also tried for the cell to conform to NSAccessibilityStaticText, but that's not possible in Swift, so I've tried a hack, overriding conformsToProtocol(_:), but that never gets called either.
Another thing I've tried was overriding func respondsToSelector(_:) to check what selectors is the runtime checking, but alas nothing helpful gets checked.
Is there anyone who's tried solving this? All I want is to supply VoiceOver with a custom string to be read out...
I had the suggestion to use function textDidChange() to perform code inside this function automatically. It is working. It is in my Controller class.
Now I am going to use this approach for creating automatically, inside of textDidChange(), a dictionary variable from text, when user is typing in NSTextView. Then, I need this dictionary for the NSTableView functions, to display a Table in application corresponding to the text typed by user.
Question is how to make accessible this dictionary from textDidChange(_:) function for the NSTableView functions like
numberOfRowsInTableView(tableView: NSTableView)
and
tableView(tableView: NSTableView, viewForTableColumn tableColumn:
NSTableColumn?, row: Int) -> NSView?
All in the same Controller class.
I am not sure if same dictionary will be your datasource for the tabelview .But for this method you can simply call reloaddata function of tableview to after updating your tableview datasource .