Custom Table Cell View doesn't get modified when load table data - objective-c

I have a little problem with a custom NSTableCellView.
The problem: I have a Table View in a Nib with all stuff configured as well to load data from an array. For now, is OK. The problem is, while the app is preparing the views (using method (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row), the returned View is modified as I want (watched by a breakpoint before return), but the View that I can see, that everybody can see, is not modified.
I expect you could help me found the problem. I give you some stuff to help to understand my problem.
Some Images
Cell before get returned, as you can see, the View is modified as well.
Cell displayed in the Table View, in this case, the Custom View is not modified, it's look likes I didn't modified anything
Code
My custom NSTableCellView, there's only a header...
#interface playlistQueueItemView : NSTableCellView
#property (weak) IBOutlet NSButton *button;
#property (strong) IBOutlet NSTextField *title;
#property (strong) IBOutlet NSTextField *artist;
- (void)setAllFromInitWithTitle:(NSString*)title artist:(NSString*)artist;
#end
Method for create the Views for the table:
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
playlistQueueItemView *cell = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
NSDictionary* song = [[PlaylistQueue getQueue] getSongWithPos:(int) row];
cell.artist.stringValue = song[#"artista"];
cell.title.stringValue = song[#"titulo"];
return cell;
}
One more thing, I followed a bit one of the Apple's sample projects, called TableViewPlayground.
Thanks :D

you have to override - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row and then return the view.
In - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row you can return a model object that has the value you want to populate.
source

Related

How to programmatically create a UITableView in UIPopover so it responds to -cellForRowAtIndexPath

I have 3 UITableViews in a class; one of the tableViews is programmatically created in a UIPopover where I assign it a tag. In -cellForRowAtIndexPath, I check the tag each tableView and configure the tableView depending on the tag id.
The problem is the popover is not created until after -cellForRowAtIndexPath is called. I don't see how I can have a separate -cellForRowAtIndexPath in the method that creates the tableView in the popover. I have the tableView.dataSource = self in the method that creates the tableView.
How can I point the tableView in the popover to it's own -cellForRowAtIndexPath?
So it wasn't entirely clear, but it seems as though your asking how to assign different cellForRowAtIndexPath for the different TableView's in your class. To this end, I've created this small piece of sample code to illustrate how you could accomplish having differing sets of data sources for multiple UITableView's in a single class.
As you can see, there are three different DataSource objects that can each independently control the cellForRowAtIndexPath for each of the three different UITableView's. There's no reason you can't have two table views utilize a single DataSource, and then the third table use it's own.
*Note: There is no reason to keep all of this in a single file, but if that is your desire you certainly can do that.
//UITableViewOne
#interface DataSourceOne : NSObject <UITableViewDataSource>
#end
#implementation DataSourceOne
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Setup cell for TableViewOne
}
#end
//UITableViewTwo
#interface DataSourceTwo : NSObject <UITableViewDataSource>
#end
#implementation DataSourceTwo
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Setup cell for TableViewTwo
}
#end
//UITableViewThree
#interface DataSourceThree : NSObject <UITableViewDataSource>
#end
#implementation DataSourceThree
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Setup cell for TableViewThree
}
#end
#interface MultiTableViewController ()
#property (nonatomic,strong) UITableView *tableOne;
#property (nonatomic,strong) UITableView *tableTwo;
#property (nonatomic,strong) UITableView *tableThree;
#property (nonatomic,strong) DataSourceOne *sourceOne;
#property (nonatomic,strong) DataSourceTwo *sourceTwo;
#property (nonatomic,strong) DataSourceThree *sourceThree;
#end
#implementation MultiTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.sourceOne = [DataSourceOne new];
self.sourceTwo = [DataSourceTwo new];
self.sourceThree = [DataSourceThree new];
//Create or Load TableViews from Xib
self.tableOne.dataSource = self.sourceOne;
self.tableTwo.dataSource = self.sourceTwo;
self.tableThree.dataSource = self.sourceThree;
}
Let me know if you want any more clarification, or if you have further questions on the topic.

How to delete objects from NSArray through tableview in Objective C?

First of I like to start with I am new to Objective C and this is my first time developing in it. For some reason I got stuck on how to delete objects from my NSArray through my tableview (with objects in it). Tryed some diffrent things but seems I am a bit stuck... What shall I pu in the code below?
bookmarks.m
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]withRowAnimation:YES];
[tableView reloadData];
}
Bookmarks.h
#import <UIKit/UIKit.h>
#import "ShowTaskViewController.h"
#import "Bookmark.h"
#interface BookmarksViewController : UITableViewController <UITableViewDelegate,UITableViewDataSource>
{
NSArray *bookmarks;
}
#property (nonatomic, retain) NSArray *bookmarks;
#end
The tableView doesn't manage your content. You have to do that yourself. When the user taps delete on a row, you have to remove that item from your array and notifiy the table view to delete the cell (with an animation).
I recommend you change your data array into an NSMutableArray. Then you can do this:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
[bookmarks removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:YES];
}
Alternatively you could temporarily create an NSMutableArray.
NSMutableArray *mutableBookmarks = [NSMutableArray arrayWithArray:bookmarks];
[mutableBookmarks removeObjectAtIndex:indexPath.row];
self.bookmarks = [NSArray arrayWithArray:mutableBookmarks];

Is it possible to create a static tableview in a storyboard and add it programmatically later? (iOS5, XCode 4)

I'm trying to create a couple of small, static tableviews and add them to a panel that I have which slides in and out. The panel is created programmatically so I can't lay the tableviews out inside it via storyboard, and anyway I'm not sure if this is possible anyhow: It seems the only way you can lay out static tableviews that work is in a tableviewcontroller, which takes up the whole screen.
If you can't tell I'm pretty new to iOS dev so if I'm not understanding some fundamental concepts here please feel free to explain.
Of course is possible. Here is how it can be done:
Drag a TableViewController to your storyboard.
Set its Size to Freeform, add an identifier and uncheck Resize View From NIB
Select the tableview and set its content to Static Cells. Design your cells.
Set its size
Now, wherever you need to instantiate it do it like this:
// I am using a UITableViewController as an example here
// you probably would like to set your actual controller subclass instead
UITableViewController *tableViewController = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"staticTv"];
UITableView *tableView = tableViewController.tableView;
[self.view addSubview:tableView]; // Or add it to whatever view
Enjoy :)
A UITableViewController isn't necessary to provide the functionality you need to manage a UITableView. I think what you're looking for is the "Delegate" pattern. Any UIViewController can be assigned to be the delegate of the UITableView. For example, I have a "static" table that shows some options in an app I am working on:
#interface LBOptionsViewController : UIViewController <UITableViewDataSource,
UITableViewDelegate>
If you're creating your table views programmatically, you'll probably either be creating them in viewDidLoad or loadView (if you're creating the actual view yourself). After you've created your tableView, assign the delegates:
self.tableView.delegate = self;
self.tableView.dataSource = self;
Then your UIViewController subclass will receive the data delegate messages like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Not sure if this helps you. I have not played with Storyboards much yet.
EDIT: #Alladinian has the right answer! If you're using an property for the view controller make sure you allocate it if you need it to be called by other methods.
I've yet to find a usefully reason to use static table view cells over dynamic. Table views were pretty scary when I started iOS programming. I used sqlite in my first app YIKES.
So yeah, you should just import the UITableView Data Source and Delegate and follow up by adding the table view to your panel (assuming it's a uiview and you can add the table view as a subview).
Anyways in your ViewController.h include UITableViewDataSource and UITableViewDelegate.
#interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
Next, add properties for a UITableView and an NSMutableArray:
#property (strong, nonatomic) UITableView* tableView;
#property (strong, nonatomic) NSMutableArray* tableViewContents;
In your ViewController's .m:
#synthesize tableView;
#synthesize tableViewContents;
inside ViewDidLoad:
self.tableViewContents = [NSMutableArray arrayWithObjects:#"Cell 1",#"Cell 2",#"Cell 3",nil];
[self.tableView setDelegate:self]
[self.tableView setDatasource:self]
In the .m file:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.tableViewContents.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSUInteger row = [indexPath row];
index = row;
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
}
cell.textLabel.text = [tableViewContents objectAtIndex:row];
return cell;
}

Displaying different content view in the same uiviewcontroller by uitableview indexpath row

I want to show different UIImageView in the same UIViewController depends on which indexpath row was selected in UITableView. I have an unwise approach which was created lots of UIViewController for different UIImageView, But i don't want do this. Is there any smarter approach can fulfilled that. You help is very appreciated.
First add an UIImageView to the UIViewController's view.
Create a NSMutableArray to store UIImageViews, and in - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
imageView = [imageViewArray objectAtIndex:indexPath.row];
}

Can't reload Table View in tab bar controller

Hi I have a tab tab controller and my first tab includes a view with:
3 text fields
a submit button
a tableView
Once I fill in the text fields I click submit and it adds the information to my managedObjectContext which is an sqlite database (CoreData).
As soon as I click submit I want the tableView to reload to include the added object. Currently my tableView will display the data in the database but it will only add the new row when I stop and re-run the simulator
This is the code for when the add button is tapped, it is here that I can't get the reload tableView working because it says tableView is an undeclared identifier, what have i missed?
-(IBAction)addButtonTapped:(id)sender {
NSLog (#"Add Button Tapped");
NSLog(#"Adding %# units of item code %# at $%# each",quantityTextField.text,productTextField.text,priceTextField.text);
Products_MarketAppDelegate* delegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext* managedObjectContext = delegate.managedObjectContext;
NSManagedObject* newProduct;
newProduct = [NSEntityDescription insertNewObjectForEntityForName:#"Product" inManagedObjectContext:managedObjectContext];
[newProduct setValue:productTextField.text forKey:#"itemCode"];
[newProduct setValue:quantityTextField.text forKey:#"quantity"];
[newProduct setValue:priceTextField.text forKey:#"price"];
if ([managedObjectContext hasChanges])
NSLog(#"Managed Object Changed");
NSError* error;
[managedObjectContext save:&error];
// Insert Reload Table Code Here
// ** I have tried the following and it gives an error "Use of undeclared identifier 'tableView'"
//[tableView reloadData];
//[self.tableView reloadData];
}
As you can see below I have added the UITableViewDelegate & UITableViewDataSource in the header file. I have also hooked up the tableview in IB so that the delegate and datasource connections are linked to file's owner.
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#interface FirstViewController : UIViewController
<UIApplicationDelegate, UITableViewDataSource,UITableViewDelegate,NSFetchedResultsControllerDelegate>
{
IBOutlet UITextField *productTextField;
IBOutlet UITextField *quantityTextField;
IBOutlet UITextField *priceTextField;
NSMutableArray *items;
NSFetchedResultsController *fetchedResultsController;
}
#property (nonatomic, retain) NSMutableArray *items;
#property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
-(IBAction)addButtonTapped:(id)sender;
#end
This is the code to fill the tableView which works correctly
#pragma mark TableView
-(NSInteger)numberOfSectionsInTableView: (UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell
Product* productItem =[fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:#"%# x %# # $%#",productItem.quantity,productItem.itemCode,productItem.price];
return cell;
}
I have searched for answers on this site and on others but I must be doing something different and the solutions aren't helping me
Your UIViewController does not currently have an instance variable pointing to your tableview. Set one up:
#property (nonatomic, retain) IBOutlet UITableView *myTableView;
Remember to synthesize this in your .m
#synthesize myTableView;
Then in your code you can call
[self.myTableView reloadData];
You might have got confused by looking at code examples that use a UITableViewController instead of a UIViewController. The UITableViewController already has an instance variable called tableView, so your subclass wouldn't need it's own tableView instance variable declared. But you're using a UIViewController, so you must declare a tableView instance variable.
Thanks #MattyG for all your help. At first I wasn't sure if I was going against the norm and thats why it wasn't working.
I ended up solving the problem due to your suggestions & it works perfectly! I used the debugger and found that that although we had created a property for the table I had not created an IBOutlet and linked it in my nib file with:
IBOutlet UITableView *myTableView;
I guess this meant that I was telling myTableView to reload but it wasn't hooked up to my table and thus couldn't use the datasource methods.