When I try to import it gives error at the import stating "method definition not in #implementation context". I think the error lies within the following code...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *infoDictionary = [self.jsonArray objectAtIndex:indexPath.row];
static NSString *Prospects = #"agencyname";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Prospects];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:Prospects] autorelease];
}
// setting the text
cell.text = [infoDictionary objectForKey:#"agencyname"];
// Set up the cell
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ViewAgencyController *dvController = [[ViewAgencyController alloc] initWithNibName:#"ViewAgency" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:dvController animated:YES];
[dvController release];
dvController = nil;
}
Cant Figure it out.
All objective-C method definitions must be between #implemention and #end compiler directives. Without those, there's no way for the compiler to know what class you want the method to belong to.
Look at your header and make sure you have an #end directive to close your class declaration, and look at your .m file and make sure you have an #implementation directive before, and an #end after your method implementations.
Related
The structure of my app currently looks like this:
Collection View Controller -> Generic Cell with table view inside of it -> individual cells.
I would like to call a method in the collection view controller from one of the individual cells. So far I have implemented a delegate in the individual cell but if I can't seem to set my delegate in the collection view controller because I don't have an instance of it.
Furthermore, I have several cells inside the table view that are required to access the methods in the collection view controller.
The responder chain can help.
The view can query the responder chain for the first target that can accept a message. Suppose the message is -fooBar, then the view can query the target using the method -[UIResponder targetForAction:sender:]
// find the first responder in the hierarchy that will respond to -fooBar
id target = [self targetForAction:#selector(fooBar) sender:self];
// message that target
[target fooBar];
Note that this communication is controlled by this method:
(BOOL)canPerformAction:(SEL)action
withSender:(id)sender;
This default implementation of this method returns YES if the responder class implements the requested action and calls the next responder if it does not.
By default, the first object that responds to that message will become the target so you may want to override the canPerformAction:withSender: if needed for some views or view controllers.
For that you can do like that :
In Collection View Controller -> .h file
#interface CollectionViewController : UICollectionViewController<ColectionCellDelegate>
#end
In Collection View Controller -> .m file
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return [self.collectionData count];
}
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
CollectionCell *cell = (CollectionCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"CollectionCell" forIndexPath:indexPath];
cell.cellData = [self.collectionData objectAtIndex:indexPath.row];
cell.delegate = self;
return cell;
}
-(void)tableCellDidSelect:(UITableViewCell *)cell{
NSLog(#"Tap %#",cell.textLabel.text);
DetailViewController *detailVC = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
detailVC.label.text = cell.textLabel.text;
[self.navigationController pushViewController:detailVC animated:YES];
}
In CollectionCell.h
#class CollectionCell;
#protocol ColectionCellDelegate
-(void)tableCellDidSelect:(UITableViewCell *)cell;
#end
#interface CollectionCell : UICollectionViewCell<UITableViewDataSource,UITableViewDelegate>
#property(strong,nonatomic) NSMutableArray *cellData;
#property(weak,nonatomic) id<ColectionCellDelegate> delegate;
#end
In CollectionCell.m
#implementation CollectionCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.cellData = [[NSMutableArray alloc] init];
}
return self;
}
-(void) awakeFromNib{
[super awakeFromNib];
self.cellData = [[NSMutableArray alloc] init];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.cellData count];
}
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"TableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
cell.textLabel.text = [self.cellData objectAtIndex:indexPath.row];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[[self delegate] tableCellDidSelect:cell];
}
Still having trouble accessing variables to load into a custom cell. I have a xib, .h, .m named InSeasonCell. I have a IBOutlet InSeasonCell *_cell; in .h of rootviewcontroller. I get lldb error for accessing my productAtIndex values. Any help would be great. I was told to read the Table View Programming Guide.
I create
_dataController = [[InSeasonProductDataController alloc] init];
Which is init in the rootviewcontroller but passed to an other object which populates it with Product objects.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"InSeasonCell";
InSeasonCell *cell = (InSeasonCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
cell = _cell;
_cell = nil;
}
if(_dataController!=nil){
Product *productAtIndex = [_dataController objectInListAtIndex:indexPath.row];
// Configure the cell...
cell.name.text = productAtIndex.name;
cell.week.text = productAtIndex.week;
cell.image.image = productAtIndex.image;
}
return cell;
}
I looked through my code and found that I am passing an object created in one class to the other. for example:
-(id)initWithDataController:(InSeasonProductDataController *)dataController spinner: (UIActivityIndicatorView *)spinner{
if(self = [super init]){
_dataController = [dataController retain];
_spinner = [spinner retain];
}
return self;
}
_dataController gets populated with Product objects later in this method and is released.
To solve this error you need in your xib file click on cell prototype and in Attribute inspection > Identifier insert the same name as you have in .m file (I write down "cell"):
in method:
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
.......
Cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
Cell = [[MainCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
I figured it out. My Product object initialized variables which I had to do a copy for each variable passed in. This got rid of the lldb error.
I am new to this so please bear with me:
I have a .xib in IB containing a UIScrollView that has a UITableView embedded in it. I would like to load custom UITableViewCells into the UITableView. I have four/five custom cells created in IB but cannot get the first to load correctly.
Here are relevant screenshots from IB:
I have set the class for the custom UITableViewCell created in IB to the UITableView class I created called "itemCell". Additionally, I have connected the three text fields outlets and delegates to "itemCell".
Here is itemCell.h:
#import <UIKit/UIKit.h>
#interface itemCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UITextField *quantityTextField;
#property (weak, nonatomic) IBOutlet UITextField *itemTextField;
#property (weak, nonatomic) IBOutlet UITextField *priceTextField;
#end
Here is itemCell.m:
#import "itemCell.h"
#implementation itemCell
#synthesize quantityTextField,itemTextField,priceTextField;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
In filecontroller.m, which is the rootcontroller .xib's implementation file I create a new cell based on the user pressing a button (add it to an array) and then reload the tableview. I am getting no errors but I am getting a normal cell loaded in rather than what I have created in IB. Here is rootcontroller.m. Any help is appreciated.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
scrollView =(UIScrollView *)self.view;
items = [[NSMutableArray alloc] init];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [items count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
return [items objectAtIndex:[indexPath row]];
}
- (UITableViewCell *)initiateNewCell{
itemCell *cell = [[itemCell alloc] init];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
return cell;
}
- (IBAction)addItem:(id)sender {
//creates the new cell to be added
[items addObject:[self initiateNewCell]];
[self.tableView reloadData];
As of iOS 5 you can now load a UITableViewCell from a nib for cell reuse with the following function.
- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier
First make sure you create an IB file that contains only the UITableViewCell
Under Identify inspector: Set the class of the UITableViewCell to "itemCell"
Under attributes inspector: Set the identifier of the UITableViewCell to "itemCellIdentifier"
In viewDidLoad: place the following code, and replace itemCellNibName with the name of the nib that contains the UITableViewCell.
NSString *myIdentifier = #"itemCellIdentifier";
[self.tableView registerNib:[UINib nibWithNibName:#"itemCellNibName" bundle:nil] forCellReuseIdentifier:myIdentifier];
In cellForRowAtIndexPath: place the following code, you can now access your IBOutlet properties you set on the itemCell, and connected in the nib.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
static NSString *myIdentifier = #"itemCellIdentifier";
itemCell *cell = (itemCell *)[tableView dequeueReusableCellWithIdentifier:myIdentifier];
cell.textLabel.text = [NSString stringWithFormat:#"Test Row:%i!",indexPath.row];
return cell;
}
Also: You do not want to include the UITableView inside a UIScrollView, a UIScrollView is already built into the UITableView, which allows for proper cell queing.
Also: I suggest you just get the bare bones of this going first, before you start pulling data from an array.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 10;
}
Also: As someone else had mentioned, the array contains the data that will populate the UITableViewCells, not the actual cells themselves.
In your
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//This identifier string needs to be set in cell of the TableViewController in the storyboard
static NSString *CellIdentifier = #"Cell";
// Resuse the cell
SomeCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// If there are no cell to be reused we create a new one
if(cell == nil) {
cell = [SomeCustomCell new];
}
// Configure the cell...
NSString *someString = [yourArrayWithStringsOrWhatEver objectAtIndex:indexPath.row];
// Setting the some property of your custom cell
[cell.yourSpecificCellProperty someString];
[cell.yourOtherSpecificCellProperty setText:#"What Ever your want!"];
}
Your cell's properties could be whatever your have connected to your custom cell in interface builder.
Hope it helps!
Well there are a few things that aren't right:
The class name begins with upper case letter itemCell -> ItemCell
You should reuse the cell. The way you want to do this, you will create a separate cell for each index path.
the items array should only contain the data source of your table, not your cells
instead of calling reload data, you can add just one row to the table, and it can be animated too
Try something like:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
scrollView =(UIScrollView *)self.view;
items = [[NSMutableArray alloc] init];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [items count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[NSBundle mainBundle] loadNibNamed:#"itemCell" owner:self options:nil].lastObject;
cell.reuseIdentifier = CellIdentifier;
}
// Do any additional setup to the cell
return cell;
}
- (IBAction)addItem:(id)sender {
[items addObject:[NSNumber numberWithInt:items.count]]; // Here comes the data source
[self.tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:items.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
}
PS: I wrote it without an IDE so there might be some errors
My goal is to have something like a "select" option in a HTML form, but now in my app. After doing research it's probably best to do this with a table view. I though of the picker view, but the fixed height is too big.
With the interface builder I simply placed a table view on my subclass of UIViewController.
How do I fill the Table view with options? I've seen many tutorials, but those are all for having a UITableView as their own class and filling up the entire screen. In my application this is just a small piece of the entire form.
What a nightmare to create a relatively simple thing like a table view. It either crashes or I get a table view that covers my entire view and that is not filled with anything.
The variable countryTable is connected to the object in the interface builder.
Frustrated after a hard day of work. Anyone got the complete working code? That would be great. I already had a great look at apple's explenation AND various tutorials, but I can't figure it out.
I've tried multiple things, but this is my current code:
#interface myView: UIViewController
{
NSArray *countryArray;
IBOutlet UITableView * countryTable;
}
#property (nonatomic, retain) UITableView *countryTabel;
#end
and in my .m file
#implementation myView
#synthesize countryTable;
- (void)loadView
{
self.countryTable.dataSource = self;
}
- (void)viewDidLoad
{
NSArray *array = [[NSArray alloc] initWithObjects:#"test1", #"test2",
#"test3",nil];
self.countryTable = array;
[array release];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void) dealloc
{
[countryTable release];
[super dealloc];
}
#pragma mark -
#pragma mark Table View Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [self.countryTable count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [countryTable objectAtIndex:row];
return cell;
}
#end
You are on the right track. If you were to use a UITableViewController subclass, you would obviously have a full screen table view by default. Going the route of using a UIViewController subclass with a UITableView as a subview in the UIViewController's view is the right way to go. A few things that you will need to address are:
1) In the UIViewControllers header file you will need to add <UITableViewDatasource, UITableViewDelegate> as your view controller is responsible for fill implementing this functionally.
2) In viewDidLoad:, set self.contryTable.delegate = self; and self.countryTable.datasource = self;
The following protocol methods need to be implemented like so:
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return countryArray.count;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [countryArray objectAtIndex:row];
return cell;
}
Hope this helps.
I accidentally deleted my firstviewcontroller.m file which is for a view that has a tableview. I then re-created my .m file the best I can remember and thought I had it all correct.
I'm now getting an error on the line
[self.tableview refresh];
saying self.tableview isn't found.
I can't seem to figure out what I missed. I don't want to overwhelm you guys with code so I'll try to just post the pertinent part.
#import "FirstViewController.h"
#import "Shared.h"
#import "Message.h"
#implementation FirstViewController
-(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];
}
Message *msg = [[Shared sharedInstance].messages objectAtIndex:indexPath.row];
NSString *authorName = msg.authorName;
NSString *cellValue = authorName;
cell.textLabel.text = cellValue;
return cell;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
`return [[Shared sharedInstance].messages count];`
}
-(void) viewWillAppear:(BOOL)animated {
`[self.tableView reloadData];`
}
tableView is a property of UITableViewController. Double-check that you inherited FirstViewController from a UITableViewController, but not from UIViewController.