NSTableView inside NSOutlineView and NSView-Encapsulated-Layout-Height - xcode

I'm building a OS X application using Swift and Xcode 6.4 on OS X 10.10.5.
On a specific view of my application I would like to have a view like this one Xcode has on the Data Model Editor.
I tried to replicate this view using an OutlineView where each "row" would have a title and a TableView plus two buttons (for the plus and minus buttons). For tests purposes I've separated the title for the TableView+Buttons, something like this (this was one of many different attempts).
Everything is working as expected except the View that has the TableView+Buttons, that is never higher than 17 pixels. If I define everything in one view, I have the same problem. I've tried defining the needed constraints but in that case there is a problem with a constraint that seems automatic called NSView-Encapsulated-Layout-Height, that forces the height to 17 pixels:
NSLayoutConstraint:0x61800008ea10 'NSView-Encapsulated-Layout-Height'
> V:[NotesTable(17)] (Names: NotesTable:0x60000012e2e0 )
I'm not defining any constraint to 17 pixels, I've tried testing with some parameters that usually insert automatic constraints (autoresizesSubviews/translatesAutoresizingMaskIntoConstraints/autoresizingMask) but I was only able to translate that 'special' constraint to another format and the grow doesn't get bigger.
Tried to search the web but I only get cases where that Encapsulated constraint makes sense and is useful.
Do you know where or how can I disable that constraint or change its value to the height I need?

Table and outline views on OS X do not support automatically determining the row height from the dynamic height of the cell views. They either have an explicit static row height, a static row height determined by the design-time height of the cell views, or a dynamic row height determined by the delegate and its implementation of -tableView:heightOfRow: or -outlineView:heightOfRowByItem:.
For your case, you're going to have to implement the delegate method. Furthermore, the delegate method can't query the actual cell view because it may not exist and the outline view would need the row height before creating it. So, the delegate has to compute it some other way.
One way is to keep a standalone view hierarchy of a prototypical cell view. When the delegate is asked for the row height, it configures that view hierarchy as it would be for the actual cell view for that row/item, forces it to lay itself out, and then queries its height. Configuring the view hierarchy may be as simple as setting the objectValue of the top-level view (if it's an NSTableCellView, a control, or otherwise implements the setter). But if your delegate does other configuration, such as in its -outlineView:viewForTableColumn:item: method, then you'll need to replicate that for this prototype view hierarchy.
Also, when any factor that would affect a row's height changes, you have to call the outline view's -noteHeightOfRowsWithIndexesChanged: method to let it know that, so it will re-query your ...heightOfRow... method.
Finally, bare table views are not especially amenable to being constrained to sibling views or their superview. They really want to live in scroll views and continue using springs-and-struts to position and size themselves. See my answer to another question for a discussion of this. It is possible that this has been improved in recent versions of the OS. Anyway, you're going to have to observe the table view's frame-change notifications (and ask it to post such notifications) in order to know when it grows. And your ability to set constraints to relate it to any other views in the cell view hierarchy will be severely limited, because it will need translatesAutoresizingMaskIntoConstraints turned on.

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!

Setting the constraints of a views subviews without knowing the amount of subviews there are

So my view is pretty simple to setup but I can't figure out how to do a specific task.
So what I need to do is take in an array of strings, each one of these strings are a country ISO3 format code which in turn have a corresponding flag associated with it. Now after I add the flags to the view I need to be able to set all the constraints.
So first I add the imagesviews to the view, that works fine but now when I get to the updateConstraints method I am unsure how to proceed since I have an unknown amount of subviews.
So each subview will be placed about 5 spaces apart from the flag before it and the top of the image and bottom of the image should span the views height.
How can I write code that handles an arbitrary number of subviews?
So first i add the imagesviews to the view
As you do that, also add each view's constraints. Since you are looping through the flags / image views, you know whether there was a previous image view and if you've taken a little care, you have a reference to it. Thus, there is actually not a lot of code — it's a loop, and not a very long one — and it isn't at all difficult.
As an alternative, I suppose you could use a UIStackView (if you are not running on iOS 8). It will just take all the image views and space them out with constraints for you; all you have to do is decide on its size, which you can presumably do by counting the image views.

How to change NSTableCellView's height when using storyboards in Interface Builder

When I create a non-storyboard OSX app and add a Table View from the Object Library to my main window in Interface Builder, I am able to change the height of an NSTableCellView inside that Table View.
Doing so, automatically changes the TableView's row height (even when I run the app).
But when I create a storyboard app and follow the exact same steps (adding Table View, changing cellView's height), the TableView's row height does not change, resulting in the NSTableCellView being cropped when I run the app.
I know you can implement the heightForRowAtIndexPath method, but I'm just wondering why this works when using xib files and stopped working when using storyboards. (I really find it a lot easier to design interfaces graphically instead of writing down arbitrary numbers in a text file.)
Is there something I'm missing here? What is the easiest way of doing this, using storyboards?
You have to set the height in the table view (size inspector -> size style: custom and set row height value).

How to correctly add NSComboBox to view-based NSTableView in Interface Builder

I'm basically asking how do you correctly add a Combo Box to a Table View with correct layout i.e. so that appears as if you were adding a ComboBox cell to a cell-based Table View. Currently when I add it to the Table Cell View it doesn't fit (bottom half chopped off) and doesn't behave as its supposed i.e. focus ring is messed up, arrows messed up, not aligned correctly.
I have searched the net couple of times over and funny enough I haven't found an answer to this question. If I don't find a solution I might have return to good old cell-based table views.
If the combo box doesn't fit, you need to increase the height of the NSTableCellView. This is done in Interface Builder or, if implemented, in the NSTableViewDelegate method tableView:heightOfRow:.

Programmatically create UI or drag and drop in storyboard for iOS development

First time building a user interface, had a few general questions
1) Does it really matter if you drag and drop view objects into view controller.. or if you programmatically add subviews and specify frames and fonts? What's the better approach to take?
2) In the programmatic approach, I end up guessing frame values, (x,y) points, and then checking in simulator if I like it. Is this the right approach, or are there faster, better ways to build out the UI? Maybe methods I'm not aware of?
3) Any useful tutorials/pointers in the right direction on how to get started?
Thanks!
1) Both approaches are fine, but the Interface Builder is usually better if you have a more static UI. In a more dynamic app (where views appear and disappear, or if you use UIViewController containment), you need to add/show/hide some of the views in the code. Even in that case you can design individual views in the IB, to make sure they look good, and then instantiate and display them in the code.
2) If you design your views in the IB, then the problem of guessing the sizes largely disappears. In some cases it can be useful to have an empty view added in the IB, which acts as a placeholder for your dynamic content. Then, when you add a view to it in the code, you just use the superview's dimensions so your view fills the placeholder.

Resources