scrolling a readonly cell in NSTableview? - cocoa

I have a table that the user should not be able to edit directly (although user actions may cause changes). One column may contain a string too long for any reasonable size cell, so to see everything there, the user needs to scroll the cell (using arrow keys, for example).
If I make either the column or cell not editible, I loose the ability to scroll the cell.
If I make it editable, of course, I loose the ability to keep the user from changeing it.
(I'm using NSArray controller and a couple of NSObject controllers to get from the model to the table view using bindings. Binding compliance via #property(copy) and #synthesize. Updating the model with setXXXX:xxx).
Thanks,
John Velman

What's wrong with letting the table display tooltips for overflowed contents? This is automatic as of 10.5 if I recall correctly, else you can use the delegate method -tableView:toolTipForCell:rect:tableColumn:row:mouseLocation: for better control.

Related

What is the appropriate UI set up for messaging functionality?

I have an app which allows users to send messages to each. The process is accomplished by saving the sent messages in a local SQLite database, while actually sending the messages to a database and using push notifications to send the message to the recipient's SQLite database. The set up I have works fine. However, what I am confused about is how to set up the actual interactive UI for the user (I am using XCode). I figured it should be a UITableView with each table cell representing a message. However, with this approach I run into a few requirements:
Variable TextView Sizes
Just as with regular iOS messaging, the TextView's size needs to be variable, adjusting its dimensions to fit all of the text in each message. I do not know how to accomplish this. I have a general understanding of how to generally vary sizes, but no clue how to dynamically have it based on the text within that view.
Variable TextView Positions
Again, just as with regular iOS messaging, the textview needs to be offset to either the right or left side depending on whether the sender was the user or who the are conversing with, respectively. I also do not know how to do this, because it changes the center of the textview.
Non-selectability
Xcode allows cells to be pressed. Handling what happens after this selection can be achieved by the didSelectRowatIndexPath tableView function. I can simply not implement this, but clicking on the cell causes it to turn darker to indicate it has been pressed. I would like to eliminate this while retaining the ability to, say, select some of the text and copy and paste it or whatever (just like messaging works normally on your phone).
Other Approaches?
This is the real meat of the question. I have considered the above approach because that is all that I have been able to come up with based on my limited experience with XCode UI elements. If there is a better approach (perhaps even a pod or framework) for this purpose I would love to hear it. I do not need the messaging UI to look amazing, just clean and crisp.
I suggest the following:
Variable TextView Sizes:
I assume you do use auto layout. If you don’t yet, please consider using it since it make life much easier!
If you use a UITableView, you can adjust the height of its UITableViewCells dynamically, depending on the actual content by using self-sizing cells. You can find a tutorial how to do this here.
Variable TextView Positions:
I assume you have a UITextView within a table view cell. In this case, you have to set auto layout constraints to the borders of the cell’s contentView. If you define a custom subclass of a UITableViewCell, you can define in this class 2 IBOutlet properties that are linked to say the left and the right layout constraints (e.g. var leftLayoutConstraint: NSLayoutConstraint). Then, you can set the constraint’s constant property as required when the cell is laid out, i.e. in the layoutSubviews function of the custom table view cell.
Non-selectability:
I am not sure what you mean by „I can simply not implement this“. Please make sure that you set the delegate property of the UITableView to the view controller where you want to handle cell selection. Selecting a cell changes the cells color by default, but you can change this: In the storyboard, select your table view’s prototype cell, and open Xcode’s utility pane (top rightmost button). Under „Table view cell“ you find „Selection“ that you can set to „None“.
I hope this helps!

NSTableView as a form - nextKeyView issue (or how to force load all rows)

Perhaps using an NSTableView as a form is a terrible idea, but I've got it working pretty well in every respect except that you can't tab from field to field.
I have a table with a label column and a field column. I also have an array that keeps track of each row in the table with its accompanying NSTextField control. The controls are set in the array as they are loaded during tableView(tableView: viewForTableColumn: row:).
After the tableview is drawn, I run through each control in the array and set its nextKeyView to the following control.
This works swell, BUT only for those controls which have been displayed on screen. Because the control isn't added until it's loaded, table rows which are off-screen aren't hooked up.
My current approach (which is awful) is to manually scroll the table several times in order to force everything to load, then set all the nextKeyViews. I haven't got it working very well yet, so I was hoping someone had a better idea. Force-loading all views, if it works, should be an OK solution, but there may be something smarter out there too.
I guess the answer is
table.scrollRowToVisible(<row>)
This will show the row you want to see.

XCode iPad split view controller with detail views containing several form controls

Fairly new to Mac and XCode 3.2.6 and iPad. I have a fairly simple business data model to implement on the iPad, but can't seem to find the combination of views and controllers to use.
It's a simple data collection program, but there are too many data fields to fit on a single screen so I've resorted to the Split View approach.
I've got eight rows of table data on the left; RootViewController is the default UITableViewController. I'm trying to write the program such that when any of those table rows are selected, the view on the right (Detail View) gets redrawn and populated with a bunch of different controls (labels, buttons, text fields, etc.) that correspond to the selection on the left. Currently all the Details views are plain UIViewControllers.
For instance, the first "tab" might be titled "Personal", and I need to display fields to collect info such as Name, DOB, Height, Weight, etc. The next one might be "Address" where I need to collect Street, City, ZIP Code, etc. The next one might be "Employer", where I'd like to collect the employer's name, address, phone number, etc. These are mostly static and unchanging, but there are enough fields for about 8 screens worth.
I've got all this laid out in Interface Builder, but when I run it on the iPad simulator and click the very first button on the very first view, the connected delegate isn't called. I've put a breakpoint there and it's not being hit.
Is there some special magic to using simple UIViewControllers on the right side of a UISplitViewController, as far as letting them contain other simple Label, TextBox, and Button controls?
Also is there any special magic in that the framework built the original start-up code with a RootViewController.h/.m and DetailViewController.h/.m pair? Am I correct in thinking that a single detail view represents the entire iPad screen to the right of the Table View, and that to add more "pages" we need to write more files and .XIBs like DetailViewController?
Final question is how to implement the data model for this app. I noticed when the project was first auto-created, there weren't any source files for the model. (Maybe most of the predefined app types don't auto-generate anything for the model, but I understand that's a big part of model-view-controller paradigm.) Anyway these data fields on all the various views will eventually be part of a SQLite record that I'd like to save and load from storage. Where would I begin to wire all that stuff in to all the auto-generated "view centric" code?
If anyone has seen a "how to write real business apps for the iPad" website along the lines of anything like this, please post the link. I'm not trying to display jpegs of various fruits in a single (reused) view on the right side; I'm trying to display several real controls for real-world data collection for a real business app.
Thanks!
Basic things if you haven't already done them:
Have you connected the interface object the user is pressing from it's INSIDE TOUCH UP event to an IBOUTLET that then refreshes the right side?
If you have, and you've mucked about a bit (ie renaming and moving stuff around), try deleting it from the right-click event panel and then reconnecting it to the same IBOUTLET again (you don't have to delete any code).
Also, if you are counting on some event to fire that isn't firing, you should search on that (ie VIEWDIDLOAD NOT FIRING) because that can both occasionally be "broken" (ie no connection to the Files Owner) but more often one might misunderstand when that actually gets fired (ie VIEWDIDLOAD vs VIEWDIDAPPEAR vs VIEWWILLAPPEAR etc.)
For your data model, CoreData is your friend. It provides a modell-oriented approach and easily allows to persist data.
For your navigation needs, I think a tabBarController better suits your needs.
Changing the detail view from the master view can be troublesome, especially when using a NavigationController as detail view. The best way I've found is using the NSNotificationCenter.
When using UISplitview I strongly recommend to support the iPad only when it's a business requirement - there are some changes in iOs 8 that make easier to use.

Cocoa: How to make table view draw custom views in each cell

I am learning Cocoa and trying to create an application for Mac that displays a simple book list. Each book is an NSView with its cover image, title and author. I want to present this list as a NSTableView with a single column and a book view in each cell. However i can't yet figure out how to display a custom view inside a table cell in interface builder or programmatically. Any tips would be very appreciated :)
Inso.
If all of your "book views" are the same size, why not use NSCollectionView / NSCollectionViewItem? It's a much cleaner solution (provided they're all sized the same).
Assuming a collection view wouldn't be a better solution, what you need to do is to write a custom cell. The column owns exactly one such cell, which the table view will use to draw the column's value for each row.
(If you came from the iPhone, yes, this is completely different from UITableView. Each NSTableColumn has exactly one cell, which it uses for every row.)
If you're using your NSView class somewhere else, then you could make it into a subclass of NSControl and have it use another instance of the same cell class. Like most controls, all the real work would be done by the cell, which enables you to reuse that behavior in multiple controls (your single control and your table view).
See Control and Cell Programming Topics for more info.
Apple added view-based table views in Lion, so you should be able do this natively with NSTableView, now.
(You still can't put an NSView in an NSCell—that wouldn't make sense. But you can have views instead of cells in a table view.)

NSTableView and NSOutlineView drag-and-drop

I have an NSTableView and an NSOutlineView, both with their content provided by bindings, that I'd like to have some drag-and-drop functionality:
Drag rows from Table A onto a row of Outline B, where they will be copied into a data structure which the row in Outline B represents.
Drag a row from Outline B onto another row in Outline B, which will copy the data represented by the first row into the data represented in the second row.
I've read Apple's drag-and-drop documentation and gotten just about nowhere. It doesn't really seem to apply to what I need to do. What am I missing?
The page you linked to is pretty clear about what you need to do. In table A's data source, implement registerForDraggedTypes: and tableView:writeRowsWithIndexes:toPasteboard: to put some private TableAPasteboardType data on the pasteboard.
In outline B's data source, implement the same two methods and put some private OutlineBPasteboardType data on the pasteboard.
Finally, implement tableView:validateDrop:proposedRow:proposedDropOperation: and tableView:acceptDrop:row:dropOperation: to check the pasteboard for either TableAPasteboardType or OutlineBPasteboardType and make the appropriate changes to your bound model, depending.
It's pretty straightforward once you just plow in and do it.
You need a data source—AFAIK, you can't make this happen with Bindings alone.
The unfinished Adium Xtras Creator, which is under the BSD license, includes an array controller that you can set as the data source to get drag-and-drop in a Bindings-powered table view.
This requirement may not apply to NSOutlineView and NSTreeController. I haven't tried that.
In MacOS 10.7 some new protocols were added to implement this.
There is a lack of documentation for tables at the moment but you can find some nice examples:
DragNDropOutlineView
SourceView
TableViewPlayground
For NSTableViwew the Protocol NSTableViewDataSource defines the following methods:
(BOOL)tableView:writeRowsWithIndexes:toPasteboard:
tableView:validateDrop:proposedRow:proposedDropOperation:
tableView:acceptDrop:row:dropOperation:
For NSOutlineView the Protocol NSOutlineViewDataSource defines the following methods:
(BOOL)outlineView:writeItems:toPasteboard:
(NSDragOperation)outlineView:validateDrop:proposedItem:proposedChildIndex:
(BOOL)outlineView:acceptDrop:item:childIndex:
These are the minimum requirements to implement for each view type.
The use cases are quite similar.
If the toPasteboard: method returns YES, the drag is started.
The validateDrop: method controls which target node is allowed by updating the marker in the view
Return YES for the acceptDrop: method if the drop was successful
This lead to two sub-usecases you have to manage. The first one is a drag & drop within the same view or the same operation between two views. Additionally you may distinguish between move, copy or delete operations. A nice example is how the breakpoints work with drag & drop in Xcode.
The tableView has some additional methods to customize drag & drop, but the ones I mentioned are the key methods to get it working.

Resources