Do I need to subclass the Image&Text NSTableCellView to add a label? - objective-c

I have a view-based NSTableView (using the Image&Text CellView).
Depending on the dataItems in the dataSource, I select an appropriate CellView to display them.
One of the templates has an additional (to the default CellView) label on it. But I don't know what is the right way to access it when I instantiate the CellView (I need to set label's value).
My question basically is - should I search for the subview (like in the following snippet) or should I subclass the CellView, add a property and so on?
NSArray* subviews = [cellView subviews];
for (id view in subviews) {
ViewType* view = (ViewType*)view;
if ( view != nil ) {
if ( [view.identifier isEqualToString:#"idSetInIB"] ) {
[view setStringValue:dataItem.someValue];
}
}
}
Thanks.

The Apple TableView Programming guide gives good basic examples on how to subclass NSTableCellView for a view based table.
It's probably a little easier to do without bindings.
And certainly better for learning it.
However, you should be able to just add another text field in Interface Builder to the table cell view.
Read the guide. It will help tremendously.

Related

Set all labels, textfields and buttons (.....layer.cornerRadius = 10)

how I can set ALL labels, textfields and buttons on my ViewController to ...layer.cornerRadius = 10? e.g. with a for-statement? or must all be set individually?
1) Subclass the classes and add a UIAppearance corner radius property. This will give you reusable classes which you can use in different view controllers with different corner radius values. You'll have to create 3 new classes and remember to set all of them in Interface Builder when adding new items.
2) Assuming everything is contained in the same view you can iterate through all of the subviews and check the class. If you end up using nested views you will need to check those subviews as well. Not the cleanest but if it's a simple view it's a good option.
for (UIView *view in self.view.subviews)
{
if ([view isKindOfClass:[UILabel class]] || [view isKindOfClass:[UIButton class]] || [view isKindOfClass:[UITextField class]])
{
view.layer.cornerRadius = 10.f;
}
}
3) You can create an IBOutletCollection and loop through it in the same way without having to check the class. This becomes annoying as you add/remove items over time.
You can put them all in an IBOutletCollection, which is an array generated through Interface Builder. Similar to how you create an outlet, select Outlet Collection in the popup that comes up. Then drag all of the other UI items you want to iterate over in there. Note, though, that all of the items in a collections must be the same type. So if you have labels and buttons, you'll need a separate collection for each.
Alternatively, you can create a separate subclass of each type with their corner radius set (since you're apparently using that style of control so often) and use those classes in Interface Builder.

Change Label With Tag Only

I am creating an application with multiple buttons and corresponding labels.
The layout is in a nib (.xib) file which is connected to the class I have the code below in. I'm trying to avoid using an IBOutlet for every label, since this would create a lot of extra code.
I know there is a way to reference a label using the tag:
UILabel *countLabel = (UILabel *)[self.view viewWithTag:numOfTag];
I called this within my buttonPressed method. However, when I try to change the text
[countLabel setText:#"newLabel"];
the app crashes. Am I accessing it wrong? I'm new to XCode..Help!
Thanks :)
This is not the correct way of doing it. Firstly whenever you creating UILabel in your XIB file, you can name them there only so technically, there is no need for you to set the label values in the connected view controller. Secondly, even if you want to reset the labels at the later stage, connecting them using IBOutlets is the best bet. Scanning through all sub views and then finding a particular subview with its tag is more tedious and should be avoided in this case.
EDIT:
For your case where you need to create more than 50 buttons and labels, I would suggest you to create a custom UIView with UIButton and UILabel in it. And then in the view where you want to display them, create objects in a for loop and display them. And when a UIButton is tapped it will be easy for you to fetch the associated UILabel though the custom UIView object.
Your label must not be found with viewWithTag:, so it will be nil. And when you try to access property of nil control, it might give you a crash.
Check if your label is not nil and check if it is label using
if(countLabel != nil && [countLabel isKindOfClass:[UILabel class]])
[countLabel setText:#"newLabel"];
else
NSLog(#"countLabel is not found");
viewWithTag: will search the view in the receiver’s hierarchy whose tag property matches the value in the tag parameter. This will return first control it will encounter with tag in hierarchy. So make sure your tag needs to so unique in entire view. Just make sure you are giving immediate parent of Label instead of self.view.
Edit:
To can try this way also if you are not able to track issue.
for (UIView *child in self.view.subviews) {
if([child isKindOfClass:[UILabel class]] && [child tag] == numOfTag)
{
[child setText:#"newLabel"];
break;
}
}

Two uitable into one uiview

So this is related to this question I asked not too long ago and I'm trying to figure out if the solution I came up with is feasible, I would try it but I'm not really sure how to start
Load a TableViewController on an animated UIView
So what I wanted to do is to have two different results when a animated uiview pops up.
I have two buttons. One button will have a uitable that shows a label and 3 icons, while the other will show one label and a different icon.
I'm using storyboards (since that's the only way I know how to do it) to connect a "Custom UitableCell" to the table.
I dragged two uitableviews and force them to be hidden from the view when viewdidload happens. So I place a prototype cell on each uitableview specific to what objects I need displayed when it gets loaded.
Now I add the uitabledelegate and datasource on the viewcontroller file.
Now my issue is, if I do this on the viewcontroller, can it only communicate to one uitable and not two? (eg. didselectrow, numberofrowsinsection, cellforrowatindexpath, etc) Or can I do and "if else" to figure out which uitable view it is communicating (or loading info) with?
This is the tutorial I followed for th uiview animation
Thoughts?
Yes, your view controller can be the data source and delegate of two uitableview or more.
Make your two UITableView properties of the view controller. Then in your delegate and data source methods, you can check the tableView parameter passed in each method, for example:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
if (tableView == self.firstTableView) {
return 1; //for the firstTableView
} else {
return 2; //this will be for the secondTableView
}
}
Do the same for your other data source and delegate methods.

Best way to deal with UITableView of Unknown depth with Storyboards

I am creating a storyboard that will pass through an unknown depth. What I am doing is creating a loop segue from the UITableViewCell to its main view controller. and in perforSegueWithIdentifier, I am passing the info for the next level.
That all works fine, but the problem is if I want to branch off to a detail view based on that data. I have to resort to hacks with buttons and phantom view segues. Does anyone know how this should be done officially? I want to be able to link the UITableViewCell to two different controllers and then decide which one to go to in performSegueWithIdentifier. is this possible?
I don't have much experience with storyboards, but from what I know of traditional UITableView usage the cell should not be telling the view controllers what to be doing. Doing this breaks the MVC paradigm. The cell's table view's delegate (which is normally the view controller displaying the table view) will respond to the method tableView:didSelectRowAtIndexPath: and will then perform the appropriate segue to the next view controller.
For showing detailed views, table view cells offer the accessory type UITableViewCellAccessoryDetailDisclosureButton. When using this type, the table view delegate can respond to the selector tableView:accessoryButtonTappedForRowWithIndexPath: and then perform the necessary segue to show the detailed view.
I hope that makes sense.
I did something similar time ago.
I didn't find any 'official' solution, but one solution I found was to add a long press gesture recognizer to the cell, that lead the user to a detail view, in addition to the normal selection.
However the only downside is that you have in some way to inform the user of this "hidden" option.
Here's a code fragment in viewDidLoad:
UILongPressGestureRecognizer *taskDetail = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(showTaskDetail:)];
taskDetail.minimumPressDuration=0.5f;
taskDetail.numberOfTouchesRequired=1;
[self.myTableView addGestureRecognizer:taskDetail];
Then in my taskDetail:
-(IBAction)showTaskDetail:(id)sender {
UILongPressGestureRecognizer *gesture = (UILongPressGestureRecognizer*)sender;
if (gesture.state == UIGestureRecognizerStateBegan) {
CGPoint p = [gesture locationInView:TV];
NSIndexPath *indexPath = [self.myTableView indexPathForRowAtPoint:p];
MyManagedObj *obj = [self.datasource objectAtIndex:indexPath.row];
// other operations omitted...
// then perform segue...
[self performSegueWithIdentifier:#"taskDetail" sender:indexPath];
}
}
Other solution I have tried was to two a buttons in UITableViewCell, one for table drill down and the other for detail. It works also, but my cell was too small, and there were no much rooms for two buttons.

Handling custom selection style in view based NSTableView

How do I go about drawing my own custom selection style for a view based NSTableView? I tried putting a BOOL var in my NSTableCellView subclass and set that to YES if it is clicked and then I can successfully draw my custom selection. But how do I change that BOOL var to NO when another view is clicked? Thanks for any help.
EDIT: After reading through the NSTableView docs, it looks like I need to subclass NSTableRowView to override the selection drawing, but what do I do with my NSTableRowView subclass? How do I get the table to use it?
Alright, I figured it out. You just have to subclass NSTableRowView. It has methods for drawing the background for selected and deselected rows. To get the table view to use your subclass just implement the table view delegate method tableView:rowViewForRow: and return an instance of your subclass.
To make things clear, I think we should give the code of the delegate method :
- (NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row
{
MyNSTableRowView *rowView = [[MyNSTableRowView alloc]init];
return rowView;
}