iphone protocol problem - objective-c

I am missing something here, where I have a class, EditableCell, and protocol, EditableCellDelegate, defined for handling a table cell for editing. (The original code comes from "iPhone for Programmers" by Paul Deitel).
While I have imported the header for EditableCell into my file ClientEditTVC.h, the properties and methods of EditableCell are not recognized in ClientEditTVC.m.
Here is the prewritten code for EditableCell.h and .m:
#import <UIKit/UIKit.h>
#protocol EditableCellDelegate; // declare EditableCellDelegate Protocol
#interface EditableCell : UITableViewCell <UITextFieldDelegate>
{
id <EditableCellDelegate> delegate; // this class's delegate
UITextField *textField; // text field the user edits
UILabel *label; // label on the left side of the cell
} // end instance variables declaration
// declare textField as a property
#property (nonatomic, retain) UITextField *textField;
// declare label as a property
#property (readonly, retain) UILabel *label;
//declare delegate as a property
#property (nonatomic, assign) id <EditableCellDelegate> delegate;
- (void)setLabelText:(NSString *)text; // set the text of label
- (void)clearText; // clear all the text out of textField
#end // end interface EditableCell
#protocol EditableCellDelegate // protocol for the delegate
// called when the user begins editing a cell
- (void)editableCellDidBeginEditing:(EditableCell *)cell;
// called when the user stops editing a cell
- (void)editableCellDidEndEditing:(EditableCell *)cell;
// called when the user touches the Done button on the keyboard
- (void)editableCellDidEndOnExit:(EditableCell *)cell;
#end // end protocol EditableCellDelegate
And
#import "EditableCell.h"
#implementation EditableCell
#synthesize textField; // synthesize get and set methods for delegate
#synthesize label; // synthesize get and set methods for delegate
#synthesize delegate; // synthesize get and set methods for delegate
// initialize the cell
- (id)initWithStyle:(UITableViewCellStyle)style
reuseIdentifier:(NSString *)reuseIdentifier
{
// call the superclass
if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]))
{
// create the label on the left side
label = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 0, 20)];
// create the text field to the right of the label
textField =
[[UITextField alloc] initWithFrame:CGRectMake(0, 10, 0, 20)];
[textField setDelegate:self]; // set the delegate to this object
// call textFieldDidEndOnExit when the Done key is touched
[textField addTarget:self action:#selector(textFieldDidEndOnExit)
forControlEvents:UIControlEventEditingDidEndOnExit];
[self.contentView addSubview:label]; // add label to the cell
[self.contentView addSubview:textField]; // add textField to cell
} // end if
return self; // return this Editable cell
} // end method initWithFrame:reuseIdentifier:
// method is called when the user touches the Done button on the keyboard
- (void)textFieldDidEndOnExit
{
[textField resignFirstResponder]; // make the keyboard go away
[delegate editableCellDidEndOnExit:self]; // call the delegate method
} // end method textFieldDidEndOnExit
// set the text of the label
- (void)setLabelText:(NSString *)text
{
label.text = text; // update the text
// get the size of the passed text with the current font
CGSize size = [text sizeWithFont:label.font];
CGRect labelFrame = label.frame; // get the frame of the label
labelFrame.size.width = size.width; // size the frame to fit the text
label.frame = labelFrame; // update the label with the new frame
CGRect textFieldFrame = textField.frame; // get the frame of textField
// move textField to 30 pts to the right of label
textFieldFrame.origin.x = size.width + 30;
// set the width to fill the remainder of the screen
textFieldFrame.size.width =
self.frame.size.width - textFieldFrame.origin.x;
textField.frame = textFieldFrame; // assign the new frame
} // end method setLabelText:
// clear the text in textField
- (void)clearText
{
textField.text = #""; // update textField with an empty string
} // end method clearText
// delegate method of UITextField, called when a text field begins editing
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[delegate editableCellDidBeginEditing:self]; // inform the delegate
} // end method textFieldDidBeginEditing:
// delegate method of UITextField, called when a text field ends editing
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[delegate editableCellDidEndEditing:self]; // inform the delegate
} // end method textFieldDidEndEditing:
// free EditableCell's memory
- (void)dealloc
{
[textField release]; // release the textField UITextField
[label release]; // release the label UILabel
[super dealloc]; // call the superclass's dealloc method
} // end method dealloc
#end // end EditableCell class definition
And here is the relevant code from ClientEditTVC.h and .m
#import <UIKit/UIKit.h>
#import "EditableCell.h"
#interface ClientEditTVC : UITableViewController <UITableViewDataSource, EditableCellDelegate> {
NSArray *fields;
NSMutableDictionary *data;
BOOL keyboardShown;
EditableCell *currentCell;
}
#end
and
#import "ClientEditTVC.h"
#implementation ClientEditTVC
// stuff here
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[EditableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
// get the key for the given index path
NSString *key =
[fields objectAtIndex:indexPath.row + indexPath.section * 3];
[cell setLabelText:key]; // update the cell text with the key
// update the text in the text field with the value
//cell.textField.text = [data valueForKey:key];
return cell;
}
// more stuff here
#end
I get a warning at the line [cell setLabelText:key]; that UITableViewCell may not respond to 'setTableText'. But tracing though with breakpoints, the setTextField code in EditableCell is being executed.
The line (commented out) for cell.textField.text produces an error, Property 'textField' not found on object of type 'UITableViewCell'
Obviously the compiler is not seeing that I have subclassed UITableViewCell, and I'm not sure why. It's even stranger, to me, that the setLableText method is getting executed. I went back to the sample code provided by Deitel, and these problems don't occur. I have looked my code over carefully, and can't seen any significant difference.
I would appreciate suggestions on what I am overlooking.

You declared cell like this:
UITableViewCell *cell;
So it is not an EditableCell. If you declare it like so:
EditableCell *cell;
it will not give you the warnings. It will probably warn that you're assigning a UITableViewCell to cell, but you can "fix" that using a cast, i.e.
EditableCell *cell = (EditableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Also, you need to adjust the return type of the function. This should eliminate all compiler warnings.

Redeclare cell as a EditableCell * instead of a UITableViewCell * and that warning should go away.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[EditableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
// get the key for the given index path
NSString *key = [fields objectAtIndex:indexPath.row + indexPath.section * 3];
[cell setLabelText:key]; // update the cell text with the key
if ([cell isKindOfClass:[EditableCell class]]) {
EditableCell* editableCell = (EditableCell*)cell;
// update the text in the text field with the value
editableCell.textField.text = [data valueForKey:key];
}
else {
assert(0 && "is it alright that this instance is not an EditableCell?");
}
return cell;
}

Related

Populate UITableView from button pressed

I am trying to populate UITableView from NSMutableArray. I have UITextField and a button on a ViewController. When I type any text in the UITextField and click button, I can see the text being added to the array with NSLog. I set breakpoints on the data source method of UITableView but it does not even hit those breakpoints when I click the button.
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
{
NSMutableArray *arrBarcode;
IBOutlet UITextField *txtInsert;
}
#property IBOutlet UITableView *myTableView;
-(IBAction)btnPressed:(id)sender;
#end
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.myTableView.delegate = self;
self.myTableView.dataSource = self;
arrBarcode = [[NSMutableArray alloc]init];
}
-(IBAction)btnPressed:(id)sender{
[arrBarcode addObject:txtInsert.text];
NSLog(#"array count is : %i", [arrBarcode count]);
[self.myTableView reloadData];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[txtInsert resignFirstResponder];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)numberOfSectionsInTableView: (UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if ([arrBarcode count] == 0){
return 0;
}
else{
NSLog(#"Number of Rows : %i", [arrBarcode count]);
return [arrBarcode count];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell Identifier";
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString *barcode = [arrBarcode objectAtIndex:[indexPath row]];
[cell.textLabel setText:barcode];
return cell;
}
#end
When I initialize a NSMutable Array with some data in the viewDidLoad method, the UITableView is populating fine but not with dynamic array. I am newbie in Objective C, Can someone point me to right direction?
Code looks OK (even if not very efficient). You have to check if the button is indeed connected to the action. In storyboard or Interface Builder, select the button and check the rightmost inspector on the right. See if the action is correctly connected.
Maybe you want to get rid of the touchesBegan call and call resignFirstResponder when the button is pressed.
For numberOfRowsInSection I think this is enough:
return arrBarcode.count;
I'm not sure but the following line looks strange to me:
#synthesize myTableView = myTableView_;
This is telling the compiler to make a getter and setter for the property myTableView and backing it with an iVar named myTableView_. But in your case you have already defined an iVar named myTableView_.
Try connecting the UITableView as a property instead. A property will be backed by an instance variable with the form _yourProperty and have getter and setter generated automatically so #synthesize isn't really needed in this case.

Custom TableView-Cell (Data from server) select multiple values with accessory change

I am working with TableView and wanted Custom TableViewCell to have a Small Image, Name and one custom image (With Tickmark and without Tick) can be on accessory to show if Cell is selected and if it's not selected it will show without Tick image on unselected cells.
And if i want to select multiple cells then it should show Tick image on selected Cells and Untick image on unselected cells and after that when i click on a button then i should be able to get the selected cell id's.
On the tableView i am getting all the values from the server and images also from URL's but the Tickmark and Unselected Tick mark image will be used the project itself.
So far i have created :
Class .h,.m,.xib of "ResultTableCell" of type UITableViewCell and my Main view "Result" with the TableView and a Button on top (on click of button i'll get the values of selected cells)
ResultTableCell.h
#import <UIKit/UIKit.h>
#interface ResultTableCell : UITableViewCell
#property (nonatomic, retain) IBOutlet UILabel *nameLabel;
#property (nonatomic, retain) IBOutlet UIImageView *thumbImageView;
ResultTableCell.m
#import "ResultTableCell.h"
#implementation ResultTableCell
#synthesize nameLabel,thumbImageView;
- (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
}
ResultTableCell.xib
The right hand side image on the xib is the place where the accessor image will come.
ResultTableCell.xib
And the main xib
Result.h
#import <UIKit/UIKit.h>
#import "ASIFormDataRequest.h"
#interface Results : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
NSMutableArray *nameData;
}
#property (nonatomic, retain)NSMutableArray *nameData;
#property (nonatomic, retain)NSMutableArray *ImageData;
#property (nonatomic, retain)NSMutableArray *idData;
#property (nonatomic, retain)UITableView *table;
#property (nonatomic, retain) IBOutlet UIButton *done;
#property (nonatomic, retain) NSMutableArray *arFors;
-(IBAction)save_done:(id)sender;
Result.m
#import "Results.h"
#import "ResultTableCell.h"
#interface Results ()
#end
#implementation Results
#synthesize arFors;
#synthesize done,nameData,table,addressData,ImageData,idData;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.arFors=[NSMutableArray array];
// I am Getting Name,id and image url data from my HomeViewController
NSLog(#"Name Data from home view is %#",nameData); // 10 Names get's printed in log
NSLog(#"id Data is %#",idData);
NSLog(#"URL image data is %#",ImageData);
table = [[UITableView alloc]initWithFrame:CGRectMake(0, 221, 320, 327) style:UITableViewStylePlain];
table.delegate = self;
table.dataSource = self;
[self.view addSubview:table];
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"Name data count is %d",nameData.count);
return nameData.count;
//return 10;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 70;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
/* UITableViewCell *cell = [tableView dequeueReusableHeaderFooterViewWithIdentifier:#"MainCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MainCell"];
}*/
static NSString *simpleTableIdentifier = #"ResultTableCell";
ResultTableCell *cell = (ResultTableCell *)[table dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ResultTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if ([self.arFors containsObject:[NSNumber numberWithInt:indexPath.row]]) {
cell.accessoryView = [[ UIImageView alloc ]
initWithImage:[UIImage imageNamed:#"table_tick" ]];
}
else {
cell.accessoryView = [[ UIImageView alloc ]
initWithImage:[UIImage imageNamed:#"table_add" ]];
}
NSLog(#"data is ************* %#",nameData);
cell.nameLabel.text = [nameData objectAtIndex:indexPath.row];
NSURL * imageURL = [NSURL URLWithString:[ImageData objectAtIndex:indexPath.row]];
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage * image2 = [UIImage imageWithData:imageData];
cell.ImageView.image = image2;
cell.ImageView.contentMode = UIViewContentModeScaleAspectFit;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"didSelectRowAtIndexPath %d",indexPath.row);
if ([self.arFors containsObject:[NSNumber numberWithInt:indexPath.row]]) {
[self.arFors removeObject:[NSNumber numberWithInt:indexPath.row]];
}
else{
[self.arFors addObject:[NSNumber numberWithInt:indexPath.row]];
// [self.table cellForRowAtIndexPath:indexPath];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[tableView reloadData];
}
-(IBAction)save_done:(id)sender
{
NSLog(#"selected cell values are %#",self.arFors);
}
Now with this code everything is working fine (tick image is shown on selected cells and untick image on unslected cells and on clicking the Done button i am getting the selected cell values),
But the Problem comes when i tapp on a cell then it like hangs and takes 5-6 seconds of time to change accessor image as it fires [tableView reloadData] in didselectrowatindexpath method so all data reloads again in the tableview and then the accessor image changes, please can any one correct my code or enhance it so that it works fast.
I have tried a lot of ways but i was not able to do it without the reloading of table and if i reload table it takes long time.
Coding help will be much tankful.
Your problem is:
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
Because it downloads all of the image data from the network each time you reload the table view. You should be doing this asynchronously and caching the returned image so you don't need to download it repeatedly. Take a look at a library like SDWebImage to help you with this.

Objective c - Best practice to handle a button touch event for a button of a custom UITableViewCell

What is best practice to handle a button touch event for a button of a custom UITableViewCell?
my classes:
MyViewController, MyCustomCell
I can think of three options:
First option- Have the button as a property of MyCustomCell, and then add a target to it in the MyViewController .m file with MyViewController as the target.
MyViewController .m file
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"customCell";
MyCustomCell *cell = (MyCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[cell.theButton addTarget:self
action:#selector(theButtonTapped:)
forControlEvents:UIControlEventTouchUpInside];
}
// Configure the cell...
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)theButtonTapped:(UIButton *)sender
{
MyCustomCell *selectedCell = (MyCustomCell *)sender.superview;
if (selectedCell) {
NSIndexPath *indexPath = [self.tableView indexPathForCell:selectedCell];
MyModel *selectedModel = [self.model objectAtIndex:indexPath.row];
// do something with the model...
}
}
Second option- If the custom cell was made in IB, Set the nib File's Owner to be MyViewController, implement buttonTapped: method in MyViewController and connect the button's Touch Up Inside event to the buttonTapped: method.
Third option- if the custom cell wasn't made in IB, add a target to the button in the MyCustomCell .m file with MyCustomCell as the target.
Define a MyCustomCellDelegate add #property (nonatomic, assign) id<MyCustomCellDelegate> delegate to MyCustomCell and call this delegate when button tapped.
Set MyViewController as the cell's delegate when creating cells and implement the MyCustomCellDelegate protocol.
MyCustomCell .h file
#class MyCustomCell;
#protocol MyCustomCellDelegate <NSObject>
- (void)buttonTappedOnCell:(MyCustomCell *)cell;
#end
#interface MyCustomCell : UITableViewCell
#property (nonatomic, retain) UIButton *theButton;
#property (nonatomic, assign) id<MyCustomCellDelegate> delegate;
#end
MyCustomCell .m file
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.theButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.theButton.frame = CGRectMake(10,10,50,30);
[self addSubview:self.theButton];
[self.theButton addTarget:self
action:#selector(theButtonTapped:)
forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
- (void)theButtonTapped:(UIButton *)sender
{
[self.delegate buttonTappedOnCell:self];
}
MyViewController .m file
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"customCell";
MyCustomCell *cell = (MyCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.delegate = self;
}
// Configure the cell...
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)buttonTappedOnCell:(MyCustomCell *)selectedCell
{
if (selectedCell) {
NSIndexPath *indexPath = [self.tableView indexPathForCell:selectedCell];
MyModel *selectedModel = [self.model objectAtIndex:indexPath.row];
// do something with the model...
}
}
Store the row of the cell as tag property of your custom button.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// bla bla bla
if (!cell)
{
//bla bla bla
[cell.yourButton addTarget:self selector:#selector(yourButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
}
// bla bla bla
cell.yourButton.tag = indexPath.row;
}
-(void)yourButtonTapped:(id)sender
{
int tag = [(UIButton *)sender tag];
NSLog(#"tapped button in cell at row %i", tag);
}
Using tag, from my point of view, would break the strictness of your code. In addition, when you have multiple sections, using tag definitely would make a mess of your code.
To avoid this problem, you can subclass UITableViewCell and make it hold an indexPath property to let the cell know its precise position.
Another problem here is, if UITableView invokes API to insert or delete row, you have to update visible cells' position data
I don't think that is the best practice.
There exists a better way.
I strongly recommend to use MVVM when you have to handle different touch events in your Cell.
In this pattern, your custom UITableViewCell would hold a custom CellViewModel. This class would be responsible for holding all data you associate with the cell, so you can retrieve the data and put the event handling logic inside the cell.
I have implemented block based approach by subclassing UIButton :
typedef void (^ActionBlock)(id sender);
#interface UIBlockButton : UIButton {
ActionBlock _actionBlock;
}
-(void)handleControlEvent:(UIControlEvents)event withBlock:(ActionBlock) action;
​#end
#implementation UIBlockButton
-(void) handleControlEvent:(UIControlEvents)event withBlock:(ActionBlock) action
{
_actionBlock = action;
[self addTarget:self action:#selector(callActionBlock:) forControlEvents:event];
}
-(void) callActionBlock:(id)sender{
_actionBlock(sender);
}
#end
And in tableview delegate :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!cell)
{
cell.yourButton.tag = indexPath.row;// pass tag
[cell.yourButton handleControlEvent:UIControlEventTouchUpInside withBlock:^(id sender) {
// your selector action code
NSLog(#"tapped button in cell at row %i",[(UIButton *)sender tag]);
}];
}
}
At some point your button is tapped, and at that point it is a subview of a cell which is a subview of some tableview.
Just write a method that takes a view, goes up the superview chain to find the containing cell, goes further up to find the tableview, and then asks the tableview for the indexPath of the cell.
That is a lot easier and more reliable than storing a tag containing a row, because you don't run into problems when tableview is edited, and it's much better to have code that finds out which indexPath it is when you need the indexPath, and not in some completely unrelated code when the cell is created.
Swift 3.0 Solution
cell.btnRequest.tag = indexPath.row
cell.btnRequest.addTarget(self,action:#selector(buttonClicked(sender:)), for: .touchUpInside)
func buttonClicked(sender:UIButton) {
let buttonRow = sender.tag
}

UITableView/UITabBarController: trying to figure out a method to pass a variable to my destination controller when a row is selected

I am using a UITableView that points to a UITabBarController to display a series of UIWebViews within these tabs.
I would like define a string to be used to construct a URL for each tab based on the item selected. The issue I am facing is how to pass the URL to the StateTrendViewController controller.
StateTableViewController.h
#import <UIKit/UIKit.h>
#interface StateTableViewController : UITableViewController
{
NSArray *StateList;
}
#property (nonatomic, retain) NSArray *StateList;
- (void) buildStateList;
#end
StateTableViewController.m
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [StateList count];
}
- (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];
}
NSInteger rowNumber = indexPath.row;
NSString *stateName = [StateList objectAtIndex:rowNumber];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = stateName.capitalizedString;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSInteger rowNumber = indexPath.row;
NSString *stateName = [StateList objectAtIndex:rowNumber];
[[self.navigationController.viewControllers objectAtIndex:2] setTitle:stateName.capitalizedString];
}
StateTrendViewController.h
#import <UIKit/UIKit.h>
#interface StateTrendViewController : UIViewController
{
IBOutlet UIWebView *StateTrendView;
IBOutlet NSString *ViewURL;
}
#property (nonatomic, retain) UIWebView *StateTrendView;
#property (nonatomic, retain) NSString *ViewURL;
#end
StateTrendViewController.m
#import "StateTrendViewController.h"
#implementation StateTrendViewController
#synthesize StateTrendView;
#synthesize ViewURL;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void) viewWillAppear:(BOOL)animated
{
NSString *baseURL = #"https://www.google.com/search?q=";
NSString *state = #"test";
NSString *fullURL = [baseURL stringByAppendingString:state];
NSURL *url = [NSURL URLWithString:fullURL];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url]; [StateTrendView loadRequest:requestObj];
}
I need to replace the static setting with the sting passed to the controller using the ViewURL property I have setup:
NSString *state = #"test";
I am using a Storyboard in my project in Xcode 4.2.1. How should I go about passing that string value to my controller?
You override prepareForSegue, more detail is here
If all you are passing is a string, the simplest way might be to define a property on your the view controller you are presenting to hold the string. I notice you already have one, *ViewURL defined, but I'm not sure if that's what you've setup for this specific task or if that is already intended for something else.
Based on the code you've shared, I'm assuming that in your didSelectRowAtIndexPath in your table controller, the controller you are setting the title, and presumably later pushing, is an instance of a StateViewController:
[[self.navigationController.viewControllers objectAtIndex:2] setTitle:stateName.capitalizedString];
If this line does indeed reference an instance of StateTrendViewController, you would assign your string in the same way you're assigning title. This needs to be set before you segue into the new view controller (I don't see that code):
[[self.navigationController.viewControllers objectAtIndex:2] setViewURL:#"MyPassedString"] //assign custom property
When your view controller appears on screen, it will have it's property ViewURL already set.
Also note that your naming style for instance variables is not a standard cocoa convention, ivars beginLowerCase. Additionally, it is unusual and may not work to push a TabBar controller inside an existing nav controller, presumably from table view view controller inside an existing nav controller. Typically a TabBar is considered a top-level navigational construct, and you may wish to rethink your architecture accordingly.

Objective C: Label Text (subclass of UIControl) not displayed in UITableview

I am trying to display a UILabel text (subclass of UIControl) in a cell of a tableview controller.
My code as follows:
In UIControl label .h file
#import <Foundation/Foundation.h>
#interface UIControlLabel : UIControl
{
UILabel *userNameLabel;
}
#property (nonatomic, retain) UILabel *userNameLabel;
#end
In UIControl.m file
#import "UIControlLabel.h"
#implementation UIControlLabel
#synthesize userNameLabel;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
NSLog(#"in init with frame method");
self.userNameLabel = [[UILabel alloc] init];
[self addSubview: userNameLabel];
}
return self;
}
#end
In tableviewcontroller .m file
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* PlaceholderCellIdentifier = #"PlaceholderCell";
int row = [indexPath row];
Answer *thisAnswer = [self.array objectAtIndex:row];
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:PlaceholderCellIdentifier] autorelease];
UIControlLabel *control = [[UIControlLabel alloc]initWithFrame:CGRectMake(35, 10,100, 10)];
control.userNameLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:13.0];
control.tag = 2;
[cell.contentView addSubview:control];
}
UIControlLabel *thisControl = (UIControlLabel *)[cell.contentView viewWithTag:2];
thisControl.userNameLabel.text = [NSString stringWithFormat:#"%#",thisAnswer.userName];
return cell;
}
My issue is that the cell is not showing the label i set above. Is there something I am missing out here?
Seems like you're not setting a frame for your UILabel within your class.
Either call sizeToFit on UILabel, set the frame to match the whole size of your cell, use autosizeMask or implement -layoutSubviews in your UIControlLabel (then you might need to call [cell setNeedsLayout].