App get crashed while loading large amount of data in UITableview - objective-c

I am showing more than 10 columns in uitableview cell and having more than 100 rows but when i scroll tableview or reload table it received memory warning and app get crashed.
And we are also using collapse and expand on this table view.
Following code applied in cellforrowatindexpath
for(i=0;i<[appDel.tempItemDic count];i++)
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(CNT+30, -30, 350,100)];
label.font = [UIFont systemFontOfSize:14.0];
label.text =[tempDic objectForKey:[appDel.arrColumnList objectAtIndex:[[appDel.tempArr objectAtIndex:i]intValue]]];
label.textAlignment = UITextAlignmentLeft;
label.textColor = [UIColor whiteColor];
label.backgroundColor=[UIColor clearColor];
label.numberOfLines=1;
[cell.contentView addSubview:label];
[label release];
backgroundView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"ListItems_secondLevel(3).png"]];
cell.backgroundView = backgroundView;
cell.imageView.image=[UIImage imageNamed:#"arrow.png"];
CNT+=350;
}

You need to create the UILabels only while creating the cell. While reusing the cell, you can get the UILabel using tag and set the value to that. Do not create again and again.
Edit:
In addition to that, as Sarah mentioned, you don't need to do that in loop. As for every cell the method will get called, and you can set the value depend on the indexPath.

you don't need for loop in the method. As objectatIndex works for the same. remove the for loop as you are already using objectAtIndex and try again.

Probably you're not reusing the cell. So if you create 100 cells and each cell has 10 labels at the you will have UILabel views all kept in memory.
You should reuse the cell in this way (code not tested, just to give you an idea, I'm not commenting the way you create the text, I'm concerned only about memory warning):
-(UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// add your code here to get the number of columns; I assume you defined a "getNumberOfColumnsForRowAtIndexPath:" somewhere in your code to retrieve this figure
NSInteger numberOfColumns = [appDel getNumberOfColumnsForRowAtIndexPath:indexPath];
NSString *cellId=[NSString stringWithFormat:#"MyComplexCellID_%d",numberOfColumns];
UITableViewCell *cell = [tv dequeReusableCellWithIdentifier:cellId];
if(!cell) {
// here you create the cell and add the labels; DON'T GIVE TEXT TO THE LABELS HERE
// in order to get the right label give them a tag; e.g. 500 is column 0, 501 column 1,...
for(int i=0;i<numberOfColumns;i++) {
UILabel *myLabel = ...
myLabel.tag=500+i;
}
}
// here you configure the cell
for(int i=0;i<numberOfColumns;i++) {
NSString *columnText = retrieve here your column text;
UILabel *labelColumn = (UILabel *)[cell.contentView viewWithTag:500+i];
labelColumn.text = columnText;
}
return cell;
}

If you are loading a large amount of data in table view I will suggest you
1:-
(void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableview reloadData];
});
}
2:-
(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(q, ^{
NSLog(#"DISPATCH_QUEUE_PRIORITY_HIGH - Main Thread");
[self methodForServerResponse];
});
}
In that methodForServerResponse-
(void)methodForServerResponse{
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(q, ^{
NSLog(#"DISPATCH_QUEUE_PRIORITY_HIGH - Main Thread within Main Thread");
//implement what you stuff need from server
});

Related

Can we set backgroundImage for Section in UITableview?

Can we set Background image for UITableView Section like UITableViewCell backGroundView. As per my research Its not possible & we need to customize the row like section of it.
Cane we able to get better solution apart from this.
Thanks in advance!
In case anyone are still interrested, there is actually a pretty straigt forward solution to this. UITableView will tell you the frames of each of your sections using the selector rectForSection:
Adding a backgroud image to each section would then look something like this (Somewhere in the view controller):
for(int i = 0;i < [self numberOfSectionsInTableView:self.tableView]; i++) {
UIImage *img = [[UIImage imageNamed:#"background"] resizableImageWithCapInsets:UIEdgeInsetsMake(30.0, 30.0, 40.0, 40.0) ]; //In this example the image is stretchable
UIView *borderView = [[UIImageView alloc] initWithImage:img];
CGRect section_rect = [self.tableView rectForSection:i];
borderView.frame = section_rect;
[self.tableView addSubview:borderView];
}
Just remember that if you reload the data in the tableview you would have to redo this as well.
Yes, I am doing this by following way, I think it work for you also,....
-(void)addBackgroundViewForSectionIndex:(int)tagIndex {
for (UIView * subview in tableView.subviews) {
if(subview.tag == tagIndex)
[subview removeFromSuperview];
}
CGRect sectionFrame = [tableView rectForSection:tagIndex];
UIImageView *newView = [[UIImageView alloc]initWithFrame:sectionFrame];
newView.tag = tagIndex;
[newView setImage:[UIImage imageNamed:#"image.PNG"]];
[tableView addSubview:newView];
[tableView sendSubviewToBack:newView];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath: (NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView1 dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [collection objectAtIndex:indexPath.row];
[self addBackgroundViewForSectionIndex:indexPath.section];
return cell;
}
Let me know if any issue,...:)
No, this is not possible using UITableView as it was intended. Section headers, as others have suggested, won't work because they'll only be visible while the header is visible. As soon as it disappears while scrolling up, the background image would disappear.
Your two options are:
Add UIImageView instances directly as subviews to the table view. Not fun, as you'll have to size and position them manually, which is kind of hard to do.
Use UICollectionView, which supports decoration views (exactly what you're looking for).
The UICollectionView method is probably better, but to be honest, either option would require a lot of work.
Swift 5 bare-bones implementation of Jesper's answer.
for sectionIndex in 0..<tableView.numberOfSections {
let backgroundView = UIView() // replace UIView with anything else you want, whether it was UIImage, nibView, etc...
backgroundView.frame = tableView.rect(forSection: sectionIndex)
tableView.addSubview(backgroundView)
}
You can set the Background for Section of TableView.
Have a look at delegate method as below:
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIImageView *bgImgView = [[[UIImageView alloc] initWithFrame:CGRectMake(0.0,0.0,tableView.bounds.size.width,40.0)] autorelease];
bgImgView.image = [UIImage imageNamed:#"yourimage.jpg"];
return bgImgView;
}
Hope this will be helpful to you.
Cheers!
table= [[UITableView alloc] initWithFrame:CGRectMake(7,0, 307, 124) style:UITableViewStylePlain];
[table setSeparatorStyle:UITableViewCellSeparatorStyleNone];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"tablebg_pt12.png"]];
imageView.frame=CGRectMake(0, 0, 307, 124);
imageView.image= [UIImage imageNamed:#"tablebg_pt12.png" ];
table.backgroundView = imageView;
[imageView release];
table.delegate = self;
table.dataSource = self;
// table.backgroundColor=[UIColor clearColor];
[viewTable addSubview:table];

Set Multiple UILabel in a row of UITable

I want to set UILabel in row of table, but the issue is that the number of label each time is different when the app restarts.
Clear that more detail that I want to create a table which has dynamic row and column. Rows are set themselves, but in the column i set the label which is also dynamics, so how can i set that label each time of new web service will call ?
Ex.
row/column
A1 b11 b12 .......b1n
A2 b21 b22 .......b2n
A3 b31 b32 .......b3n
.
.
Am bm1 bm2 .......bmn
where A is row or b is column
You could have a mutable array called rowData for example. In your init/initWithCoder/etc method, you could create another mutable array called columnData for example that could contain the data for each label. Add a columnData object for each row to rowData.
For your cellForRowAtIndexPath method, you could do something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"] autorelease];
int row = [indexPath row];
int i = 0;
int nLabels = [[rowData objectAtIndex:row] count];
UILabel *label;
NSLog([NSString stringWithFormat:#"%d labels", nLabels]);
for (i = 0; i < nLabels; i++) {
NSLog([NSString stringWithFormat:#"%d", i]);
label = [[[UILabel alloc] initWithFrame:CGRectMake(cell.frame.origin.x + (i * 40), cell.frame.origin.y, 40, cell.frame.size.height)] autorelease]; //replace 40 with desired label width
label.textColor = [UIColor grayColor];
label.backgroundColor = [UIColor clearColor];
// set the label text here
[cell.contentView addSubview:label];
NSLog([NSString stringWithFormat:#"%d subviews", [[cell.contentView subviews] count]]);
}
}
return cell;
}
Better option would be just create a UITableView in UITableViewCell and your each label would be cell and you can disable inner tableview scrolling. But you need to make sure that you have calculated inner tableview height properly.
Other solution like adding n number of UIlabel etc wont give you smooth scrolling.
Create cells that have the maximum number of labels you might need. Make their tag be 1,2,3,4... - increasing numbers. Each time you are asked to supply a cell by the table, you either take an old one or new one, decide how many labels you need, make that range of labels visible (ie label.hidden = NO;), then hide the other labels. You will need to change the text of the visible labels obviously.
You use tag method and indexpath.row.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
for (i = 0; i < n; i++) {
label = [[UILabel alloc] initWithFrame:CGRectMake (i * yourWidth, 0, yourWidth + 5, yourHight)];
label.textColor = [UIColor blueColor];
label.tag = (indexPath.row)*100 + i //you can create n labels in a row.
label.text = [NSString stringWithString:#"%d",label.tag];
[cell.contentView addSubview:label];
}
}
return cell;
}
I think it will be helpful to you.
You should consider using a different view, such as DTGridView

UITableViewCell with UILabel subview caching issue

First of all, please don't tell me this is a duplicate. I know this question has been asked and answered many times but I still can't seem to get my code to work even after reading everyone else's solutions.
I'm having an issue with my UITableViewCell that contains a UILabel subview. The UILabel sometimes doesn't appear in certain cells until I scroll away from those cells and return to them. Here is the code I am using to customize the cells:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UILabel *label;
if (cell == nil) {
// cell is nil, create it
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 33)];
label.tag = 888;
} else {
label = (UILabel*)[cell.contentView viewWithTag:888];
[label removeFromSuperview];
}
label.text = #"Label Text";
label.backgroundColor = [UIColor clearColor];
[label sizeToFit];
label.center = CGPointMake(cell.contentView.frame.size.width-label.frame.size.width/2-20, cell.contentView.frame.size.height/2);
[cell.contentView addSubview:label];
// customize cell text label
cell.textLabel.text = #"Cell Text";
cell.textLabel.textColor = [UIColor darkGrayColor];
return cell;
}
It appears as though the label shows up correctly when dequeueReusableCellWithIdentifier:CellIdentifier returns a non nil value but does not show up if the return value is nil and a new cell must be instantiated.
If anyone has an idea of why this might be happening, help would be greatly appreciated.
I see a couple of things you want to do.
1) read up on "sizeToFit" - the description says if the view has no superview you may get weird results.
2) When you create the view, add it to the cell immediately.
3) After you resize the cell, get its size, then compute the proper frame - I'd suggest not using "center" but I do not know that your code won't work for a fact.
4) Before even changing the center to changing the frame, hard code something like this:
CGRect r = label.frame;
r.origin = (CGPoint){ 20, 20 };
label.frame = r;
This will at least convince you that new cells and old cells are working properly. Then you can compute the frame you really want, or further play with center.
Not sure of the cause of your problem, but there are some improvements you could make. Maybe one of them fixes the issue:
In the dequeu scenario, you remove the label from the view, only to add it back. Instead, you should leave it in the view hierarchy.
To avoid having to resize and move the label all the time. Why not make it sufficiently wide, set the text right aligned. That way, you don't have to resize of move the label in the dequeue scenario.
It seems that the issue may be with modifying cell.textLabel. Other posts on this site have suggested that any time this label is modified, a new label is actually created and added to the cell's contentview (as opposed to just modifying the existing label). Setting cell.textLabel.backgroundColor = [UIColor clearColor]; seems to have fixed the problem
I'm still a bit confused about this though because even adding my custom label subview last (after setting properties for cell.textLabel) didn't fix the problem - the background color of cell.textLabel had to be set to transparent/clear.
There are three things out of place:
if (cell == nil) { // cell is nil, create it
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 33)];
label.tag = 888;
[cell.contentView addSubview:label]; // (1) DO THIS HERE
} else {
label = (UILabel*)[cell.contentView viewWithTag:888];
// (2) DON'T DO THIS: [label removeFromSuperview];
}
label.text = #"Label Text";
label.backgroundColor = [UIColor clearColor];
[label sizeToFit];
label.center = CGPointMake(cell.contentView.frame.size.width-label.frame.size.width/2-20, cell.contentView.frame.size.height/2);
// (3) DON'T DO THIS HERE: [cell.contentView addSubview:label];
....
I assume ARC is on, otherwise you need a [label release] after adding it to the contentView.

Weird updates when using reloadRowsAtIndexPaths: in a table

I've got a table where the accessoryView button in the cell is replaced by a custom check mark icon. If the time interval for a pair of temperature settings is enabled, the cell row shows a check mark, along with a time, heating and cooling value. If the time is disabled, no check mark, and time displayed in the timefield.text is modified to state: "Disabled". The code works fine when I use reloadData. However, since I'm updated only one row at a time, that's overkill for the big table that I'm using. I'm trying to use reloadRowsAtIndexPaths: but I get screen updates that affect not only the cell that was clicked on, but the previous cell that was clicked on. I was using no animations (UITableViewRowAnimationNone), but changed that to fading animations (UITableViewRowAnimationFade) to see what was going on. Sure enough, the fading occurs on the desired table row and the undesired table row. Also, the time value for the current cell row appears in the previous cell row time field. Once I stay with clicking on one row, there's no problem with the updates, but once I switch to another row, I have both rows affected the one time. It's like the update method is picking up cruft from somewhere.
I have also tried bracketing the reloadRowsAtIndexPaths: call with calls to beginUpdates and endUpdates, and nothing changes.
Clearly I'm not understanding something fundamental here. What am I doing wrong? Here is the method in question:
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
UIButton *button = (UIButton *)cell.accessoryView;
BOOL checked;
if (intervalDisabled[((indexPath.section * 4) + indexPath.row)] == NO) {
checked = YES;
intervalDisabled[((indexPath.section * 4) + indexPath.row)] = YES;
} else {
checked = NO;
intervalDisabled[((indexPath.section * 4) + indexPath.row)] = NO;
}
UIImage *newImage = (checked) ? [UIImage imageNamed:#"unchecked.png"] : [UIImage imageNamed:#"checked.png"];
[button setBackgroundImage:newImage forState:UIControlStateNormal];
timeField.text = [NSString stringWithFormat:#"%#", [self.dateFormatter stringFromDate:[timeOfDays objectAtIndex:((indexPath.section * 4) + indexPath.row)]]];
//[self.tableView reloadData]; <-- This works fine
NSArray *rowArray = [NSArray arrayWithObject:indexPath];
[self.tableView reloadRowsAtIndexPaths:rowArray withRowAnimation:UITableViewRowAnimationFade];
}
Edit:
OK. Here is code you requested. I hope it helps. I will be glad to post other portions. Sorry, I haven't got the hang for formatting code in this editor yet.
// Customized cell for setpoints
- (UITableViewCell *)setPointsCell:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *temperatureSymbol;
static NSString *kCustomCellID = #"setPointsCellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCustomCellID];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:kCustomCellID] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
}
// Set up the cell.
NSDictionary *dictionary = [listOfRows3 objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"Content"];
NSString *cellValue = [array objectAtIndex:indexPath.row];
//Set properties of label and add its text
cell.textLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
cell.textLabel.text = cellValue;
// Add time field
timeField = [[UITextField alloc] init];
timeField.tag = (indexPath.section * 100) + (indexPath.row * 10) + TIME_FIELD;
CGRect frame = CGRectMake(80.0, 6.0, 90.0, 31.0);
timeField.frame = frame;
timeField.borderStyle = UITextBorderStyleRoundedRect;
timeField.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
// timeField.backgroundColor = [UIColor clearColor];
timeField.textAlignment = UITextAlignmentRight;
// Check and handle situation where time interval is disabled
BOOL rowHasCheck;
if (intervalDisabled[((indexPath.section * 4) + indexPath.row)] == NO) {
rowHasCheck = YES;
timeField.text = [NSString stringWithFormat:#"%#", [self.dateFormatter stringFromDate:[timeOfDays objectAtIndex:((indexPath.section * 4) + indexPath.row)]]];
} else {
rowHasCheck = NO;
timeField.text = #"Disabled";
}
UIImage *image = (rowHasCheck) ? [UIImage imageNamed:#"checked.png"] : [UIImage imageNamed:#"unchecked.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect bFrame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
button.frame = bFrame; // match the button's size with the image size
[button setBackgroundImage:image forState:UIControlStateNormal];
// set the button's target to this table view controller so we can interpret touch events and map that to a NSIndexSet
[button addTarget:self action:#selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside];
button.backgroundColor = [UIColor clearColor];
cell.accessoryView = button;
// Override default keyboard handler so we can use a picker instead
timeField.delegate = self;
[cell.contentView addSubview:timeField];
// Set up termperature (F or C) to display
if (temperatureScale == FAHRENHEIT) {
temperatureSymbol = #"F";
} else {
temperatureSymbol = #"C";
}
// Add heating setpoint field
UITextField *heatingSetPointField = [[UITextField alloc] init];
heatingSetPointField.tag = (indexPath.section * 100) + (indexPath.row * 10) + HEATING_FIELD;
frame = CGRectMake(180.0, 6.0, 52.0, 31.0);
heatingSetPointField.frame = frame;
heatingSetPointField.borderStyle = UITextBorderStyleBezel;
heatingSetPointField.backgroundColor = [UIColor colorWithRed:1.0 green:0.2 blue:0.2 alpha:1.0];
heatingSetPointField.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
heatingSetPointField.textAlignment = UITextAlignmentRight;
heatingSetPointField.text = [NSString stringWithFormat:#"%i %#", hSetpoints[((indexPath.section * 4) + indexPath.row)], temperatureSymbol];
// Override default delegate handler
heatingSetPointField.delegate = self;
[cell.contentView addSubview:heatingSetPointField];
// Add cooling setpoint field
UITextField *coolingSetPointField = [[UITextField alloc] init];
coolingSetPointField.tag = (indexPath.section * 100) + (indexPath.row * 10) + COOLING_FIELD;
frame = CGRectMake(240.0, 6.0, 52.0, 31.0);
coolingSetPointField.frame = frame;
coolingSetPointField.borderStyle = UITextBorderStyleBezel;
coolingSetPointField.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
coolingSetPointField.backgroundColor = [UIColor colorWithRed:0.4 green:0.4 blue:1.0 alpha:1.0];
coolingSetPointField.textAlignment = UITextAlignmentRight;
coolingSetPointField.text = [NSString stringWithFormat:#"%i %#", cSetpoints[((indexPath.section * 4) + indexPath.row)], temperatureSymbol];
// Override default delegate handler
coolingSetPointField.delegate = self;
[cell.contentView addSubview:coolingSetPointField];
[timeField release];
[heatingSetPointField release];
[coolingSetPointField release];
return cell;
}
The main problem is that you seem to be using a single timeField reference across all cells. At a minimum, the timeField should be created separately in each cell (just like the heatingSetPointField) and then extract it from the cell later using its tag.
There are many other issues (eg. text fields will get added multiple times to each cell when a cell is reused).
I think reloadData is "working" because you haven't tried scrolling the table view up/down and seeing wrong data in the cells when they come back into view.
You may want to read the Table View Programming Guide (especially the Customizing Cells section) and start with a simpler table view cell and add one layer of complexity at a time until you reach your goal.

How to add a scrollable NSTableView programmatically

I'm trying to add a tableview to a view in code instead of using Interface Builder and unfortunately it's causing some problems =(
Here's an example of how I'm doing it now.
NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame:someRect];
NSTableView *tableView = [[NSTableView alloc] initWithFrame: scrollView.bounds];
resultsTableView.dataSource = self;
resultsScrollView.documentView = tableView;
[someView addSubview: scrollView];
So basically I'm just putting the tableView inside the scrollView (because that's what IB is doing) and then adding the latter as a subview of the someView. The result is that a tableView appears - but the no data is shown within the tableView. Debugging shows that the dataSource is being asked for how many rows are in the tableView but the method:
tableView:objectValueForTableColumn:row:
is never being called. I suspect that this is because of my way of creating the tableView.
I've tried google but no luck and the "Introduction to Table Views Programming Guide" on macdevcenter wasn't helpful either. What am I missing?
Thanks in advance...
I created the default sample project and then did the following:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSRect scrollFrame = NSMakeRect( 10, 10, 300, 300 );
NSScrollView* scrollView = [[[NSScrollView alloc] initWithFrame:scrollFrame] autorelease];
[scrollView setBorderType:NSBezelBorder];
[scrollView setHasVerticalScroller:YES];
[scrollView setHasHorizontalScroller:YES];
[scrollView setAutohidesScrollers:NO];
NSRect clipViewBounds = [[scrollView contentView] bounds];
NSTableView* tableView = [[[NSTableView alloc] initWithFrame:clipViewBounds] autorelease];
NSTableColumn* firstColumn = [[[NSTableColumn alloc] initWithIdentifier:#"firstColumn"] autorelease];
[[firstColumn headerCell] setStringValue:#"First Column"];
[tableView addTableColumn:firstColumn];
NSTableColumn* secondColumn = [[[NSTableColumn alloc] initWithIdentifier:#"secondColumn"] autorelease];
[[secondColumn headerCell] setStringValue:#"Second Column"];
[tableView addTableColumn:secondColumn];
[tableView setDataSource:self];
[scrollView setDocumentView:tableView];
[[[self window] contentView] addSubview:scrollView];
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
{
return 100;
}
- (id) tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
{
NSString* cellValue = [NSString stringWithFormat:#"%# %ld", [aTableColumn identifier], (long)rowIndex];
return cellValue;
}
You can grab the sample app TableViewInCode
(Oh, to the objective-c dot syntax, just say no. :-)
The result is that a tableView appears - but the no data is shown within the tableView. Debugging shows that the dataSource is being asked for how many rows are in the tableView but the method:
tableView:objectValueForTableColumn:row:
is never being called.
It's not asking you for the object values for any columns because it doesn't have any columns. Create some NSTableColumn instances and add them to the table view.
It doesn't appear (from your sample) that you're putting the tableView inside the scrollView. Is it getting added as a subview somewhere you're not showing us?
Also, are you sure you need a separate scrollview? Doesn't tableView implement scrolling already?