Using a delegate to transfer data - ios

I have a view controller with a static cell named 'Make' I have two controllers one called "AddCarTableViewController" and "MakeTableViewController" when you click on the static cell named 'Make' it presents the make table view controller where you can select the make, then pops the view controller and am trying to store the selected value in the detailTextLabel of the static cell. here is my code for all the controllers.
The problem I'm having is once I select the make everything happens as it should I even log the selected item and it saves it after popping the view controller, but I can't figure out how to implement selected item into the detailTextLabel. Any help will be much appreciated!
"MakeTableViewController.h"
#import <UIKit/UIKit.h>
#import "AddCarTableViewController.h"
#protocol CarMakeDelegate <NSObject>
- (void)updateCarMake:(NSString *)updateMake;
#end
#interface MakeTableViewController : UITableViewController
#property (nonatomic, strong) NSArray *carMakes;
#property (nonatomic, weak) id <CarMakeDelegate> delegate;
#end
MakeTableViewController.m
#import "MakeTableViewController.h"
#interface MakeTableViewController ()
#end
#implementation MakeTableViewController {
NSIndexPath *oldIndexPath;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.carMakes = [[NSArray alloc] initWithObjects:#"Acura", #"Aston Martin", nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#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 [self.carMakes 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];
}
cell.textLabel.text = [self.carMakes objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
oldIndexPath = indexPath;
NSString *addMake = self.carMakes[indexPath.row];
[self.delegate updateCarMake:addMake];
NSLog(#"%#", addMake );
[[self navigationController] popViewControllerAnimated:YES];
}
#end
AddCarTableViewController.h
#import <UIKit/UIKit.h>
#import "MakeTableViewController.h"
#interface AddCarTableViewController : UITableViewController
#property (strong, nonatomic) NSString *makeName;
#property (weak, nonatomic) IBOutlet UITableViewCell *makeCell;
#end
AddCarTableViewController.m
#import "AddCarTableViewController.h"
#interface AddCarTableViewController ()
#end
#implementation AddCarTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
#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 4;
}
-(void)updateCarMake:(NSString *)updateMake {
self.makeCell.detailTextLabel.text = updateMake;
}
#end

You don't need to use delegate in this case. Just update the underlying data model. and call
[tableview reloadData];
When the makeViewController is popped.
In the AddCarVC's cellForRowAtIndex, add another line to check if current indexPath corresponds to Make cell and if it does update the detailLabel text.

Related

UITableView delegate and datasource in UITableViewCell

I have a UITableView inside a UITableViewCell and I need to figure out how to set the sub table view datasource and delegate. At the moment this is what I have:
MainTableViewController.h
#import <UIKit/UIKit.h>
#interface MainTableViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate>
#end
MainTableViewController.m
#import "MainTableViewController.h"
#import "TableViewCell.h"
#interface MainTableViewController ()
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
#implementation MainTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UITableView delegate functions
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 3;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"tableViewCell";
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.cellLabel.text = [NSString stringWithFormat:#"%ld", (long)indexPath.row];
return cell;
}
#end
TableViewCell.h
#import <UIKit/UIKit.h>
#interface TableViewCell : UITableViewCell <UITableViewDelegate, UITableViewDataSource>
#property (weak, nonatomic) IBOutlet UILabel *cellLabel;
#property (weak, nonatomic) IBOutlet UITableView *subTableView;
#end
TableViewCell.m
#import "TableViewCell.h"
#implementation TableViewCell
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
self.subTableView.delegate = self;
self.subTableView.dataSource = self;
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"subTabeViewCell"];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"subTabeViewCell"];
cell.textLabel.text = #"test";
return cell;
}
#end
Because I can't ctrl + drag from my sub table view to the TableViewCell class, I'm trying to set the delegate and datasource programmatically within the initialisation, but it's not working and I'm just getting straight up confused.
I know I can set the datasource and delegate to connect to the first class and then within each of the delegate functions check to see which tableView I'm dealing with, but the with the nature of what I'm trying to do it won't really work, I've tried.
So all help is welcome
So I figured it out, well i figured out a way of doing it. Within the cellForRowAtIndexPath in the MainTableViewController.m, I simply added:
[cell.subTableView setDelegate:cell];
[cell.subTableView setDatasource:cell];
And all is working away

Array not being passed from tableview to view controller through Delegate

I am trying to copy the array from tableview controller to view controller. I have checked the code multiple times and it seems to be okay.
//Delegate class
#import <UIKit/UIKit.h>
#protocol Category <NSObject>
#required
-(void) delegateMethodForCategory : (NSMutableArray *) arrayOfCategory;
#end
#interface Categories : UIViewController <UITableViewDelegate,UITableViewDataSource>
#property (nonatomic) id<Category> delegate;
#property (nonatomic,strong) NSArray *sports;
#property (strong, nonatomic) IBOutlet UITableView *tableview;
#property (nonatomic,strong) NSMutableArray *selectedIndexes;
#end
//Delegate methods
#import "Categories.h"
#interface Categories ()
{
NSMutableArray *array ;
}
#end
#implementation Categories
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_sports= [[NSArray alloc] initWithObjects: #"Baseball", #"Soccer", #"Hockey",
#"Other",nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#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 _sports.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
array = [[NSMutableArray alloc]init];
// Configure the cell...
cell.textLabel.text=[self.sports objectAtIndex:indexPath.row];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = selectedCell.textLabel.text;
if([tableView cellForRowAtIndexPath:indexPath].accessoryType==UITableViewCellAccessoryNone)
{ [tableView cellForRowAtIndexPath:indexPath].accessoryType=UITableViewCellAccessoryCheckmark;
[array addObject:cellText];
}else if([tableView cellForRowAtIndexPath:indexPath].accessoryType==UITableViewCellAccessoryCheckmark){
[tableView cellForRowAtIndexPath:indexPath].accessoryType=UITableViewCellAccessoryNone;
[array removeObject:cellText];
}
}
- (IBAction)doneButton:(id)sender {
[self.delegate delegateMethodForCategory:array];
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
#import <UIKit/UIKit.h>
#import "Categories.h"
#interface ActivityCreator : UIViewController <UIPopoverPresentationControllerDelegate, Category>
#property (nonatomic) Categories *requestClass;
#property (nonatomic,strong) NSMutableArray *arrayOfSports;
#end
//This class implements delegate
import "ActivityCreator.h"
#interface ActivityCreator ()
#end
#implementation ActivityCreator
- (void)viewDidLoad {
[super viewDidLoad];
[self settingUp];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller{
return UIModalPresentationNone;
}
-(void)settingUp{
_requestClass = [[Categories alloc]init];
self.requestClass.delegate = self;
}
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"hubabuba"]){
Categories *pop = (Categories *)segue.destinationViewController;
pop.modalPresentationStyle = UIModalPresentationPopover;
pop.popoverPresentationController.delegate = self;
}
}
-(void) delegateMethodForCategory : (NSMutableArray *) arrayOfCategory {
_arrayOfSports = arrayOfCategory;
NSLog(#"%#",_arrayOfSports);
}
Any guidance where I am doing wrong will be of great help. Have been stuck on this for a while.
The delegate method is not being called at all.
Thanks
Set the delegate of Categories class in prepareForSegue method instead of setting in settingUp method.
Write
pop.delegate = self;
In prepareForSegue method.

Display TableView from TextField and passing data

I'm learning Xcode and programming for the IPad. I have a TableView and can display it using a button. I would rather display it when I click on a TextField. If I dismiss the first responder, the keyboard, how then do I display the tableView? I have not found a example that fits. Any direction would help.
It is just simple
just in UItextField delegate method create your tableview.But return No ,that will never show keyboard and write your tableview code there.
here your have to use user defined delegates.
//firstViewController
***********************
#interface ViewController ()<UITextFieldDelegate,send>
{
UITextField *textField;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
textField=[[UITextField alloc]initWithFrame:CGRectMake(20, 20, 160, 60)];
textField.delegate=self;
textField.backgroundColor=[UIColor greenColor];
[self.view addSubview:textField];
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
TableViewController *table=[[TableViewController alloc]initWithNibName:#"TableViewController" bundle:nil];
table.delegate=self;
[self presentViewController:table animated:YES completion:nil];
return NO;
}
-(void)clickedValue:(NSString *)name
{
textField.text=name;
}
//secondcontroller
*********************
in.h
#protocol send <NSObject>
#required
-(void)clickedValue:(NSString *)name;
#end
#interface........
#property (nonatomic, retain) id<send> delegate;
.m
******
#interface TableViewController ()
{
NSArray *arr;
}
#end
#implementation TableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
arr=[[NSArray alloc]initWithObjects:#"murali",#"mohan",nil];
}
- (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
{
return arr.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];
}
cell.textLabel.text=[arr objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.delegate clickedValue:[arr objectAtIndex:indexPath.row]];
[self dismissViewControllerAnimated:YES completion:nil];;
}

How to make a Sub Table view in a TableViewCell

I have a TableView displaying a list of domain :
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.tableView.dataSource = mainClass.domainList;
}
The domain list is set up like that :
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.domainList count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc] init];
cell.textLabel.text = [[self.domainList objectAtIndex:indexPath.row] name];
return cell;
}
This works perfectly, it displays each domain in a row of my table view.
Now i would like to add a "Sub TableView" in each cell of my Table View to display a list of documents related to the domain.
I tried that :
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableView *table = [[UITableView alloc] init];
table.dataSource = [self.domainList objectAtIndex:indexPath.row];
UITableViewCell *cell = [[UITableViewCell alloc] init];
cell.textLabel.text = [[self.domainList objectAtIndex:indexPath.row] name];
[cell.contentView addSubView table]
return cell;
}
It doesn't crash but it doesn't work neither. I mean the sublist doesn't appear anywhere.
What am i doing wrong?
datasource must be a class implementing the protocol UITableViewDataSource. It looks like you are setting it to a custom object. Create a separate class with the code you used to implement the first table, then set the sublist as source data. In the objc.io article “clean table view code” they explain how to make reusable datasources. Or you can just give it a try on your own.
Consider this code:
// ARRAYDATASOURCE.H
#import <Foundation/Foundation.h>
typedef void (^TableViewCellConfigureBlock)(id cell, id item);
#interface ArrayDataSource : NSObject <UITableViewDataSource>
-(id) init __attribute__((unavailable("disabled, try initWithItems:cellIdentifier:configureCellBlock")));
- (id) initWithItems:(NSArray *)anItems
cellIdentifier:(NSString *)aCellIdentifier
configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock;
- (id)itemAtIndexPath:(NSIndexPath *)indexPath;
#end
// ARRAYDATASOURCE.M
#import "ArrayDataSource.h"
#interface ArrayDataSource ()
#property (nonatomic, strong) NSArray *items;
#property (nonatomic, copy) NSString *cellIdentifier;
#property (nonatomic, copy) TableViewCellConfigureBlock configureCellBlock;
#end
#implementation ArrayDataSource
- (id)initWithItems:(NSArray *)anItems
cellIdentifier:(NSString *)aCellIdentifier
configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock
{
self = [super init];
if (self) {
self.items = anItems;
self.cellIdentifier = aCellIdentifier;
self.configureCellBlock = [aConfigureCellBlock copy];
}
return self;
}
- (id)itemAtIndexPath:(NSIndexPath *)indexPath
{
return self.items[(NSUInteger) indexPath.row];
}
#pragma mark UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.items.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier
forIndexPath:indexPath];
id item = [self itemAtIndexPath:indexPath];
self.configureCellBlock(cell, item);
return cell;
}
#end

Get Object attributes in tableviewcontroller

I'm just going to be crazy. I want to display some attributes from an object in a TableViewController.
To resume :
I've got a first screen with a list of different Aircraft. Each Aircraft is different and get 2 attributes (a name and an identification number). When i click on an aircraft i want to display its informations in a new view controller (here a TableViewController).
The only thing i get is an empty string... I don't understand how to do this.
Here my code for AircraftViewController.h (the list of different aircraft)
#import <UIKit/UIKit.h>
#import "AircraftInfoViewController.h"
#interface AircraftViewController : UITableViewController <AircraftInfoViewControllerDelegate>
#property (nonatomic, strong) NSMutableArray *aircraft;
#end
Here my code for AircraftViewController.m
#import "AircraftViewController.h"
#import "Aircraft.h"
#interface AircraftViewController ()
#end
#implementation AircraftViewController
{
NSString *_info;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (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 [self.aircraft count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
AircraftCell *cell = (AircraftCell *)[tableView dequeueReusableCellWithIdentifier:#"AircraftCell"];
Aircraft *aircraft = (self.aircraft)[indexPath.row];
cell.immatLabel.text = aircraft.immat;
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"PickInfo"]) {
AircraftInfoViewController *aircraftInfoViewController = segue.destinationViewController;
aircraftInfoViewController.delegate = self;
aircraftInfoViewController.info = _info;
}
}
- (void)aircraftInfoViewController:(AircraftInfoViewController *)controller didSelectInfo:(NSString *)info
{
_info = info;
Aircraft *aircraft = [[Aircraft alloc] init];
// Here is my problem !
NSLog(#"String is %#", aircraft.name);
[self.navigationController popViewControllerAnimated:YES];
}
#end
Here my Aircraft Object
#import <Foundation/Foundation.h>
#interface Aircraft : NSObject
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *immat;
#end
Here my AircraftInfoViewController.h (where i display info)
#class AircraftInfoViewController;
#protocol AircraftInfoViewControllerDelegate <NSObject>
- (void)aircraftInfoViewController:(AircraftInfoViewController *)controller didSelectInfo:(NSString *)info;
#end
#interface AircraftInfoViewController : UITableViewController
#property (nonatomic, weak) id <AircraftInfoViewControllerDelegate> delegate;
#property (nonatomic, strong) NSString *info;
#end
Here my AircraftInfoViewController.m
#import "AircraftInfoViewController.h"
#interface AircraftInfoViewController ()
#end
#implementation AircraftInfoViewController
{
NSArray *_infos;
NSUInteger _selectedIndex;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_infos = #[#"TEST"];
_selectedIndex = [_infos indexOfObject:self.info];
}
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_infos count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"AircraftCell"];
cell.textLabel.text = _infos[indexPath.row];
if (indexPath.row == _selectedIndex) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if (_selectedIndex != NSNotFound) {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:
[NSIndexPath indexPathForRow:_selectedIndex inSection:0]];
cell.accessoryType = UITableViewCellAccessoryNone;
}
_selectedIndex = indexPath.row;
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
NSString *info = _infos[indexPath.row];
[self.delegate aircraftInfoViewController:self didSelectInfo:info];
}
#end
Thx for helping...
I don't exactly get your problem, but in your code you are:
//1. creating a new aircraft
Aircraft *aircraft = [[Aircraft alloc] init];
//2. this aircraft object is new and dose not have a name yet as you never assigned a name to it.
//3. this is why your log shows an empty string
NSLog(#"String is %#", aircraft.name);
Looks like you need to print the info:
NSLog(#"String is %#", _info);
But it will be helpful to help you if you could explain what you want to get better.

Resources