How to reload UItableView that is inside UiViewController - objective-c

I have a UITableView inside UiViewController.
In the same screen, I also have two buttons: Show All vs Show Top 5.
Now based on a selection all/top 5, I have to update table data.
I cant use [tableView reloadData] as I am not using UITableViewController.
This is the first time I am working on an iphone app. So any help is appreciated.
(I used this tutorial to get started http://www.icodeblog.com/2009/05/24/custom-uitableviewcell-using-interface-builder/)
Thanks.
Here is a snippet of my code:
.h file
#interface DataViewController : UIViewController {
NSString *showType;
}
#property (nonatomic, retain) NSString *showType;
-(IBAction) showTop: (id) sender;
-(IBAction) showAll: (id) sender;
#end
.m file
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"customCell";
DataCustomCell *cell = (DataCustomCell *) [tableView dequeueReusableCellWithIdentifier:cellID];
if([showType isEqualToString:#"all"])
{
// use this data..
}
else
{
// use some other data..
}
// ....
}
-(IBAction) showNearby: (id) sender
{
self.showType=#"top";
// reload table some way
}
-(IBAction) showAll: (id) sender
{
self.showType=#"all";
//reload table some way
}

Create a UITableView IBOutlet like this
#property (nonatomic, retain) IBOutlet UITableView *myTableView;
in your UIViewController's interface file. Then have that connect to the UITableView in Interface Builder. After synthesizing it in your implementation file, you should be able to access it like this
[self.myTableView reloadData];
Also, since you retained it, you will have to release myTableView in the dealloc method.

Related

Not able to obtain correct indexPath.row value from objective C file in Swift file

File: ContactsViewController.m
In this file I am using the didSelectRowAtIndexPath method to push a new View Controller to show information about the name that was pressed on the Table View Controller. The View Controller that will be displaying the information about the name is being implemented in Swift. The part that I am referring to in this code is in the didSelectRowAtIndexPath method, line:
_myIndex = indexPath.row;
I believe indexPath.row should return the index of the name that was tapped in the Table View Controller.
#import "ContactsViewController.h"
#import "Contacts-Swift.h"
#interface ContactsViewController ()
#property (nonatomic, readwrite, strong) NSMutableArray* contacts;
#property (nonatomic, readwrite) NSInteger myIndex;
#end
#implementation ContactsViewController
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
/*NSArray *contactArray = #[#"Johnny Appleseed", #"Paul Bunyan", #"Calamity Jane"];
_contacts = [NSMutableArray arrayWithArray:contactArray];*/
/*Contact *c1 = [[Contact alloc] initWithName: #"Johnny"];
Contact *c2 = [[Contact alloc] initWithName: #"Paul Bunyan"];
Contact *c3 = [[Contact alloc] initWithName: #"Calamity Jane"];*/
// _contacts = [NSMutableArray arrayWithArray: #[c1, c2, c3]];
self.contacts = [NSMutableArray array];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.tableView registerClass: [UITableViewCell class]
forCellReuseIdentifier:#"UITableViewCell"];
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return self.contacts.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell" forIndexPath:indexPath];
Contact *contact = self.contacts[indexPath.row];
cell.textLabel.text = contact.name;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ContactsViewController *viewController = [self.navigationController.storyboard instantiateViewControllerWithIdentifier:#"the"];
[self.navigationController pushViewController:viewController animated:YES];
_myIndex = indexPath.row;
}
File: ContactsViewController.h
This is the header file that I am using in order to have access to the objective C methods and variables when working in the swift file. (I am not very familiar with objective C so there is a strong possibility that this implementation is what is causing my problems).
#import <UIKit/UIKit.h>
#interface ContactsViewController : UITableViewController <UITableViewDelegate>
#property (nonatomic, readonly) NSInteger myIndex;
#property (nonatomic, readonly, strong) NSMutableArray* contacts;
#end
File: ExistingContactViewController.swift
In the ExistingContactViewController I am just trying to set the firstName label equal to the text that is present in the contacts array at indexPath.row (in the ContactsViewController.m file).
import UIKit
#objc class ExistingContactViewController: UIViewController {
var contactsObject = ContactsViewController()
#IBOutlet weak var firstName: UILabel!
#IBOutlet weak var lastName: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
print("\(contactsObject.myIndex)")
firstName.text = contactsObject.contacts[contactsObject.myIndex] as? String
}
When clicking names that are added to the Table View Controller the only index that is ever printed
print("\(contactsObject.myIndex)")
is 0. Which tells me that I am not capturing the index of the name that is tapped.
Image of myStoryboard The bottom most scene is the one that I am trying to change the First Name label to display the name of the cell that was tapped.
I have not yet been able change the title of this label when clicking on a cell. I have been able to implement this functionality when using just swift files (through watching numerous videos). I am sure that there is a key concept I am missing in the objective C files so any suggestions and/or pointers are much appreciated. If any additional details are needed let me know!
Thanks.
Seems that in your didSelectRowAtIndexPath: you are pushing a ContactsViewController to the navigation stack and if I understand correctly it should be instance of ExistingContactViewController. Also you should set the contactsObject property of the ExistingContactViewController before pushing it in the navigation stack (before viewDidLoad is executed) otherwise it's value will always be a new ContactsViewController which, probably, is causing the issue.
I hope this helps!

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.

Initialising an NSTableView

I'm quite new to Cocoa and I am trying to setup a table view backed by an array. I've setup the app delegate as the datasource for the tableview, and implemented NSTableViewDataSource protocol.
When I run the app, I get the following log output:
2012-06-23 18:25:17.312 HelloWorldDesktop[315:903] to do list is nil
2012-06-23 18:25:17.314 HelloWorldDesktop[315:903] Number of rows is 0
2012-06-23 18:25:17.427 HelloWorldDesktop[315:903] App did finish
launching
I thought that when I called reloadData on the tableView it would call numberOfRowsInTableView:(NSTableView *)tableView again to refresh the view, but that doesn't seem to be happening. What have I missed?
My .h and .m listings are below.
AppDelegate.h
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDataSource>
#property (assign) IBOutlet NSWindow *window;
#property (assign) IBOutlet NSTableView * toDoListTableView;
#property (assign) NSArray * toDoList;
#end
AppDelegate.m
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize toDoList;
#synthesize toDoListTableView;
- (void)dealloc
{
[self.toDoList dealloc];
[super dealloc];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSLog(#"App did finish launching");
// Insert code here to initialize your application
// toDoList = [[NSMutableArray alloc] init];
toDoList = [[NSMutableArray alloc] initWithObjects:#"item 1", #"item 2", nil];
[self.toDoListTableView reloadData];
// NSLog(#"table view %#", self.toDoListTableView);
}
//check toDoList initialised before we try and return the size
- (NSInteger) numberOfRowsInTableView:(NSTableView *)tableView {
NSInteger count = 0;
if(self.toDoList){
count = [toDoList count];
} else{
NSLog(#"to do list is nil");
}
NSLog(#"Number of rows is %ld", count);
return count;
}
-(id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSLog(#"in objectValueForTable");
id returnVal = nil;
NSString * colId = [tableColumn identifier];
NSString * item = [self.toDoList objectAtIndex:row];
if([colId isEqualToString:#"toDoCol"]){
returnVal = item;
}
return returnVal;
}
#end
The first thing that I'd check is that you're NSTableView IBOutlet is still set in applicationDidFinishLaunching.
NSLog(#"self.toDoListTableView: %#", self.toDoListTableView)
You should see output like:
<NSTableView: 0x178941a60>
if the outlet is set properly.
If you see 'nil' rather than an object, double check to ensure that your NSTableView is connected to your outlet in the XIB editing mode of Xcode. Here's a documentation link for assistance connecting outlets.
I fixed it - I'd set the appDelegate as the datasource and the delegate for the tableView but ctrl-dragging from the tableView to the appDelegate, but I hadn't ctrl-dragged the other way to actually link up the outlet I'd declared with the table view. It's working now. Thanks for your help though Jeff.

UITableViewCell does not appear in my table

I have an UITableVIew. Now I made my own UITableViewCell. But if my table appears nothing is shown. However the cells are still selectable and open the DetailView. Which command have I forgotten?
//Customize the appearance of table view cells.
-(UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"MainTableCell";
MainTableCell *cell = (MainTableCell*)[tableView dequeueReusableCellWithIdentifier:Cel lIdentifier];
if (cell == nil) {
cell = [[[MainTableCell alloc] initWithStyle:UITableViewCellStyleDef ault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
VerwaltungInformation *selectedFormel = [listOfFormularies objectAtIndex:indexPath.row];
cell.FormelNameLabel.text = selectedFormel.nameFormel;
return cell;
}
Do I have to add special things? If somebody needs more code - please tell me.
Here is my MainTableCell.h:
import <UIKit/UIKit.h>
#interface MainTableCell : UITableViewCell {
UILabel *FormelNameLabel;
UILabel *ErklaerungVerfuegbarLabel;
UILabel *BeispielVerfuegbarLabel;
UILabel *RechnerVerfuegbarLabel;
}
#property (nonatomic, retain) IBOutlet UILabel *FormelNameLabel;
#property (nonatomic, retain) IBOutlet UILabel *ErklaerungVerfuegbarLabel;
#property (nonatomic, retain) IBOutlet UILabel *BeispielVerfuegbarLabel;
#property (nonatomic, retain) IBOutlet UILabel *RechnerVerfuegbarLabel;`
#end
And here is my MainTableCell.m:
#import "MainTableCell.h"
#implementation MainTableCell
#synthesize FormelNameLabel;`
#synthesize ErklaerungVerfuegbarLabel;
#synthesize BeispielVerfuegbarLabel;
#synthesize RechnerVerfuegbarLabel;`
- (void)dealloc {
[FormelNameLabel release];
[ErklaerungVerfuegbarLabel release];
[BeispielVerfuegbarLabel release];
[RechnerVerfuegbarLabel release];
[super dealloc];
}
#end
you have commented this line
cell. VerwaltungInformation *selectedFormel = [listOfFormularies objectAtIndex:indexPath.row];
and also check wthr
selectedFormel.nameFormel
contains any value.
ok, I'll try to answer.
1.try to NSLog this value selectedFormel.nameFormel before setting it to the label.text.
NSLog(#"selectedFormel.nameFormel:%#", selectedFormel.nameFormel);
2.Have you configured your cell properly? are you sure that for example FormelNameLabel's frame is not zero?
NSLog(#"cellFrame:%#", NSStringFromCGRect(cell.frame));
Are you sure that you have added a label to the cell as subview?
If all these things are done and it still shows nothing provide a code from your cell!

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.