Adding Text Field Data to Table Cell - objective-c

How I can store text field data in a view controller into a tableView cell in a TableViewController With Xcode using data source?
That means when the user taps "+" it will show another view that has the text field. When the user enters the text and presses save, the entered data will be stored as a table cell.

First make sure you understand data sources. Then you have to implement
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return self.data.count;
}
- (NSView *)tableView:(NSTableView *)tableView
viewForTableColumn:(NSTableColumn *)tableColumn
row:(NSInteger)row {
NSTableCellView * result = [tableView makeViewWithIdentifier:#"identifier" owner:self];
result.textField = #"Your special string";
return result;
}
After having setup it in IB like this and having connected the outlet of the Table View data source to your custom objects class (the class the above code is in) it should look like this
Please notice I used the same identifier as in the code so that I can get the created table cell view back easily.
self.data could be an array for example in which you store all your underlying objects (for the cell creation).
Of course you could also add any kind of UI elements to the cell view as well. In this case I use a custom subclass for the cell view. You would have to do something like this then (and set your class as the class of the cell view within IB of course. This is the part in the screenshot that has an NSTableCellView currently in it. It had to be MyGreatCellView from now on):
#interface MyGreatCellView : NSTableCellView {
IBOutlet NSTextField *files;
}
#property (assign) NSTextField *files;
Then you could also refer to result.files in the tableView:vieForTableColumn:row for example.
If something is unclear, just ask.

Getting the UITextField data onto a TableView Cell.
Here is a query for some one for the same issue.I think it will help you.

Related

How to bring the custom view cell above table rows in NSTableView?

When I use a custom view as the cell of a view-based NSTableView, the custom view is somewhat below the table row. When I click on it, instead of affecting the elements (e.g. text field) custom view, the table row was selected (and highlighted). I have to reclick to select the text field.
- (NSView*)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSLog(#"We are creating views!");
NSTableCellView *newView;
newView = [tableView makeViewWithIdentifier:#"PostCell" owner:self];
NSTextField *newTextField = [[NSTextField alloc] init];
[newView addSubview:newTextField];
return newView;
}
When I disable the row selection according to NSTableView - Disable Row Selection, there was no selection.
- (BOOL)selectionShouldChangeInTableView:(NSTableView *)tableView {
return NO;
}
But I still cannot select directly the text field. What's worse, I cannot even select it using the mouse. Only tab on the keyboard works.
There seem to be something above it. But is it the "table column" shown in interface builder? Or something else?
How can I fix this?
Use a custom subclass of NSTableView and override -validateProposedFirstResponder:forEvent: to return YES.
See this blog entry from the Apple engineer who wrote the view-based table view code.
Make sure following code is present.
- (BOOL)tableView:(NSTableView *)aTableView shouldSelectRow:(NSInteger)rowIndex {
return YES;
}
You may try logging the subviews Or you can check superviews of view.
This will help to understand view hierarchy.
Also on side note if one of the view's userInteraction is disable then it's subview's won't be able to receive the events. Please verify that all the views and it's subviews userInteraction is enable.
I hope this helps.

Static table view inside UIViewController [Xcode 5]

I'm aware of the problem that one is not able to have static table view content in a UIViewController in
I don't get a warning/error but he also doesn't compile. Is there a trick to it or do I have to use the old ways around it?
Thanks in advance.
UPDATE: With the latest update (Xcode 5.1) it seems that it's no longer possible to put static cells inside regular UIViewController. My answer still applies for UITableViewController though.
Yes, you can have static table view content in UIViewController.
All you need to do is:
-Create the table's static cells in interface builder and design them the way you like.
-Make the UIViewController implement table view's data source and delegate:
#interface MyViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
-Connect the table view's delegate and dataSource to the view controller in interface builder
-Implement -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section to return the number of your cells. (e.g. return 10, yes simple as that)
-Connect your cells to your code as IBOutlets in Interface Builder. IMPORTANT: Make sure they are strong, weak won't work. e.g. #property (strong, nonatomic) IBOutlet UITableViewCell *myFirstCell;
-Implement -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath to return the correct cell at index path. e.g:
int num = indexPath.row;
UITableViewCell *cell;
switch (num) {
case 0:
cell = self.myFirstCell;
break;
case 1:
cell = self.mySecondCell;
break;
}
return cell;
If you apply all these steps, you should have working static cells that works for tables with not many cells. Perfect for tables that you have a few (probably no more than 10-20 would be enough) content. I've ran the same issue a few days ago and I confirm that it works. More info on my answer here: Best approach to add Static-TableView-Cells to a UIViewcontroller?
There's a way to improve Can's answer.
Connect your cells to code not as IBOutlet but as IBOutletCollection. If you name it as e.g. cells your code will look like this, which makes it slightly cleaner:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.cells.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
return self.cells[indexPath.row];
}
The order in which you connect cells to outlet collection will be the order you see when run the app.
I can think of supporting several sections by linking their cells to several outlet collections.
This is my try:
I have created container view and Table View Controller. Then I opened source code of Storyboard and changed destination identifier of container view to table view container identifier. Now make table view controller static...
UPDATE:
Just Ctrl+Drag from ContainerView to UITableViewController!
UPDATE 2:
Set embedded view controller class to smith like MYStaticTableViewController, witch should only have this method to provide -prepareForSegue calling to parent view controller:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([self.parentViewController respondsToSelector:#selector(prepareForSegue:sender:)])
[self.parentViewController prepareForSegue:segue sender:sender];
}
UPDATE 3:
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
if ([self.parentViewController respondsToSelector:#selector(shouldPerformSegueWithIdentifier:sender:)])
return [self.parentViewController shouldPerformSegueWithIdentifier:identifier sender:sender];
return YES;
}
Can's solution does break in XCode 5.1 :(
I found a workaround which builds off the same basic idea, but unfortunately requires a little more involvement: http://www.codebestowed.com/ios-static-tableview-in-uiviewcontroller/
To summarize, you can add TableViewCells directly to views (and create IBOutlets from them, etc), but in order for them to get "moved" to the TableView properly, you need to remove them from the view in code, and you also need to set Auto-Layout constraints in IB.
As Dannie P mentioned above, using an IBOutletConnection is the way to go. To clarify on this a bit further:
Take the first cell from your static table view and ctrl+drag it into your UITableViewController. On the connection property window, select Outlet Collection on the Connection pull down menu.
Your should end up with code similar to this:
#property (strong, nonatomic) IBOutletCollection(UITableViewCell) NSArray *cells;
Next, ctrl+drag over all the rest of your cells (one at a time) onto the property you created above in the order you want them to appear in your static table view.

NSTableView Multiple Row Types

I'm trying to create a homework planner app that has two types of TableCellViews in a View Based NSTableView. One type is a narrow bar that just has a label of what subject the below homework is for, and the other type is a row to input homework items. (I'll include a screenshot below.)
My question is: when creating new rows in a TableView, how do you specify which type of row you'd like to create? I'm assuming it has something to do with identifiers, but I can't find any information on how to use them in this way.
This is basically how it would look:
You are on the right track with the identifiers. Here's how you use them.
First setup your NSTableView with your specific row types (as you've probably already done). In the screenshot below I made one row with a title and description and another with a few buttons.
Next, you need to setup the desired identifiers. Click the first row in Interface Builder and select the Identity Inspector. Pick a unique identifier for your first row. Do the same for the other(s).
Finally, in your implementation create a new row of a specific type using the following code:
TableViewController.m
#pragma mark - NSTableViewDelegate
- (NSView *)tableView:(NSTableView *)tableView
viewForTableColumn:(NSTableColumn *)tableColumn
row:(NSInteger)row {
NSTableCellView *cell;
if(someCondition == YES) {
cell = [self.tableView makeViewWithIdentifier:#"ButtonRow" owner:self];
} else {
cell = [self.tableView makeViewWithIdentifier:#"TitleDescriptionRow" owner:self];
}
return cell;
}
If you're looking for a more in depth tutorial, check out Cocoa Programming L51 - View-Based NSTableView (YouTube video, not by me).

Buttons for each row UITableView

I have a custom cell in a UITableView, defined by a custom class (.h and .m files). I am able to display the cell, and change the text for each cell in the list, but my custom cell also has buttons in it (two, actually). When I click the button, I need to know which row's button has been clicked. Is there any way to get this within the custom ui cell class?
I hope what I'm requesting is clear. If not, feel free to comment and I'll try to explain as best as possible.
You don't show any code to comment on, but generally speaking you can:
define a tag for each button which represents the table row where the button appears;
when your button action method is called, you can access then the tag property of the button to know which row it was.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
...
}
...
[button setTag:indexPath.row];
...
}
- (void)buttonPressedAction:(id)sender
{
UIButton *button = (UIButton *)sender;
int row = button.tag;
}
For a more elaborate solution, have a look at this S.O. thread.
You can use this approach:
Set an associated object value with each button. You can support this by adding a category to UIButton
#interface UIButton (AssociatedObject)
#property ( nonatomic, retain ) id associatedObject ;
#end
Implementation:
#implementation UIButton (AssociatedObject)
-(void)setAssociatedObject:(id)object
{
objc_setAssociatedObject( self, #"_associatedObject", object, OBJC_ASSOCIATION_RETAIN_NONATOMIC ) ;
}
-(id)associatedObject
{
return objc_getAssociatedObject( self, #"_associatedObject" ) ;
}
#end
Use this like this:
myButton.associatedObject = <some object>
Set action/target to your view controller (or maybe table view delegate)
[ myButton addTarget:<view controller> action:#selector( buttonTapped: ) forControlEvents:UIControlEventTouchUpInside ] ;
In your action, look at the sender's associated object. Sender will be your UIButton
-(void)buttonTapped:(UIButton*)sender
{
// retrieve object associated with the tapped button:
id associatedObject = sender.associatedObject ;
}
I have done this by creating a protocol for the custom cell class and then making the UIViewController that is handling the UITableView the delegate for each of the custom cells.
Then I attached the UIButton to an IBAction in the custom cell class that made a call to it's delegate with information about which cell it is or which information I needed to act on.
So I would set up a protocol with something like:
#protocol CustomCellDelegate <NSObject>
- (void) cellButtonPressed:(NSDictionary *)stuffForDelegate;
#end
Then when I implemented cellButtonPressed: in the ViewController I would use stuffForDelegate to determine which cell it was or what information I needed to act on.
The tag method is okay, but I find it tedious to deal with all of the tags flying around and I prefer using objects and protocols and delegates instead.

Holding NSView instances in an array

Is it possible to store an NSView object in a mutable array? As I understand it, the view will be an object so the array should be able to hold it. Specifically, I want to hold several instances of a nib file, which I think would be loaded with an NSNib init, and then addObject to the array.
The idea is to display an NSView in each of the rows of a column in a TableView. I think it can be done because iTunes does something similar (with what I think is an NSImage) in displaying album artwork in a list view.
Still, any knowledge on the subject (or link to an example or tutorial) would be very appreciated.
TableViews usually don't hold an NSView for each item. They hold a number of NSViewTableCells (which are, system-wise, far more lightweight than NSViews), and they re-use these cells. They usually don't have many more cells than necessary to display the visible part of the TableView, AFAIK, and when the view is scrolled, cells that have become "invisible" are re-used.
So the best way to do this is to subclass the cell and to make the TableView display the contents using these. Using NSViews for every entry in a list of, say, my MP3 albums would be extremely expensive.
In Xcode goto File->New File and choose Objective-C class then in the drop down, choose to make it a subclass of UITableViewCell. Name it MyCell (for example)
Next in interface builder, create a new XIB and change its owner to your newly created class. You may also want to delete the default view and add a UITableViewCell. Set the owner's view outlet to this new tableview cell. Then add whatever you want to the UITableViewCell.
Then create a new UIViewController (which it may be helpful to create a new UITableViewController first and then change its type to UIViewController just so you get all the UITableViewDelegate methods added for you) and choose to add a XIB file for the UIViewController. Open the header file for the newly created UIViewController and add UITableViewDelegate protocol so the header may look like this:
#interface MyViewController: UIViewController <UITableViewDelegate, UITableViewDataSource>
On the view for the view controller (in interface builder) add a UITableView and then set its datasource and delegates to the owner. Make sure to import the MyCell.h header file. Then implement the tableViewMethods in particular for your UITableViewCell you would do something like this:
- (UITableViewCell *)tableView:(UITableView *) tableView
cellForRowAtIndexPath:(NSIndexPath *) indexPath
{
static NSString *MyCellIdentifier = #"MyCellIdentifier";
MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:MyCellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
//Here you would set properties of the cells items like labels, etc.
return cell;
}