I added NSTableView to NSViewController.view, and setting the setTranslatesAutoresizingMaskIntoConstraints to No, unable to resize the window height anymore from code or debugging the app and trying to modify window height by dragging the edge of the window, i am only able to modify the width.
in ViewDidLoad I have:
[super viewDidLoad];
NSView* firstView = [self view];
tableView = [[NSTableView alloc] init];
[firstView addSubview:tableView];
[tableView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
[tableView.heightAnchor constraintEqualToAnchor:firstView.heightAnchor multiplier:0.9].active = YES;
[tableView.widthAnchor constraintEqualToAnchor:firstView.widthAnchor multiplier:0.9].active = YES;
NSTableColumn * column1 = [[NSTableColumn alloc] initWithIdentifier:#"Id"];
NSTableColumn * column2 = [[NSTableColumn alloc] initWithIdentifier:#"Name"];
[column1 setWidth:250];
[column2 setWidth:250];
// generally you want to add at least one column to the table view.
[tableView addTableColumn:column1];
[tableView addTableColumn:column2];
[tableView setDelegate:self];
[tableView setDataSource:self];
[[tableView.centerYAnchor constraintEqualToAnchor:firstView.centerYAnchor constant:0] setActive:YES];
[[tableView.centerXAnchor constraintEqualToAnchor:firstView.centerXAnchor constant:0] setActive:YES];
Related
I have a custom uitableview with custom uitableviewcell in my view cell. The cell doesn't show on second load. That is, when I go from this view to another and back to this view.
This is how I load my table in my view.
CropTableViewController *cropTblViewCon = [[CropTableViewController alloc]init];
self.cropTableViewController = cropTblViewCon;
cropTableViewController.view.frame = cropTblView.frame;
[cropTblView removeFromSuperview];
[self.view addSubview:cropTableViewController.view];
self.cropTblView = cropTableViewController.tableView;
This is how I go another view
AppDelegate_iPhone *appDelegate = [[UIApplication sharedApplication] delegate];
AddPestReportStepOne *report = [[AddPestReportStepOne alloc]init];
[appDelegate.navCon pushViewController:report animated: YES];
[report release];
This is how I load my table cell in my custom table view.
static NSString *CellIdentifier = #"CustomCropCell";
CustomCropCell *cell = (CustomCropCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
tableView.scrollEnabled = NO;
// tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
NSArray *topLevelObjects = [[NSBundle mainBundle]
loadNibNamed:#"CustomCropCell" owner:nil options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]) {
cell = (CustomCropCell *) currentObject;
break;
}
}
}
//if (counter<6 ) {
CropEntity *crop = [[CropEntity alloc] init];
crop=[ cropList objectAtIndex:counter];
NSString *imgStr = [NSString stringWithFormat:#"%#%#%#",domainName,cropImagePath, [crop cropImage]];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imgStr]]];
CGSize size = CGSizeMake(80, 80);
[cell setBackgroundColor: [UIColor clearColor]];
image = [Utilities scale:image toSize:size ];
[cell.columnOne setTag: [[crop cropId] integerValue] ];
[cell.columnOne setTitle:[crop cropName] forState:UIControlStateNormal];
[cell.columnOne setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[cell.columnOne setTitleEdgeInsets:UIEdgeInsetsMake(0.0, -image.size.width, -75.0, 0.0)]; // Left inset is the negative of image width. counter = counter+ 1;
[cell.columnOne setImage:image forState:UIControlStateNormal];
[cell.columnOne setImageEdgeInsets:UIEdgeInsetsMake(-15.0, 0.0, 0.0, -cell.columnOne.titleLabel.bounds.size.width)]; // Right inset is the negative of text bounds width.
[cell.columnOne setBackgroundColor: [UIColor clearColor]];
counter = counter + 1;
It seems that the rows are not removed. My cellforrowat indexpath keep increasing...
Okay, i'm assuming you want to add a UITableView to a ViewController. Here are the steps for this:
(1) You have create an UIViewController, whether by code or interface builder
(2) Create an UITableView, and add it to your UIViewController
UITableView *tableView = [[UITableView alloc]
initWithFrame:CGRectMake(0, 0, 320, 440)
style:UITableViewStylePlain];
// Set up the tableView delegate and datasource
[self.view addSubview:tableView];
[tableView release];
I'm sure there is a reason why you are adding the tableView to a UIViewController (there is not reason to have an extra UITableViewController. If not just use a UITableViewController, and set up a UITableView.
Also, keep in mind where you create the tableView at. For instance, if you create it in init or viewDidLoad and using a UINavigationController, when you hit the back button on the UINavigationController the ViewDidLoad or init isn't getting called. Try it yourself, put a NSLog statement to test.
So either use viewDidAppear or [tableView reloadData];
Edit:
Think about your code you create a UITableViewContoller then you remove its UITableView from it's super view (does not make sense) and then you add the UITableViewControllers view (the UITableView) to self.view which is i'm guessing a UIViewController. Surely this can't be what you are trying to do.
I would recommend reading Apple's View Programming guide for a better understanding of UIViewControllers and Views.
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaViewsGuide/Introduction/Introduction.html
I've got a fairly complex UITableViewCell and in production code I'm able to pull out a selected UILabel with the following
[[[[[[cell subviews] objectAtIndex:1] subviews] objectAtIndex:0] subviews] objectAtIndex:4];
Everything works no problem -the issue I'm having is when I try to create a simple unit test that shows how this is expected to work.
For some reason I'm not able to build up a scenario that has 2 items in the contentView property of the cell
So I can easily get [[cell subviews] objectAtIndex:0] but never 1
In my test helper I'm doing the following to simulate this (with no luck)
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
UIView *view1 = [[UIView alloc] init];
UILabel *label1 = [[UILabel alloc] init];
UIView *view2 = [[UIView alloc] init];
UILabel *label2 = [[UILabel alloc] init];
[view1 addSubview:label1];
[cell.contentView addSubview:view1];
[view2 addSubview:label1];
[view2 addSubview:label2];
[cell.contentView addSubview:view2];
NSLog(#"inside ...%#", [[cell subviews] objectAtIndex:1]);
You can't add label1 to view1 AND view2, you have to create two different labels. One view can ONLY have one superview so when you say [view2 addSubview:label1]; then label1 gets removed from view1.
When I call [table reloaddata];
The cells get redrawn with new data, but my UILabels get messed up because they are drawn over the old UILabels, so its a mess.
static NSString* PlaceholderCellIdentifier = #"PlaceholderCell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:PlaceholderCellIdentifier] autorelease];
cell.detailTextLabel.textAlignment = UITextAlignmentCenter;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.contentView.backgroundColor = [UIColor clearColor];
}
Is my Init of the cell.
I add a UILabel like so
UILabel *theDateLabel = [[UILabel alloc] initWithFrame:CGRectMake(140, 35,140, 20)];
[theDateLabel setBackgroundColor:[UIColor clearColor]];
[theDateLabel setTextColor:[UIColor lightGrayColor]];
[theDateLabel setText:[dateFormatter stringFromDate:theDate]];
[theDateLabel setFont:[UIFont fontWithName:#"TrebuchetMS-Bold" size:15]];
[cell addSubview:theDateLabel];
[theDateLabel release];
There are a few more labels in the cell, same thing.
What I would like to happen is that the old labels disappear from the cell so that they are no longer visible.
You should not add theDateLabel as a subview of cell. You should add it as a subview of cell.contentView.
As yuji suggests, one way to implement this is to create a subclass of UITableViewCell with a property for each custom subview. That way you can easily get to the date label of a reused cell to set its text for the new row.
Another common approach is to use the tag property that every UIView has. For example:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString* PlaceholderCellIdentifier = #"PlaceholderCell";
static const int DateLabelTag = 1;
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:PlaceholderCellIdentifier] autorelease];
UILabel *theDateLabel = [[UILabel alloc] initWithFrame:CGRectMake(140, 35,140, 20)];
theDateLabel.tag = DateLabelTag;
theDateLabel.backgroundColor = [UIColor clearColor];
theDateLabel.textColor = [UIColor lightGrayColor];
theDateLabel.font = [UIFont fontWithName:#"TrebuchetMS-Bold" size:15];
[cell.contentView addSubview:theDateLabel];
[theDateLabel release];
}
NSDate *theDate = [self dateForRowAtIndexPath:indexPath];
UILabel *theDateLabel = [cell.contentView viewWithTag:DateLabelTag];
theDateLabel.text = [dateFormatter stringFromDate:theDate];
return cell;
}
While Richard's solution will work, if your cells have any other subviews they'll get removed as well. Also, allocating and initializing your subviews every time you draw a cell isn't necessarily optimal.
The standard solution here is to create a subclass of UITableViewCell with a property #dateLabel (and so on for the other labels). Then, when you're initializing a cell, if it doesn't have a #dateLabel yet you can give it a new one, otherwise you only have to set its text.
I have a table view cell with multiple images in them. When touching the images they shold display an overlay on top of the image which tells the user that this image was selected.
Is there a way to change the look of just one UITableViewCell without having to do a [tableView reloadData] which would allow me to style the cell differently in the table view datasource delegate method.
The way I would do it is to subclass UITableViewCell and then on tableView:didSelectRowAtIndexPath: get a reference to the cell and do whatever you want to it (or just target the image touch event if this is not a selection).
There might be another way of doing this without having to subclass, but I find myself subclassing UITableViewCell all the time and it's pretty straightforward to do.
If you wish to avoid subclassing, this can be achieved with gesture recognisers. Your question suggests a Tap and Hold user interaction on each image, which I have implemented in the code below. One point to remember, if the user is tapping and holding, they may not see the text you wish them to see.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"ImageCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
}
UILongPressGestureRecognizer *recognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(imageTapped:)];
UILongPressGestureRecognizer *recognizer2 = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(imageTapped:)];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Ben.png"]];
imageView.frame = CGRectMake(cell.contentView.bounds.origin.x,cell.contentView.bounds.origin.y , 100, 40);
imageView.userInteractionEnabled = YES;
[imageView addGestureRecognizer:recognizer];
[cell.contentView addSubview:imageView];
UIImageView *imageView2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Steve.png"]];
imageView2.frame = CGRectMake(cell.contentView.bounds.origin.x + imageView.frame.size.width + 10,cell.contentView.bounds.origin.y , 100, 40);
imageView2.userInteractionEnabled = YES;
[imageView2 addGestureRecognizer:recognizer2];
[cell.contentView addSubview:imageView2];
[imageView release];
[imageView2 release];
[recognizer release];
[recognizer2 release];
return cell;}
- (void)imageTapped:(id)sender {
NSLog(#"%#", sender);
UILongPressGestureRecognizer *recognizer = (UILongPressGestureRecognizer *)sender;
if (recognizer.state == UIGestureRecognizerStateBegan) {
UILabel *label = [[UILabel alloc] initWithFrame:recognizer.view.bounds];
label.text = #"Pressed";
label.backgroundColor = [UIColor clearColor];
label.tag = 99999;
label.textColor = [UIColor whiteColor];
[recognizer.view addSubview:label];
[label release];
}
else {
[[recognizer.view viewWithTag:99999] removeFromSuperview];
}
}
Hope this helps.
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?