Multiple UITableView but some rows smaller than others - xcode

I have multiple UITableViews for layout purposes on the screen. These are functionally working fine, I'm just boggled as to why they are displaying differently.
My 3 table views are: loginTableView, forgotPass and openAccount The delegate and datasource of all 3 is file's owner. This is what I have on the viewDidLoad:
#define TABLE_CELL_HEIGHT 50;
loginTableView.rowHeight = TABLE_CELL_HEIGHT;
forgotPass.rowHeight = TABLE_CELL_HEIGHT;
openAccount.rowHeight = TABLE_CELL_HEIGHT;
The loginTableView cells show up fine but the other two tables' cells are smaller in height than it. I'm using a custom method to create the cells (same method for all tables) and I can't spot any difference between how the different tables are set up.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return TABLE_CELL_HEIGHT;
}
try implementing this method in your tableView delegate.

Ah - it looks like the correct table view had "Separator = None" set in interface builder where the other two table views did not. This was adding a separator and making them the tiniest bit smaller than the other table view.

Related

NSView-based table view with auto layout grows, but does not shrink rows

I have a NSTableView in view-based mode (not cell-based) with usesAutomaticRowHeights=YES. The rows have dynamic height that might change at any time. This setup successfully grows table view rows (row content is never clipped), but table view rows don't shrink to the intrinsic row view height when rows get shorter. Calling noteHeightOfRowsWithIndexesChanged: on the table view after layout does not seem to fix the problem, my tableView:heightOfRow: is also not called again after noteHeightOfRowsWithIndexesChanged:.
Is there anything I have missed/isn't documented about using auto layout in NSView-based tableviews with variable row height? After all, growing rows always works without any additional code, they just do not shrink on their own.
NSTableView* tv = [[NSTableView alloc] init];
[tv setTranslatesAutoresizingMaskIntoConstraints:NO];
[tv setUsesAutomaticRowHeights:YES]; // Use auto layout for row height
NSTableColumn* column = [[NSTableColumn alloc] init];
[tv addTableColumn:column];
// Set table view data source and delegate, rows are then loaded...
After debugging the default table view layout for a long time, I finally found the issue. The table view row views come with some autoresizingmask settings that interfere with content, when using autolayout for the row content views. You need to set the row view's translatesAutoresizingMaskIntoConstraints to NO. This can be achieved for a view-based NSTableView using the delegate method tableView:(NSTableView *)tableView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row:
- (void)tableView:(NSTableView *)tableView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row
{
// Remember that rowView != row content view!
[rowView setTranslatesAutoresizingMaskIntoConstraints:NO]; // Disable constraints interfering with row view content
}
Interestingly, this does not seem to be an issue if content does not shrink past the initial row height or maximum row height it has grown to, due to dynamic height increases.

how to reference NSTableView inside NSView Class (Cocoa)?

I m trying to implement a mac application, basically I have a NSTableView inside a NSView.
I implemented a drag & drop of multiple files feature on the NSView, now I want to update NSTableView with the files names just dropped.
So I need to reference NSTableView in my NSView and try reloadData to reload tableview.
I have tried initialised tableview controller in NSView and it seems not working?
MyTableController *testController = [[MyTableController alloc] init];
testController.nsMutaryOfDataObject = [[NSMutableArray alloc]init];
int i;
for (i = 0; i < 20; i ++) {
NSString * zStr1 = [[NSString alloc]initWithFormat:#"%d",(i + 1) * 10];
NSString * zStr2 = [[NSString alloc]initWithFormat:#"%d",((i + 1) * 100) + 2];
NSString * zStr3 = [[NSString alloc]initWithFormat:#"%d",((i + 1) * 1000) + 3];
MyDataObject * zDataObject = [[MyDataObject alloc]initWithString1:zStr1
andString2:zStr2
andString3:zStr3];
[testController.nsMutaryOfDataObject addObject:zDataObject];
} // end for
[testController.idTableView setHeaderView:nil];
[testController.idTableView reloadData];
Xib file as below:
Anyone can help me out?
A tableview has TWO different aspects: the view (presentation of data; drag and drop) and the datasource (an array combined with an array controller).
Usually a tableview leads a life on its own, independent from the view it is positioned in. So concentrate yourself first on the datasource-aspect and second on the drag-and-drop-aspect.
"TableView reload" simply means load the assigned array again.
For the data structure in your array a model is strongly recommended.
The names of the different parts in your model are bound to the columns in your table.
The array is the datasource to your tableview.
Use an array controller.
Your fileNames must be in the array, organized in the manner of the model...
Because a tableview is always part (subview) of an NSScrollView, assure that your really have selected the tableview itself.
In the documentation are fairly good samples for working with tableviews, with and without bindings, also "TableViewLinks" handling URLs...
Your code is missing the basic methods for a tableview to work, so start from scratch with a sample.
Sounds, as if the TV is working correctly
and
you have the fileNames available in the NSView class
and
don't want to implement the drag and drop functionality also in the class for the TV.
Then you could use a notification that is sent from the NSView-class to the TV-class with the fileNames-data attached. After receiving in the tv-class the fileNames could be used/added to the array. I once have created such a solution, it works perfect.
It also assures encapsulation of the classes.

Set custom HeaderView for each Column in NSTableView

Is it possible to set a custom header view for each Column in NSTable ? When I drag drop a table to a view, I can see that there is only 1 header view for both the columns. I referred this answer and implemented same in my table class.
- (NSTableHeaderView *)headerView{
CustomHeaderView *customHeader = [[CustomHeaderView alloc] initWithFrame: ...];
return customHeader;
}
But this will add one view for all the table columns.
If my understanding is correct, TableHeaderView is only one view, and default header view looks like it contains 2 cells for both columns but its actually one view. ? If so how do I go about having separate views or mimic the same behaviour for custom header view ?

Add a custom section to UITableView when working with NSFetchedResultsController

I'm working with NSFetchedResultsController to fill one of my UITableViews with data grouped into sections. Now I want to add a new section atop all the fetched sections created by data that would not be fetched (I'm creating an additional array for that). Is there a nice way to insert that array without breaking all the nice NSFetchedResultsController behavior?
Update
What I've tried so far is to manually adjust every use of the indexPath. When ever a method (i.e. -tableView:numbersOfRowsInSection) get's called I check if it's the first section and if so I would take the data from my array instead of the NSFetchedResultsController. If not, I would just create a new NSIndexPath with the original indexPath's row and the section - 1 to access the fetchedResults. This seems to be a rather naive approach. At least, this does not work for me (yet).
Thanks!
–f
I created a UITableViewDataSource with a mixture of static and dynamic sections. I do it by modifying NSIndexPath like you planned. Important is to modify the NSIndexPath in the delegate methods of NSFetchedResultsControllerDelegate, too:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
indexPath = [NSIndexPath indexPathForRow:indexPath.row + 1 inSection:kSectionWithAdditionalRowIndex];
if (newIndexPath) {
newIndexPath = [NSIndexPath indexPathForRow:newIndexPath.row + 1 inSection:kSectionWithAdditionalRowIndex];
}
[super controller:controller didChangeObject:anObject atIndexPath:indexPath forChangeType:type newIndexPath:newIndexPath];
}
The sample is taken from a subclass of my class CBUIFetchResultsDataSource.m, which is a generic UITableViewDataSource powered by a NSFetchedResultsController. I had to also overwrite -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section, -(id)objectAtIndexPath:(NSIndexPath*)indexPath and -(NSIndexPath*)indexPathForObject:(id)object.

How to add row-span in view-based NSTableView?

I'm trying to get a table layout as shown below working with view-based NSTableViews that have been introduced in Lion.
There were multiple approaches described for cell-based NSTableViews, e.g. Mimic the artwork column, but these don't really apply for view based table views.
The idea is that the table gets populated by an array of objects, in one (or more) column spanning rows indicating that objects share some data in common. numberOfRowsInTableView: returns to total number of items (19 in the case of the attached image).
Has anyone tried something like this?
Layout
I was able to do this by using two separate NSTableViews that have their NSScrollView's scrolling synchronized. To learn how to synchronize multiple scroll view's (with the exact subclass code) read Scroll View Programming Guide for Mac - Synchronizing Scroll Views
I have groupTableView that has a single column and shows the views that represent the group. I also have itemTableView that has columns representing the items of the group. I use the same delegate/datasource methods with if-else-statements to check which NSTableView is being used and respond accordingly with the proper # of rows, cell view, etc.. Additionally, I implement the following delegate method to adjust the group table view's row height to be equal the sum of the item row heights of the rows in the group:
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
{
if (tableView == self.groupTableView) {
NSUInteger firstRowIndexForGroup = ...;
NSUInteger lastRowIndexForGroup = ...;
CGFloat groupHeight = 0.0;
for (NSUInteger currentRowIndex = firstRowIndexForGroup; currentRowIndex <= lastRowIndexForGroup; currentRowIndex++) {
groupHeight += [self.itemTableView rectOfRow:lastRowIndexForGroup].size.height;
}
return groupHeight - [self.itemTableView intercellSpacing].height;
} else {
return self.itemTableView.rowHeight;
}
}
You must also call -noteHeightOfRowsWithIndexesChanged: every time the table view needs a group view because the height changes according to the number of rows in the group.
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
if (tableView == self.groupTableView) {
GroupRowView *view = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
// configure view
[tableView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndex:row]];
return view;
} else {
ItemRowView *view = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
// configure view
return view;
}
}
I disabled row selection and horizontal and vertical scroll bars on the group table view. I also made the horizontal grid solid for both table views. Finally, I position the group table view directly next to the item table view with no gap in between so it appears as if it's simply another column in a single table view. The result is a flawless implementation that has zero lag between the table views. To the user, it appears as if it's a single table view.
Could you not use an NSOutlineView instead? It's specifically designed to have grouping support.

Resources