As will be seen from my question, I'm a beginner to iOS development. I have looked at several tutorials and several questions but none seem to be covering my case (I'm probably missing something). I am simply trying to add elements to an array from one class, then call the method that reloads the table data from another class. However, when I try to reload the data after calling the relevant method from another class, the table fails to be loaded (no new data seems to be added). In fact, even the previous values of the array in the table seem to be gone.
Class A:
MyClassA.h
#interface MyClassA : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
UITableView *tableView;
NSMutableArray *Elements;
}
#property UITableView *tableView;
#property NSMutableArray *Elements;
-(void) addElement: (NSString *) ElementName;
#end
MyClassA.m
#implementation MyClassA
{
NSString *ElementName[10];
}
- (void) viewWillAppear:(BOOL)animated
{
NSLog(#"MyClassA: viewWillAppear");
ElementName[0] = #" 1 ";
ElementName[1] = #" 2 ";
ElementName[2] = #" 3 ";
Elements = [[NSMutableArray alloc]initWithObjects:ElementName[0], ElementName[1], ElementName[2],nil];
self.tableView.dataSource = self; // The table successfully loads with the data element
}
-(void) addElement: (NSString *) ElementName
{
NSLog(#"Entered addElement"); // This method is successfully accessed
Elements = [[NSMutableArray alloc]initWithObjects:ElementName[0], ElementName[1], ElementName[2],nil]; // The problem is here, printing data in this array shows they have no value
[self.tableView reloadData]; // The problem is here. This does not load the data
}
Class B:
MyClassB.h
#class MyClassA
#interface MyClassB : UIViewController
#property (nonatomic, strong) MyClassA *MyClassACall
-(IBAction) MyButtonClicked: (id) sender;
#end
MyClassB.m
#implementation MyClassB
#synthesize MyClassACall;
-(id) init
{
self = [super init]
if (self) {
NSLog(#"MyClassB init");
MyClassACall = [[MyClassA alloc] init];
}
return self;
}
-(IBAction)MyButtonClicked:(id)sender
{
NSLog("My button is clicked");
[self.MyClassAcall addElement:#"NewElement"];
}
I successfully get all the NSlogs, and the table loads the first time correctly with the provided data. However, when trying to add data by loading a method from another class, the table data remains the same and does not get reloaded. What am I missing here?
I have not loaded the whole code to keep this simple. I hope that this makes sense and please let me know if I could clarify. If a similar question exists, please point me to it and I appreciate your help.
I've made a mini tutorial here for you.
OK, so let's say we got a scenario like this:
There are two view controllers - ViewControllerA and ViewControllerB.
ViewControllerA will be in charge of adding items.
ViewControllerB will be in charge of displaying the items.
So ViewControllerA will look like this:
and ViewControllerB will look like this:
ViewControllerA.h
#import <UIKit/UIKit.h>
#interface ViewControllerA : UIViewController
#property (nonatomic, strong) NSMutableArray *arrItems;
#end
Here, we store the data source called arrItems as a NSMutableArray. We will pass this array to ViewControllerB later.
ViewControllerA.m
#import "ViewControllerA.h"
#import "ViewControllerB.h"
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self initViews];
}
-(void)initViews
{
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.title = #"View Controller A";
UIButton *btnAddItem = [[UIButton alloc] initWithFrame:CGRectMake(60, 200, 200, 50)];
[btnAddItem setTitle:#"Add Item" forState:UIControlStateNormal];
btnAddItem.backgroundColor = [UIColor greenColor];
btnAddItem.layer.cornerRadius = 5.0;
[btnAddItem addTarget:self action:#selector(addItem) forControlEvents:UIControlEventTouchUpInside];
UIButton *btnViewData = [[UIButton alloc] initWithFrame:CGRectMake(60, 300, 200, 50)];
[btnViewData setTitle:#"View Data" forState:UIControlStateNormal];
btnViewData.backgroundColor = [UIColor blueColor];
btnViewData.layer.cornerRadius = 5.0;
[btnViewData addTarget:self action:#selector(viewData) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btnAddItem];
[self.view addSubview:btnViewData];
// init empty array to hold data source items
self.arrItems = [[NSMutableArray alloc] init];
}
-(void)addItem
{
[self.arrItems addObject:#"New Element"];
NSLog(#"added a new element to arrItems, arrItems now has %u items", self.arrItems.count);
}
-(void)viewData
{
ViewControllerB *vcB = [[ViewControllerB alloc] initWithItems:self.arrItems];
[self.navigationController pushViewController:vcB animated:YES];
}
For the green "Add Item" button, we use a method like this to add item to our data source:
-(void)addItem
{
[self.arrItems addObject:#"New Element"];
NSLog(#"added a new element to arrItems, arrItems now has %u items", self.arrItems.count);
}
You'll notice when you tap on the green button, you'll get a console log telling you how many items is currently in your array.
Now when we're done adding items, we have the blue "View Data" button which pushes ViewControllerB onto the navigation stack:
-(void)viewData
{
ViewControllerB *vcB = [[ViewControllerB alloc] initWithItems:self.arrItems];
[self.navigationController pushViewController:vcB animated:YES];
}
ViewControllerB.h
#import <UIKit/UIKit.h>
#interface ViewControllerB : UIViewController <UITableViewDataSource, UITableViewDelegate>
-(id)initWithItems:(NSArray *)arrItems;
// ----------------------------------------------------------------
// view controller B data source is set from
// view controller A using init method shown above
// ----------------------------------------------------------------
#property (nonatomic, copy) NSArray *arrItems;
#property (nonatomic, strong) UITableView *tableView;
#end
Here, we've declared a init method that takes a NSArray parameter. This method will allow us to inject the data source array from ViewControllerA into ViewControllerB.
Per the usual, we also have the tableView in ViewControllerB.
ViewControllerB.m
-(id)initWithItems:(NSArray *)arrItems
{
self = [super init];
if(self)
{
self.arrItems = arrItems;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self initViews];
}
-(void)initViews
{
self.navigationItem.title = #"View Controller B";
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
self.tableView.dataSource = self;
self.tableView.delegate = self;
[self.view addSubview:self.tableView];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.arrItems.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
cell.textLabel.text = self.arrItems[indexPath.row];
return cell;
}
Notice in the initWithItems: method, we're storing the data source from the passed in parameter arrItems into ViewControllerB's self.arrItems:
-(id)initWithItems:(NSArray *)arrItems
{
self = [super init];
if(self)
{
self.arrItems = arrItems;
}
return self;
}
ViewControllerB can then use this data and display it in the tableView data source methods.
So you end up with something like this if you click Add Item five times:
Xcode's console also logs 5 items added:
2014-12-08 10:33:39.195 DataPassingDemo[1211:25705] added a new element to arrItems, arrItems now has 1 items
2014-12-08 10:33:40.099 DataPassingDemo[1211:25705] added a new element to arrItems, arrItems now has 2 items
2014-12-08 10:33:40.619 DataPassingDemo[1211:25705] added a new element to arrItems, arrItems now has 3 items
2014-12-08 10:33:41.123 DataPassingDemo[1211:25705] added a new element to arrItems, arrItems now has 4 items
2014-12-08 10:33:41.667 DataPassingDemo[1211:25705] added a new element to arrItems, arrItems now has 5 items
Is that more clear ?
First of all, i think, it's eligible way to make array in C way as elementName[10], but at this way it's overflow, you can simply use objective-c style with literals, or "initWithCapacity:10". Also Simplify your code, change it at this way:
#implementation MyClassA
{
//NSString *ElementName[10]; // you already have NSMutableArray, why did you do this ?
}
- (void) viewWillAppear:(BOOL)animated
{
NSLog(#"MyClassA: viewWillAppear");
Elements = [#[#"1",#"2",#"3"] mutableCopy];
self.tableView.dataSource = self;
}
-(void) addElement: (NSString *) ElementName
{
NSLog(#"Entered addElement"); // This method is successfully accessed
// You already have initialized array, you need simply to add new element
[elements addObject: elementName];
[self.tableView reloadData];
}
Okay, so. Couple of things...
The way you defined your Elements array is an old method of doing things, You do not need to declare the ivar just the property.
MyClassACall = [[MyClassA alloc] init]; is creating a new instance of MyClassA so whatever you set on that will not actually appear on your view controller you had.
If you need to display a model on one view controller and update it in another view controller i would recommend centralising that model so that both view controllers can access/mutate this model. Singleton is probably the easiest way to achieve that.
Related
Through delegation I created a view controller that takes the input from textfields and passes it back and adds it to an nsmutablearray, successfully adding a row for it. whenever i navigate away from the tableview my newly appended object just disappears. Here is some code to give you a better idea of what i might be doing wrong.
TableViewController.h -
#interface TableViewController : UITableViewController<UITableViewDelegate, UITableViewDataSource>
#property(strong,nonatomic)NSMutableArray *codeList;
#property(strong,nonatomic)NSMutableArray *codeArray;
#end
TableViewController.m -
#interface TableViewController ()
#end
#implementation MCTableViewController
#synthesize codeList;
#synthesize codeArray;
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.codeList = [NSMutableArray arrayWithObjects:#"Array",
#"Pointer",
#"Class",
#"Protocol",
#"Delegate",
nil];
self.codeDescArray = [NSMutableArray arrayWithObjects:
#"Array Description",
#"Pointer Description",
#"Class Description",
#"Protocol Description",
#"Delegate Description",
nil];
)
In the same class I programmatically created a button that moves to the view where data is supposed to be passed back. code below. This is done through delegation.
- (void)addNewCodeButtonPressed {
AddNewCodeVC *addVC = [[AddNewCodeVC alloc] init];
addVC.dataDelegate = self;
UINavigationController *navBar = [[UINavigationController alloc]initWithRootViewController:addVC];
[self.navigationController presentViewController:navBar animated:YES completion:nil];
}
Here is where the delegate logic is created in AddNewCodeVC.h -
#import <UIKit/UIKit.h>
#import "TableViewController.h"
#class AddNewCodeVC;
#protocol addNewCellData <NSObject>
- (void)sendDataToTableView:(NSString*)code codeDesc: (NSString*)desc;
#end
#interface AddNewCodeVC : UIViewController<UITextFieldDelegate> {
__weak id dataDelegate;
}
#property(weak,nonatomic)id<addNewCellData>dataDelegate;
#property(strong,nonatomic)UITextField *codeTextfield;
#property(strong,nonatomic)UITextField *descTextfield;
#end
finally here is the AddNewCodeVC.m -
#import "AddNewCodeVC.h"
#interface AddNewCodeVC ()
#end
#implementation AddNewCodeVC
#synthesize dataDelegate;
- (void)viewDidLoad {
[super viewDidLoad];
self.codeTextfield.delegate = self;
self.descTextfield.delegate = self;
//Programmatically created both textfields, nothing special
}
//"saveNewCode" is action for another button i created
- (void)saveNewCode {
sendDataToTableView:self.codeTextfield.text codeDesc:self.descTextfield.text];
[self.dataDelegate sendDataToTableView:self.codeTextfield.text codeDesc:self.descTextfield.text];
NSLog(#"CODE: %#", self.codeTextfield.text);
NSLog(#"DESC: %#", self.descTextfield.text);
[self dismissViewControllerAnimated:YES completion:nil];
}
The code works but nsmutable array wont hold the passed values if i navigate away from the TableViewController. I think this is because my main view controller programmatically segues to the tableview controller and creates a new instance of it, so that might have some effect? I'll leave some code below just in case it is relevant.
MainviewController.m -
- (void) tableViewBtnPressed:(UIBarButtonItem *)sender {
TableViewController *tableVC = [[TableViewController alloc] init];
//This for another delegate I created, not relevant
tableVC.selectedDataDelegate = self;
UINavigationController *navBar = [[UINavigationController alloc]initWithRootViewController:tableVC];
[self.navigationController presentViewController:navBar animated:YES completion:nil];
}
Hopefully this code is enough to illustrate the problem, i hope someone has an idea whats going on with the NSMutableArray, and why it isn't holding any new objects that are passed into it, any help is appreciated.
I have a textfield on my MainViewController that I'd like to pass a string into from my TableViewController. Specifically when I select a cell (didSelectRowatIndexPath) I'd like to take the text for that indexpath.row and dismiss the TableViewController passing the string into the textfield on my MainViewController. I have attempted to create a delegate to get this to work but all it says in the debugging window is that the correct string is passing but never appears in the textfield... Here is my code showing everything necessary for the delegation.
My TableViewController.h where the delegate is declared...
#protocol sendDataProtocol <NSObject>
- (void)sendDataToMain:(NSString*)text;
#end
#interface TableViewController : UITableViewController<UITableViewDelegate, UITableViewDataSource> {
__weak id selectDataDelegate;
}
#property(nonatomic,weak)id<sendDataProtocol> selectedDataDelegate;
#property(strong,nonatomic)NSArray *presetList; //Holds the strings I want to pass
#end
Then my TableViewController.m file...
#interface TableViewController ()
#end
#implementation TableViewController
#synthesize selectedDataDelegate;
-(void)viewDidLoad {
//http://morsecode.scphillips.com/morse.html
self.presetList = [NSArray arrayWithObjects:#"AS",
#"BCNU",
#"CL",
#"CT",
#"CUL",
#"K",
#"QSL",
#"QSL?",
#"QRX?",
#"QRV",
#"QRV?",
#"QTH",
#"QTH?",
#"R",
#"SN",
#"SOS",
#"73",
#"88",
nil];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.selectedDataDelegate sendDataToMain:self.presetList[indexPath.row]];
NSLog(#"Delegate says: %#", self.presetList[indexPath.row]);
//The NSLog does display the correct cell I pressed, but no data passes back
[self dismissViewControllerAnimated:YES completion:nil];
}
Now here is my MainViewController.h file, this is where my textfield resides, and how I implement the delegate into this file...
#interface MainViewController : UIViewController<UITextFieldDelegate, CAAnimationDelegate, sendDataProtocol> //include protocol here
#property(strong,nonatomic)UITextField *morseTextfield;
- (void)sendDataToMain:(NSString*)text; //conform to protocol
#end
Now the MainViewController.m file...
- (void)viewDidLoad {
[super viewDidLoad];
TableViewController *tvc = [TableViewController new];
tvc.selectedDataDelegate = self;
}
//Protocol method declared here
- (void)sendDataToMain:(NSString*)text {
NSString *str = text;
self.morseTextfield.text = str;
NSLog(#"text: %#",text);
}
The textField NSLog never displays anything, so its not connecting to the delegate or something.
So something is clearly wrong but I'm not sure what. I used this stackoverflow answer as a reference but even then couldn't get it to work (refer to the passing data back section)
Passing Data between View Controllers
Also as a side note I'm coding everything programmatically. Any help is appreciated, thank you.
This is how i created the textfield...
//CONFORMING TO DELEGATES
self.morseTextfield.delegate = self;
//CREATING AND ADDING TEXTFIELD TO VIEW
self.morseTextfield = [[UITextField alloc]initWithFrame:CGRectMake((self.view.frame.size.width-300)/2,
(self.view.frame.size.height)/7, 300, 30.0)];
self.morseTextfield.borderStyle = UITextBorderStyleRoundedRect;
self.morseTextfield.font = [UIFont fontWithName:#"Avenir Next" size:20];
self.morseTextfield.textAlignment = NSTextAlignmentCenter;
self.morseTextfield.placeholder = #"Translate text into morse code";
[self.morseTextfield addTarget:self action:#selector(dismissKeyboard) forControlEvents:UIControlEventEditingDidEndOnExit];
self.morseTextfield.autocorrectionType = UITextAutocorrectionTypeNo;
self.morseTextfield.spellCheckingType = UITextSpellCheckingTypeNo;
self.morseTextfield.autocapitalizationType = UITextAutocapitalizationTypeNone;
[self.morseTextfield setReturnKeyType:UIReturnKeyDone];
[self.view addSubview:self.morseTextfield];
Possibly you set delegate to one instance of TableViewController and display another one.
- (void)viewDidLoad {
[super viewDidLoad];
TableViewController *tvc = [TableViewController new];
tvc.selectedDataDelegate = self;
}
in your code tvc will be just released from memory and you delegate will not work.
Also in you .h file this row is useless.
- (void)sendDataToMain:(NSString*)text; //conform to protocol
In your MainViewController update next method. You have to set delegate in it
- (void) tableViewBtnPressed:(UIBarButtonItem *)sender {
MCTableViewController *tableVC = [[MCTableViewController alloc] init];
tableVC.selectedDataDelegate = self;
UINavigationController *navBar = [[UINavigationController alloc]initWithRootViewController:tableVC];
[self.navigationController presentViewController:navBar animated:YES completion:nil];
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Plz code Help Can anyone tell me how to do that task?
In main screen user selects footballer,in 2nd screen in Table view cell user select specific row and save that row and go back to main view.in main view then it shows the specific row videos.
Basically i want to know about speific row selection,save that selection in table view and show thier contetnts in main screen.
go through the below code, it implements the delegate concept and also implements the solution for ur question hope this helps u :)
//in your main view controller
#import "ViewController.h"
#import "FootBallPlayersViewController.h"
#interface ViewController ()<FootballPlayerDelegate>//confirms to this delegate
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)whenSelectButtonClicked:(id)sender
{
FootBallPlayersViewController *controller = [[FootBallPlayersViewController alloc]initWithNibName:#"FootBallPlayersViewController" bundle:nil];
controller.delegate = self; //u must set to self
[self presentViewController:controller animated:YES completion:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)selectedFootBallPlayer:(NSString *)player
{
//implementation of your delegate method
//hear u are getting the football player name and u can continue further hear
NSLog(#"%#",player);
if([player isEqualToString:#"player1"])
{
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton setTitle:player forState:UIControlStateNormal];
[aButton addTarget:self action:#selector(whenFirstPlayerButtonClicked:) forControlEvents:UIControlEventTouchUpInside]; //add the target to self for click events
aButton.frame = CGRectMake(50, 50, 200, 55);
[self.view addSubview:aButton];
}
else
{
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton setTitle:player forState:UIControlStateNormal];
aButton.frame = CGRectMake(50, 105, 200, 55);
[aButton addTarget:self action:#selector(whenSecondPlayerButtonClicked:) forControlEvents:UIControlEventTouchUpInside]; //same hear
[self.view addSubview:aButton];
}
}
//now define the action methods
- (void)whenFirstPlayerButtonClicked:(UIButton *)sender
{
NSLog(#"player 1 video start");
}
- (void)whenSecondPlayerButtonClicked:(UIButton *)sender
{
NSLog(#"player 2 video start ");
}
#end
in the view that contain's the tableview do somthing like this
//in FootBallPlayersViewController.h
#import <UIKit/UIKit.h>
#protocol FootballPlayerDelegate <NSObject> //define a protocol named FootballPlayerDelegate
- (void)selectedFootBallPlayer:(NSString *)player;
#end
#interface FootBallPlayersViewController : UIViewController
{
NSArray *players;
NSString *selectedPlayer;
}
#property (retain, nonatomic) IBOutlet UITableView *playerTable;
#property (nonatomic, assign) id<FootballPlayerDelegate>delegate; //create a delegate
#end
in your FootBallPlayersViewController.m file
#import "FootBallPlayersViewController.h"
#interface FootBallPlayersViewController ()<UITableViewDataSource,UITableViewDelegate>
{
}
#end
#implementation FootBallPlayersViewController
#synthesize delegate; //synthesizing the delegate
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
players = [[NSArray alloc]initWithObjects:#"player1",#"player2", nil];
// players = [[NSArray alloc]initWithObjects:#"player1","player2", nil];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc
{
[players release];
[_playerTable release];
[super dealloc];
}
- (IBAction)whenDoneButtonClicked:(id)sender {
//when done button clicked -->
//send a delegate to main controller
if([self.delegate respondsToSelector:#selector(selectedFootBallPlayer:)])//to avoid crash
{
[self.delegate selectedFootBallPlayer:selectedPlayer]; //call the delegate method hear
}
//dismiss the view
[self dismissViewControllerAnimated:YES completion:nil];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return players.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableHeaderFooterViewWithIdentifier:#"cell"];
if(cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
cell.textLabel.text = [players objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//u can manage check mark and all, i am getting the selected player name
selectedPlayer = [players objectAtIndex:indexPath.row];
}
#end
Simple solution ...
As you are a newbie , I am clarifying each point.
First make a property in AppDelegate.h
#property int selectedRow;
Save the selected indexpath.row in 2nd screen that is your Table view screen, and also import AppDelegate.h
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.appDelegate=(AppDelegate *)[[UIApplication sharedApplication] delegate];
self.appDelegate.selectedRow=indexPath.row; //saving the row
}
On main screen's viewWillAppear()
-(void)viewWillAppear:(BOOL)animated
{
if(self.appDelegate.selectedRow!=-1)//check wether row is selected or not
{
//action to show the specific row videos
}
}
Good Ways to accomplish this:
Custom Delegate
NSNotificationCenter
NSUserDefaults (edit: unnecessary disk writes)
Maintaining a Common NSObject Subclass and refreshing data on -willAppear
Other Ways:
Database (Core Data / SQLite) or plist (all too heavy for your case) (edit: unnecessary disk writes)
UIPasteBoard
A quick delegate tutorial:
Part 1: Creating the delegate
Suppose this is in the .h of the UITableViewController subclass that I have named YourTableViewControllerClassName
//declare the protocol
#class YourTableViewControllerClassName;
#protocol YourTableViewControllerClassNameDelegate <NSObject>
//#required //uncomment to specify required delegate methods as below
//- (void)requiredMethodNotUsedForThisExample;
#optional
- (void)selectedRow: (NSString *)selectedObj;
#end
#interface YourTableViewControllerClassName : UITableViewController
//declare a weak property to store any object
#property (nonatomic, weak) id <YourTableViewControllerClassNameDelegate> delegate;
#end
Suppose this is the -didSelectRowAtIndexPath of the corresponding UITableViewController subclass:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
//the following line is the main thing and can be called
//in any method within this class (placed wisely)
if([[self delegate] respondsToSelector:#selector(selectedRow)]) { //avoid crash
[[self delegate] selectedRow:cell.textLabel.text];
}
[self.navigationController popViewControllerAnimated:YES];
}
Part 2: Implementing the delegate
Suppose this is the code somewhere in the former UIViewController subclass:
//call this method somewhere
-(void)pushMyTableViewController
{
//declare "UILabel lblText;" in the .h of this class
//lblText = [UILabel alloc] init];
//[lblText setFrame: CGRectMake(0,0,100,35)];
//[self.view addSubview:lblText];
YourTableViewControllerClassName *tvcObj = [[YourTableViewControllerClassName alloc] init];
//for the following line, remember to declare
//<YourTableViewControllerClassNameDelegate> in the .h of this class
//hence declaring that this class conforms to the delegate protocol
[tvcObj setDelegate:self];
[self.navigationController pushViewController:tvcObj animated:YES];
}
And this will be the delegate method you could implement in the former UIViewController subclass:
#pragma mark - Optional YourTableViewControllerClassName Delegate Methods
-(void)selectedRow:(NSString *)selectedObj
{
[lblText setText:selectedObj];
}
NOTE: This will not solve your particular issue because we are only setting a label depending on the selected row from the UITableViewController subclass.
The point was to show how delegation works.
Also, if you can get the cell.textLabel.text and set it on a UILabel in the former class then you can make changes at the appropriate places (mainly the method/s within #protocol)and pass the array index of the selected item instead or any object/variable/whatever that makes your life easier
*If you want something easier then go for NSNotificationCenter or NSUserDefaults or maybe even UIPasteBoard (if it floats your boat)
Use the tableView delegate called when you select any row
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
appDelegate.selectedindex = indexpath.row;
or
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:indexpath.row] forKey:#"SelcetedIndex"];
}
then there is 3 things you can do to get your selected index
1) make a app delegate variable for index path so that you can set here and get the value on other controller
// add property at appDelegate file
#property int selectedIndex;
2) Using NSUserDefault to set the selected index value
// read userDefault value
[[[NSUserDefaults standardUserDefaults] objectForKey:#"SelcetedIndex"] intValue];
3) using delegate to return back the value to previous controller
// try to google and first understand the concept and let me know if you want to go with delgate
I'm trying to accomplish something incredibly simple. I am trying to programmatically push to a viewController when the only item in my collection view is pushed. Nothing happens. I believe there is more than one problem in my tangled mess. My understanding of the basics of arrays is clearly anything but. If I put an NSLog line inside my if statement below, I get nothing when pushing my lone item. Here is my didSelectItemAtIndexPath method:
NSMutableArray *itemApp = [model.viewControllers objectAtIndex:indexPath.row];
if (itemApp == 0) {
NSLog (#"This does not appear")
TableViewController *ctc = [[TableViewController alloc] initWithStyle:UITableViewStylePlain];
[self.navigationController pushViewController:ctc animated:YES];
}
model is defined in viewDidLoad:
model = [[SimpleModel alloc] init];
SimpleModel is mentioned in the .m implementation:
#implementation smileController;
{
SimpleModel *model;
}
viewControllers is property of the SimpleModel class, along with its friend, apps:
#property (nonatomic, strong) NSMutableArray *apps;
#property (nonatomic, strong) NSMutableArray *viewControllers;
Here is the SimpleModel.m
- (id)init
{
if (self = [super init])
{
self.apps = [NSMutableArray arrayWithObjects:#"1", nil];
self.viewControllers = [NSMutableArray arrayWithCapacity:self.apps.count];
TableViewController *tvc = [[TableViewController alloc] init];
[self.viewControllers addObject:tvc];
}
return self;
}
In SimpleModel.m you populate the viewControllers array with a single TableViewController.
Given this, when the first block of code you posted should be more like this:
TableViewController *itemApp = [model.viewControllers objectAtIndex:indexPath.row];
if (itemApp) {
NSLog (#"This should appear")
[self.navigationController pushViewController:itemApp animated:YES];
}
This assumes you want to push the view controller you obtain from the model.viewControllers property.
Please note that itemApp can only be nil if model or model.viewControllers are nil.
I want to load data (an array of strings) from the parent view into a set of UITextFields in the child view upon presenting the modalView.
I know how to pass from child to parent, and I'm sure it's even easier to go the other way, but I don't know how.
UPDATE: Update removed because I found the problem (double releasing of modal view)
Override the init method for the child view controller.
- (id) initWithStrings:(NSArray *)string {
if (self = [super init]) {
// Do stuff....
}
return self;
}
Then in the parent:
MyChildViewController *vc = [[[MyChildViewController alloc] initWithStrings: strings] autorelease];
Two ways you could do it:
1.Override the init method as Matt suggests
2.Create fields in your child class and pass those values to your text field.
#interface ChildViewController : UIViewController{
NSArray *strings;
UITextfield *textField1;
UITextfield *textField2;
}
...
- (void)viewDidLoad {
[super viewDidLoad];
textField1.text = [strings objectAtIndex:0];
textField2.text = [strings objectAtIndex:1];
}
Then in the parent class:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ChildViewController *childController = [[ChildViewController alloc] init];
childController.strings = your_array_of_strings;
[self.navigationController pushViewController:childController animated:YES];
[childController release];
}
- (id)initWithDataObject:(YourDataObjectClass *)dataObject {
if (self = [super init]) {
self.dataObject = dataObject;
// now you can do stuff like: self.myString = self.dataObject.someString;
// you could do stuff like that here or if it is related to view-stuff in viewDidLoad
}
return self;
}
If you want to get really fancy, you can make a delegate for your child view.
#protocol MyChildViewDelegate
- (NSArray*)getStringsForMyChildView:(MyChildView*)childView;
#end
#interface MyChildView : UIView
{
id <MyChildViewDelegate> delegate;
...
}
#property (nonatomic, assign) id <MyChildViewDelegate> delegate;
...
#end
Then somewhere in your view you would ask for the strings:
- (void)viewDidLoad
{
...
NSArray* strings = [delegate getStringsForMyChildView:self];
...
}
Then in your controller (or where ever) you can do:
myChildView = [[MyChildView alloc] initWith....];
myChildView.delegate = self;
...
- (NSArray*)getStringsForMyChildView:(MyChildView*)childView
{
return [NSArray arrayWithObjects:#"one", #"two", #"three", nil];
}
It's probably a little overkill in this case, but this is how UITableViews do it too: they have a data source delegate to provide them with their contents.