I've been developing on iOS for some time, but am very new to Cocoa development, and something seemingly very simple is stumping me.
I have an NSTableView, hooked up to a subclass of NSWindowController as both datasource and delegate. I have an array of "File" objects (my model class) and want to populate one column of my tableview with file types, and another with timestamps.
The dataSource methods are definitely being called, as verified by setting breakpoints. In fact, I end up with an appropriate number of rows that are selectable...but none of them display anything. I even tried returning an arbitrary string literal in objectValueForTableColumn, for all rows and columns, and still nothing.
I think I'm probably stuck on how tableViews work in iOS, but obviously they are very different here...I am used to configuring and returning a cell myself, but here we just pass AnyObject??? How exactly does the tableView know how to display AnyObject? I'm really struggling with the conceptual understanding here. Appreciate any help.
Related
Please note this is not an iOS question.
I have an NSView-based app (i.e. not document-based), and I’d like to bolt on a printing subsystem. I can get NSViews in my main controller to print ok. However, I want to have a special view constructed just for printing. The view should not show in the app’s window. The view contains two NSTextFields, two NSTextViews, and 5 labels.
I cannot seem to figure out a way to do this. I have tried various forms of these examples:
Add an NSView to my main view window? Seems logical, but it’s awkward in a storyboard, (I can’t position the view in the storyboard).
Programmatically create a custom NSView with a xib?
For this, I’ve tried:
#IBOutlet weak var printView: NSView!
….
let printOperation = NSPrintOperation(view: printView!)
This results in the comprehensive "fatal error: unexpectedly found nil while unwrapping an Optional value” message.
The outlets are configured correctly (I think)
A seperate ViewController? If so, how can I avoid having two print buttons — one to call the print controller, and the second, to print the PrintController’s view.
I’ve tried reading the Apple docs, but they are not the way I learn best. There are also no Print documents in Swift that I've found. I’ve waded through many SE questions, but have come up blank. Could you point me towards a solution please.
I think the specific problem here is that you're never causing the view to be loaded.
You can double check whether this is the case by overriding the viewDidLoad method on the controller. If it's never called, your view is never loaded from the nib.
Normally the UI machinery takes care of all that when you display a view controller, which is why it can be so confusing when it doesn't happen.
You should be able to trigger the view load by accessing the view property on the controller. e.g.
_ = self.view // Touch the view to force it to load
https://developer.apple.com/documentation/appkit/nsviewcontroller/1434401-view has some additional information.
You can also call loadView() directly although that's usually frowned upon.
I am trying to bind a NSPopUpButton in a view based NSTableView with NSArrayContollers using Xcode 8.1. I have an macOS app that had been using a cell based NSTableView and I would like to convert it to a view based table, however, I have been completely unsuccessful in doing this. I have looked at all the various wed postings, but nothing seems to work for me. I have been working on this for over two days.
Here is my design:
accountArrayController is bound to the larger table and this all seems to work just fine.
patientArrayController is aNSMutableArray of NSString's that contains the list of patients to be populated in the menu items of the NSPopUpButton.
Here are the actual bindings for the NSPopUpButton
I am guessing that the problem is in the Content Values bindings, I have tried many variations. When I compile this, I get
.../xxx.storyboard: Exception while running ibtool: *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil
However, when I try other variations, Xcode (really ibtool) hangs for a long time and then exits with an error code of 255.
How can I resolve this? I'm happy to provide other binding information and code blocks, if needed.
The model attribute name you used in the NSTableColumn bind, you want to also use in the Table Cell View bind - 3rd level down from table column. It should have filled in already 'objectValue' or 'selection' or 'arrangedObjects', just add . and you should be good.
I am quite new to NSTableView but as I tried to get things straight, I took a look at InterfaceBuilder!!
TableView hierarchy
I understand that objects are responsible for scrolling and clipping. TableView is the real NSTableView instance. The object titled function list ist the NSTableColumn below that is my TableCellView objects. What I don't understand is the object TextCell. It doesn't seem anything to do. Even wrong colors and alike have no effect at all. I am using a view based variant. Is the TextCell solely for cell based TableViews?
I found that part not quite well documented. I am planning on building custom views for my table. So I was thinking a thorough understanding would be a good approach.
Yes, it's strange that that's still there. It's useless and has no effect on anything, but you can't delete it. Ignore it.
I'm new to Cocoa and Objective-C, so I'm following the Lynda courses and learning a lot. Thing is, I've encountered a problem that I cannot figure out, even though I seem to be doing it exactly the same way...
Basically, I'm trying to get a Table View hooked up through bindings to an Array Controller, just to list out the contents of a simple NSMutableArray in my code. I'd gotten it all hooked up properly, but no matter what I did it wasn't displaying anything when I ran the program.
Here's where it gets weird: on a lark, I added a "+" button and hooked it into the "add" function of the Array Controller, and when I ran the app and clicked that button, it not only added a new line, but it displayed the whole array as well! Apparently everything had been hooked up properly the whole time, it just wasn't displaying the information. Further experimentation revealed that I could make any changes I wanted to the array, whether in the original code or during the runtime of the app, but they would only be updated in the Table View when I clicked that "+" button.
I feel like this is probably a simple solution, just some "Continuous" box that needs to be checked or something, but I cannot for the life of me find it... Can anyone point out what I need to do to get my TableView to show its contents automatically?
(Also, I don't know if this is related or not, but none of the "Model Key Path" fields in the inspector are offering suggestions as I type, which they do in the Lynda course. The app works fine if I manually type everything in, but it says "no completions found" the whole time.)
Thank you in advance for helping out a n00b!
none of the "Model Key Path" fields in the inspector are offering suggestions as I type
As I understand it this is probably because the NSMutableArray that holds your data array i.e. dogPound or similar, isn't also declared as a property, only an instance variable.
Declare the property #property NSMutableArray * dogPound; and change the instance variable declaration to _dogPound and I think interface builder should offer you the auto-completes.
I'm new to Cocoa and Objective-C
Me too.
I'd gotten it all hooked up properly,
In about 30 minutes, I can get everything setup with a custom class like Dog, and another class called AppController that consists of one instance variable: NSMutableArray* dogPound. The init() method for the AppController class creates the array and adds some Dog instances to the array. I also bound an NSArrayController to the dogPound array, and I bound the NSTableView columns to the NSArrayController. After I Build&Run the NSTableView displays the information for each Dog instance in the dogPound array.
I also tried a simpler version where there is no Dog class and the array in the AppController class just consists of some NSString objects. Once again, I was able to successfully bind an NSArrayController to the array and bind the table's columns to the NSArrayController, so that an NSTableView displayed all the NSString's in the array.
You need to post your exact code, and you need to write down every step you did in IB, which of course is a huge pain in the ass, but it's the only way anyone will be able to help you.
Here's where it gets weird: on a lark, I added a "+" button and hooked
it into the "add" function of the Array Controller, and when I ran the
app and clicked that button, it not only added a new line, but it
displayed the whole array as well!
Of course. The add: method in the NSArrayController adds a new item to the array and then signals the NSTableView that it should reload the data, i.e display everything that's currently in the array.
I feel like this is probably a simple solution, just some "Continuous"
box that needs to be checked or something,
Nope, nothing like that.
none of the "Model Key Path" fields in the inspector are offering
suggestions as I type
Lack of autocompletion choices is a big hint that you are doing something wrong--even though I find I can't always figure it out, so I just keep typing. Did you remember to start your bindings in the Attributes Inspector(Object Controller section) for the NSArrayController? In IB, did you create an instance of your AppController class, or whatever you called the class that contains the NSMutableArray, by dragging an Object onto MainWindow.xib?
I have an NSTableView with a single column, which gets its data through an NSArrayController bound to a Core Data entity. The data feed works great, and I have been able to get drag and drop working by implementing the methods
– numberOfRowsInTableView:
– tableView:objectValueForTableColumn:row:
as well as the specific drag and drop methods
– tableView:acceptDrop:row:dropOperation:
– tableView:writeRowsWithIndexes:toPasteboard:
But do I really have to implement the first two methods even though the tableview is fed data through the array controller? I tried commenting out my implementations, but then I get errors in the console saying "Illegal NSTableView data source". The documentation for the NSTableViewDataSource protocol says that the methods are optional if the application is using Cocoa bindings, so obviously, I'm doing something wrong.
The question: How do I make the tableview use its existing binding and still support drag and drop?
I believe you do need to implement them to silence the complaint. I believe when used with Bindings the values returned by these data source methods are ignored. So for -numberOfRowsInTableView: you can return zero; for -tableView:objectValueForTableColumn:row: you can return nil.
You do not need to implement these methods. It seems pretty shaky, but I silenced them by re-establishing the datasource connection in Interface Builder. I think perhaps if you add the datasource after you add bindings, it silences the warning.