IOS: Passing value from UITableView row to UILabel in First Controller - ios

In my second controller when user select a row and after clicked on the back button
I would like to update a UILabel with the text choice.
I have added a UILabel on the first controller and connected to h. file but I don't know how go on
I would like to replicate the GENERAL/AUTO-LOCK function in iPhone/iPad Settings.

You should use delegates for this.
SecondViewController.h:
#protocol SecondViewControllerDelegate;
#interface
...
#property (nonatomic, assign) id <SecondViewControllerDelegate> delegate;
...
#end
#protocol SecondViewControllerDelegate <NSObject>
- (void)secondViewController:(SecondViewController *)vc didTapRowWithText:(NSString *)text;
#end
SecondViewController.m:
#implementation
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[self.delegate secondViewController:self didTapRowWithText:cell.yourLabel.text];
}
...
#end
whoever created and pushed SecondViewController (and maybe/hopefully also 1st one):
// put this after secondViewController initialization
secondViewController.delegate = self;
- (void)secondViewController:(SecondViewController *)vc didTapRowWithText:(NSString *)text
{
firstViewController.yourLabel.text = text;
}

Related

How to pass message using delegates from one view controller to another using delegate?

main storyboard imageI have one Table View Controller named "Contacttableviewcontroller" and one View Controller as"Detailviewcontroller". I have 2 text fields in my View Controller to give contact name and number. I have a button to save. When I click on that button, it should display it in Table View Controller. Concept I am using is passing information from destination to source using delegates. Here goes my code which is not working properly.
Detailviewcontroller.h
#protocol detailviewcontrollerdelegate<NSObject>
- (void)additem:(NSString *)Name MOBILE:(NSString *)Mobile;
#end
#interface DetaiViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *nametextfield;
#property (weak, nonatomic) IBOutlet UITextField *mobiletextfield;
- (IBAction)Save:(id)sender;
#property(nonatomic,weak)id<detailviewcontrollerdelegate>delegate;
Detailviewcontroller.m
- (IBAction)Save:(id)sender {
[self.delegate additem:self.nametextfield.text MOBILE:self.mobiletextfield.text];
}
Contacttableviewcontroller.h
#interface ContactTableViewController : UITableViewController<detailviewcontrollerdelegate>
#property(strong,nonatomic)NSString *contactname;
#property(strong,nonatomic)NSString *contactno;
-(void)reloadtabledata;
#property(strong,nonatomic)NSArray *contactnamearray;
#property(strong,nonatomic)NSArray *contactnoarray;
#end
Contacttableviewcontroller.m
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 4;
}
- (void)additem:(NSString *)Name MOBILE:(NSString *)Mobile
{
self.contactname=Name;
self.contactno=Mobile;
self.contactnamearray=#[self.contactname];
self.contactnoarray=#[self.contactno];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellreuse" forIndexPath:indexPath];
cell.textLabel.text=[_contactnamearray objectAtIndex:indexPath.row];
cell.detailTextLabel.text=[_contactnoarray objectAtIndex:indexPath.row];
return cell;
}
-(void)reloadtabledata
{
[self.tableView reloadData];
}
Firstly, you need to check, if you have attached your action method, -Save: to your button or not. You can attach it through the storyboard or programatically. To do it through storyboard, give your button a name like saveButton(not compulsory) and then attach it by ctrl dragging as usual.
Make sure, you attach all the IBOutlets through storyboard properly.
P.S: I have updated the variable's name with proper naming convention. You should also follow the camel case convention while naming your variables.
here is the DetailViewController.h code-
#import <UIKit/UIKit.h>
#protocol DetailViewControllerDelegate;
#interface DetailViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *nameTextField;
#property (weak, nonatomic) IBOutlet UITextField *mobileTextField;
#property(strong, nonatomic) IBOutlet UIButton *savebutton;
- (IBAction)Save:(id)sender;
#property(nonatomic,weak)id<DetailViewControllerDelegate>delegate;
#end
#protocol DetailViewControllerDelegate<NSObject>
- (void)additem:(NSString *)Name MOBILE:(NSString *)Mobile;
#end
And DetailViewController.m-
#import "DetailViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (IBAction)Save:(id)sender {
[self.delegate additem:self.nameTextField.text MOBILE:self.mobileTextField.text];
[self.navigationController popToRootViewControllerAnimated:YES];
}
#end
Now, if you put a break point inside your action method, you will see, it is getting called.
You can see an extra line of code-
[self.navigationController popToRootViewControllerAnimated:YES];
-this is making sure that when you press the save button, it not only sends the data, but also returns to you TableView Controller to show your results.
Now, you need to make sure that your DetailViewController knows who is going to implement its delegate. So, in your ContactTableViewController, wherever, you are initialising your DetailViewController, you have to assign its delegate to self.
So, after a little tweaks, the ContactTableViewController.h class looks like-
#import <UIKit/UIKit.h>
#import "DetailViewController.h"
#interface ContactTableViewController : UITableViewController<DetailViewControllerDelegate>
#property(strong,nonatomic)NSString *contactName;
#property(strong,nonatomic)NSString *contactNo;
-(void)reloadtabledata;
#property(strong,nonatomic)NSMutableArray *contactNameArray; //need to be mutable array, so that the data can keep appending
#property(strong,nonatomic)NSMutableArray *contactMobileNoArray; //same as above
#end
Now, there are some small modifications in the file but, the comments should clarify the purpose.
So, the ContactTableViewController.m file looks like
#import "ContactTableViewController.h"
#interface ContactTableViewController ()
#end
#implementation ContactTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
//Make sure you initialize the array before tryig to add any element
self.contactNameArray =[[NSMutableArray alloc]init];
self.contactMobileNoArray=[[NSMutableArray alloc]init];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark-
#pragma mark- TableView Datasource methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.contactNameArray count]; //you need to set the row count as the same as the array elements
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellreuse" forIndexPath:indexPath];
cell.textLabel.text=[self.contactNameArray objectAtIndex:indexPath.row];
cell.detailTextLabel.text=[self.contactMobileNoArray objectAtIndex:indexPath.row];
return cell;
}
-(void)reloadtabledata
{
[self.tableView reloadData];
}
#pragma mark- Segue method
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
[segue.destinationViewController setTitle:#"Add Details"];
DetailViewController *vc = [segue destinationViewController];
vc.delegate=self; // By this, you just told your TableViewController that it is responsible for the implementation of the DetailViewController's delegate
}
#pragma mark- DetailViewController's Delegate method
- (void)additem:(NSString *)Name MOBILE:(NSString *)Mobile
{
self.contactName=Name;
self.contactNo=Mobile;
[self.contactNameArray addObject:self.contactName]; //added the new entry
[self.contactMobileNoArray addObject:self.contactNo]; //added the new entry
[self.tableView reloadData]; //reload the table right after you updated the arrays
}
#end
This should help you with all your queries. If there is a change in the ContactTableViewController.m file, I added one or more comments. I tried to run the app and this is working properly.
Hey Just add this line in your view did load method of Contacttableviewcontroller.
DetailViewController *detailVc=[DetailViewController alloc]init];
detailVc.delegate =self;
Try this one
detailviewcontrollerdelegate
#import <Foundation/Foundation.h>
#protocol detailviewcontrollerdelegate<NSObject>
- (void)additem:(NSString *)Name MOBILE:(NSString *)Mobile;
#end
Detailviewcontroller.h
#import <UIKit/UIKit.h>
#import "detailviewcontrollerdelegate.h"
#interface DetaiViewController : UIViewController{
id< detailviewcontrollerdelegate > delegate;
}
#property (nonatomic, assign) id< detailviewcontrollerdelegate > delegate;
#property (weak, nonatomic) IBOutlet UITextField *nametextfield;
#property (weak, nonatomic) IBOutlet UITextField *mobiletextfield;
- (IBAction)Save:(id)sender;
and other as u have done make it same
**Detailviewcontroller.m**
- (IBAction)Save:(id)sender {
[self.delegate additem:self.nametextfield.text MOBILE:self.mobiletextfield.text];
}

How to change tableview data with button press on a different view controller?

I am having a bit of trouble getting a button pressed on a ViewController to load a specific lot of information in an array for displaying on a UITableViewController.
I know you can do it with detecting the segue but I have tried this without - I had success. I read somewhere else how I can use tags on the button to identify it and I tried to use this but it only displays one set of data no matter what button I have pressed. I've tried swapping a lot of things around to try and get it to work but to no avail. I have a ViewController with the buttons on it, a TableViewController to display the arrays and a CellViewController to display the better description of the tableview info.
My code is pretty 'all over the shop' at the moment. I haven't included the Cell View controllers as I don't think they have that much relevance with what I want to do at this stage.The buttonviewcontroller is just a normal UIViewController and both buttons are linked as 'Button1'class in the storyboard. They have been given tags 0 and 1 which I believe is in under the 'view' subheading in the storyboard. Please alert me if this is wrong and I am missing something really obvious but that was the only place I could find 'tag'.
Honestly I don't know exactly what I'm doing in xcode as I'm not very familiar with it but seem to understanding parts of it. However, I'm not sure exactly what I'm doing wrong at the moment.
Code:
ButtonViewController.M (this is where the buttons are)
#import <UIKit/UIKit.h>
#import "tableViewController.h"
#import "TableCell.h"
#interface ButtonViewController : UIViewController
-(IBAction) button_Clicked:(id)sender;
#property (strong, nonatomic) IBOutlet UIButton *Button1;
#end
ButtonViewController.m
#import "ButtonViewController.h"
#import "tableViewController.h"
#import "TableCell.h"
#interface ButtonViewController ()
#end
#implementation ButtonViewController
-(IBAction) button_Clicked:(id)sender
{
//something here that is going wrong
tableViewController *tableVC = [[tableViewController alloc]initWithNibName:#"tableViewController" bundle:nil];
if(_Button1.tag==0)
{
tableVC.buttonSelected = 0;
}
else if(_Button1.tag==1)
{
tableVC.buttonSelected = 1;
}
[self.navigationController pushViewController:tableVC animated:YES];
[tableVC.tableView reloadData];
#end
tableViewController.h
#import <UIKit/UIKit.h>
#interface tableViewController : UITableViewController
#property (nonatomic, assign) int buttonSelected;
#property (nonatomic, strong) NSArray *Title;
//#property (nonatomic, strong) NSMutableArray *Title;
#property (nonatomic, strong) NSArray *Description;
//#property (nonatomic, strong) NSMutableArray *Description;
//Not sure if Mutable or normal array
#end
tableViewController.m
#import "tableViewController.h"
#import "TableCell.h"
#import "DetailViewController.h"
#import "ButtonViewController.h"
#interface tableViewController ()
#end
#implementation tableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if(_buttonSelected == 0)
{
_Title = #[#"Hamstring Muscle Tear",#"Lower Back Pain"];
_Description = #[#"Blahahaha", #"blahahaha2",#"blalalala3"];
[self.tableView reloadData];
}
else if (_buttonSelected == 1)
{
_Title = #[#"1",#"2",#"3"];
_Description = #[#"dededdededde", #"deddedede2",#"blalalala3"];
[self.tableView reloadData];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return _Title.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TableCell";
TableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
int row = [indexPath row];
cell.TitleLabel.text = _Title[row];
cell.DescriptionLabel.text = _Description[row];
return cell;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"ShowDetails"]) {
DetailViewController *detailviewcontroller = [segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow];
int row = [myIndexPath row];
detailviewcontroller.DetailModal = #[_Title[row],_Description[row]];
}
}
#end
There are two ways to doing same.
Implement delegate method and call it on event.
You can fire NSPostNotification event from one controller to another controller.
Change the data, then post an NSNotification that it changed.
The table view data source observes the notification and calls [tableView reloadData]
You can find details how to do this in apple's sample code.

how to pass data from tableview to another tableview cell?

I am using static UITableView to show profile of a customer.
It has SelectCountryCell to select country which, when clicked, opens new UITableView with country list.
When I select country from Country TableView, It should display in previous TableView's SelectCountryCell.
How do I do this?
You should bind the static cells to outlets in your UITableViewController and put the profile syncing methods to the - viewWillAppear method.
When the user changes the country in the Country list the profile updates. After that when the user moves back to the UITableViewController instance with static content the profile data will be automatically updated.
You can define a delegate in your CityTableView and then define a method in this delegate.
You should realize this method in your CountryTableView.
Then you may get what you want.
I only offer you a thought. You should find the detail by yourself.
MasterViewController.h
#import "DetailViewController.h"
#interface MasterViewController : UITableViewController <DetailProtocol> // Note this.
#property (strong, nonatomic) DetailViewController *detailViewController;
#property (strong, nonatomic, readwrite) NSString *selectedCountry;
#end
MasterViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!self.detailViewController) {
self.detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
}
self.detailViewController.delegate = self; // THIS IS IMPORTANT...
[self.navigationController pushViewController:self.detailViewController animated:YES];
}
// Note this -- It's a delegate method implementation
- (void)setCountry:(NSString *)country
{
self.selectedCountry = country;
}
DetailViewController.h
#protocol DetailProtocol <NSObject>
-(void)setCountry:(NSString *)country;
#end
#interface DetailViewController : UIViewController
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#property (unsafe_unretained) id <DetailProtocol> delegate; // Note this
#end
DetailViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
[self.delegate setCountry:[countries objectAtIndex:indexPath.row]]; // Note this
[self.navigationController popViewControllerAnimated:YES];
}

Passing information between viewControllers in Storyboard

I am learning how to use storyboards by making a very simple app. On the main view controller (InfoViewController), I have a textField by the name: nameField. After entering text in this field, when I enter the save button, the text should should get appended to the array (list) (declared in TableViewController) and be displayed on the table in TableViewController.
Also, the segue identifier is: GoToTableViewController.
However, the text does not get passed from nameField to the list (array). At first, I assumed that I was making some mistake with the textField. So I replaced it with a static text. But that did not help either. Then I checked if the string has been added to the array by using NSLog() , but every time I get Null. From my understanding, the list (array) is not created until TableViewController is loaded. For that reason, I alloc and init list in InfoViewController. But it does not help.
Can somebody please help me find out the mistake that I am making?
Thanks!
Relevant sections of my code are as follows:
InfoViewController.h
#import <UIKit/UIKit.h>
#class TableViewController;
#interface InfoViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *nameField;
#property (strong, nonatomic) TableViewController *tableViewController;
#end
InfoViewController.m
#import "InfoViewController.h"
#import "TableViewController.h"
#implementation InfoViewController
#synthesize nameField;
#synthesize tableViewController;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
tableViewController = [[TableViewController alloc] init];
tableViewController.list = [[NSMutableArray alloc] init];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqual:#"GoToTableViewController"])
{
/* Pass data to list and then reloadTable data */
tableViewController = segue.destinationViewController;
tableViewController.infoViewController = self;
// (*) [tableViewController.list addObject:nameField.text];
// (*) [tableViewController.list addObject:#"Hi!"];
[tableViewController.list insertObject:#"Hi" atIndex:0];
// (**) NSLog(#"%#", [tableViewController.list objectAtIndex:0]);
[tableViewController.tableView reloadData];
}
}
#end
( * ) I inserted these statements to see if I was making a mistake with using the value in nameField.
( ** ) This statement is meant to check the value inserted in the array.
TableViewController.h
#import <UIKit/UIKit.h>
#class InfoViewController;
#interface TableViewController : UITableViewController
#property (nonatomic, strong) NSMutableArray *list;
#property (strong, nonatomic) InfoViewController *infoViewController;
#end
TableViewController.m
#import "TableViewController.h"
#import "InfoViewController.h"
#implementation TableViewController
#synthesize list;
#synthesize infoViewController;
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
list = [[NSMutableArray alloc] init];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{ return 1; }
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{ return list.count; }
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = [list objectAtIndex:indexPath.row];
return cell;
}
#end
Reload the table in viewWillAppear method of tableViewController:
[tableViewController.tableView reloadData];

Delegate not working when selecting row on UITableView

I have a UITableView, which when I select a row, I want to segue to another view, where the details of the tank are displayed... The segue happens, but the delegate does not send the object etc over... I think I have my knickers in a twist over where the delegate is declared/synthesized and implemented etc...
Here is where I declare the delegate in the header file of the UITableViewController:
#class iTanksV2ListViewController;
#protocol iTanksV2ListViewControllerDelegate
- (void) iTanksListViewController:(iTanksV2ListViewController *) sender choseTank:(tank *)tank;
#end
#interface iTanksV2ListViewController : UITableViewController
#property (weak, nonatomic) id <iTanksV2ListViewControllerDelegate> delegate;
#end
and this is what I have in the UITableViewControllers m file:
#implementation iTanksV2ListViewController
#synthesize delegate = _delegate;
- (void)viewDidLoad
{
[super viewDidLoad];
self.tankTableView.delegate = self;
self.tankTableView.dataSource = self;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedTank = [self.tanks objectAtIndex:indexPath.row];
[self.delegate iTanksListViewController:self choseTank:self.selectedTank];
}
...and then here is the code I have for the delegate in the DetailViewController implementation file...
#interface tankDetailViewController () <iTanksV2ListViewControllerDelegate>
#end
-(void)iTanksListViewController:(iTanksV2ListViewController *)sender choseTank:(id)tank
{
self.tankToShow = tank;
}
All the other variables etc are declared, I have left them out in the hope it makes things clearer - the code compiles, and the segue happens but the delegate doesn't seem to do anything!!!
You mention segues so I'm assuming you're using a storyboard. If that's true, forget about delegates for this purpose. A delegate is supposed to be an object that performs some action for another but all you need is data transfer.
I suggest using the prepareForSeque: method instead in your iTanksV2ListViewController class. Keep the line that sets self.selectedTank when a row is tapped but then put something like this in prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
tankDetailViewController *next = (tankDetailViewController *)[segue destinationViewController];
next.tankToShow = self.selectedTank;
}

Resources