I am developing an app which is similar to the settings app in iphone.
In my first VC i have a 4 rows upon selection it takes to the second VC. my second VC displays list of items. Once the user selected, the selected text should be displayed on the firstVC adjacent to the one selected.
How to achieve it with the help of dictionary objects or in other way.!Thanks in advance...
I did a similar task a few days back and here is how I accomplished that. Note, there might be many alternatives to achieving what you want.
KeyPoint: UITableView is dependent upon its DataSource (array or dictionary) for its data to be displayed in cell as well as number of sections and rows per section.
Now, initially your DataSource has values that are displayed as default. Upon tapping the row, initialize and push the 2ndViewController on navigation stack. In this 2ndViewController, you must somehow update the 1stViewController's DataSource (replacing original values).
Approach 1
You can use Protocols & Delegates
Create a protocol as following.
#protocol MyTableDelegate
- (void) dismissWithData:(NSString*)data;
Create a delegate reference in 2ndViewController, Call that delegate method and pass the selected data
#interface 2ndViewController : UIViewController
#property (assign) id<MyTableDelegate> delegate;
#property (assign) NSIndexPath *ip;
// Also synthesize it
#implementation 2ndViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self.delegate dismissWithData:#"Second Table Selection"];
[self.navigationController popViewControllerAnimated:YES];
}
Now in 1stViewController, implement the TableView & Protocol Method
#interface 1stViewController : UIViewController <MyTableDelegate>
#implementation 1stViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
2ndViewController *controller = [[2ndViewController alloc] initWithNib....];
// Set the Delegate to Self
controller.delegate = self;
self.ip = indexPath;
// Push Controller on to Navigation Stack
}
- (void) dismissWithData: (NSString*) data
{
// We Will Store NSIndexPath ip in didSelectRowAtIndex method
// Use the ip to get the Appropriate index of DataSource Array
// And replace it with incoming data // Reload TableView
[self.dataSource replaceObjectAtIndex:[ip row] withObject:data];
[self.tableView reloadData];
}
Approach 2
You could also pass the data source to 2ndViewController in the didSelectRowAtIndexPath method..
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
2ndViewController *controller = [[2ndViewController alloc] initWithNib....];
controller.dataArray = self.dataSource;
// Push Controller on to Stack
}
Then in the same didSelectRowAtIndexPath method of 2ndViewController, update the data source, and call
[self.navigationController popViewControllerAnimated:YES];
also, you need to reload your tableview in 1stController's ViewWillAppear method
- (void)ViewWillAppear:(BOOL)animated
{
[self.tableView reloadData];
[super ViewWillAppear:animated];
}
I think you need to call [self.tableView reloadData] in viewDidAppear. If possible do go through this link Reload UITableView when navigating back?
The array that you are using in your first VC. Pass that array to the second VC, update it there in the secondVC class and write this statement "[firstVC.tableView reloadData]" in the viewWillAppear method of your firstVC class.
This will update your array of firstVC class in secondVC class when user selects anything in secondVC class, and than when user naivgates back table view of firstVC is reloaded. So that the update array is reflected in table view.
Related
I created master details template project in xcode 4.6 and I added custom cell with 2 textfields. I also created new class which is subclass of UITableViewCell and inside this class I created outlets for text fields. When user types something NSMutableArray is updated and this works fine. Now I am wondering how to pass this array back to MasterViewController (UITableViewController) so that I can use this data to show calculations.
I tried using tutorials for delegates between UIViewControllers but I keep getting errors. Any help is appreciated.
You shouldn't keep data inside the UITableViewCell, as it breaks the MVC.
You need to get a reference of the UITextField on your cell. This is how I do in a login form:
I have a custom cell subclass called TextFieldCell, it has an outlet called textField, I want that my UITableViewController have references to these UITextFields.
First I open my storyboard, set the cell class to TextFieldCell and than connect the UITextField to cell textField outlet. Than I add this to the tableView:cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
(…)
if (indexPath.row == 0) {
// Sets the textField of the first cell as the loginTextField.
self.loginTextField = tCell.textField;
} else {
// Sets the textField of the second cell as the passwordTextField.
self.passwordTextField = tCell.textField;
}
tCell.textField.delegate = self;
(…)
}
Now I can access the value of my loginTextField and my passwordTextField. I do that on the tableView:cellForRowAtIndexPath: because that's when I'm creating the cell to add to the table view.
In your case you need to create Protocol:
I just Give Basic Idea for how to Create Protocol
Also Read This Question
#DetailViewController.h
#import <UIKit/UIKit.h>
#protocol MasterDelegate <NSObject>
-(void) getButtonTitile:(NSString *)btnTitle;
#end
#interface DetailViewController : MasterViewController
#property (nonatomic, assign) id<MasterDelegate> customDelegate;
#DetailViewController.m
if([self.customDelegate respondsToSelector:#selector(getButtonTitile:)])
{
[self.customDelegate getButtonTitile:button.currentTitle];
}
#MasterViewController.m
create obj of DetailViewController
DetailViewController *obj = [[DetailViewController alloc] init];
obj.customDelegate = self;
[self.navigationController pushViewController:reportTypeVC animated:YES];
and add delegate method in MasterViewController.m for get button title.
#pragma mark -
#pragma mark - Custom Delegate Method
-(void) getButtonTitile:(NSString *)btnTitle;
{
NSLog(#"%#", btnTitle);
}
i am kind of making app which play audio using table view
After selecting particular row,it play audio on next view,but it does not solve my problem
Since want it to stop after dismissing the view and return to table view
So i want a way to play song on next view in such a way it stops after dismissing the view
or,
if i can access to the particular row(indexpathy.row) on next view
just property synthesize the raw no or int value to the nextview like bellow..
#interface NextViewController : UIViewController{
int rowNo;
}
#property (nonatomic, assign) int rowNo;
and synthesize in .m file like bellow...
#synthesize rowNo;
and when you push to nextview at that time set this property like this
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NextViewController *objNextViewController = [[NextViewController alloc]initWithNibName:#"NextViewController" bundle:nil];
objNextViewController.rowNo = indexPath.row;
[self.navigationController pushViewController:objNextViewController animated:YES];
[NextViewController release];
}
Simply take a variable in the next view's class and pass in the value of indexpath.row to it when you are selecting the cell. Since this variable has the value of row selected, you can access this value in next view.
I have two UITableview. The first one shows 3 sections with 3 row each one, this is the default layout. When the user press line 2 section 0, the second view is showed to select a value. Once the value is selected, it returns to the first view, but this time, with a different layout. Depending on the value selected, the first view can only show one, two or three sections. I'm trying to achieve this behavior passing the indexpath from the child view to its parent and dynamically change the number of sections. I get the number of row selected in child view, but once it is passed to the parent view, the row numbers gets zero.
The code for child view is:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSUInteger row = indexPath.row;
//Create parent view instance to pass back indexpath as a integer
DiarioA *plc = [[DiarioA alloc] init];
NSInteger i1 = row;
plc.rowTipo = i1;
[plc release];
[self.navigationController popViewControllerAnimated:YES];
}
Pa
ret view (DiarioA.h)
#property (nonatomic, assign) int rowTipo;
PArent view (Diario.m)
#synthesize rowTipo;
- (void)viewWillAppear:(BOOL)animated{
[self.tableView reloadData];
//Check if rowTipo has value
NSLog(#"RowTipo: %d",rowTipo);
}
//Use rowTipo to dynamically adjust uitableview layout.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
if (self.rowTipo==0) {
return 3;
}
return self.rowTipo;
}
Could you help me to indentify why I'm loosing the indexpath that is coming from the childview to parentview. Your help is greatly appreciated.
DiarioA *plc = [[DiarioA alloc] init];
you are creating a new object here and setting the plc.rowTipo = i1; changes the value of this object not the parent object.
Either you pass your parent object to the child controller and then change its value like this.
// child .h file
DiarioA *plc;
#property (nonatomic, assign) DiarioA *plc;
//child .m file
#synthesize plc;
// code when you push your child controller
ChildController *controller = [[ChildController allo] initWithNibName.....];
controller.plc = self
and
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSUInteger row = indexPath.row;
plc.rowTipo = row;
[self.navigationController popViewControllerAnimated:YES];
}
I think you should make protocol of your child view controller and make your parent view controller its delegate. Than just set delegate property after initialization of your child view controller and call your delegate method sending indexpath there.
My problem is how to reload the tableview
I have 2 viewcontrollers.
In first Viewcontroller I have one tableview. if I select any row in tableview it goes to second viewcontroller.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
NextPageController *nextView = [[NextPageController alloc] initWithNibName:#"NextPageView" bundle:nil];
[self.navigationController presentModalViewController:nextView animated:YES];
[nextView release];
}
in second view controller I have one textfield. If I enter any value into the textfield I need to disaplay that value into the first viewcontroller tableview.
can any one help me?
Thanks in advance.
give NextPageController a protocol and a delegate,just like this:
#protocol (NextPageControllerDelegate)
-(void)displayString:(NSString *)inputString;
#end
#interface FirstTableViewController : UITableViewController {
id<NextPageControllerDelegate> stringDelegate;
}
#property (nonatomic, assign) id<NextPageControllerDelegate> stringDelegate;
and in the .m file:
#implementation
#synthesize stringDelegate;
then, when you alloc the NextPageViewController, insert this:
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
NextPageController *nextView = [[NextPageController alloc] initWithNibName:#"NextPageView" bundle:nil];
nextView.stringDelegate = self;
[self.navigationController presentModalViewController:nextView animated:YES];
[nextView release];
}
of course, your table view controller must conforms to the NextPageControllerDelegate protocol, and give the implementation of
-(void)displayString:(NSString *)inputString;
after that, when you are in nextView, and want to have the table view display that string, you may do this:
if(nil != self.stringDelegate)
[self.stringDelegate displayString:someString];
ant then it's done
Make Global String ,
Assign it in secondViewController and when you pop from secondViewController to FirstViewController , viewWillAppear will call.
make logic such it uses global variable and then reload table ..
you need to have a global NSString variable in appDelegate that stores your text of text filed in second view.
Now, when you come back to previous page, in
- (void) viewWillAppear
{
[yourDataSourceArray addObject:appDelegate.yourGlobalString];
[yourTableView reloadData];
}
and yes make sure that your yourDataSourceArray is NSMutableArray.
Hope it helps you.
You could create a property for an NSString in your first view, and a property for an instance of the first view controller (UITableViewController?) in your second view. Then upon saving or popping or whatever you're doing in the second view controller once you have entered the text you want, you could set the property of the NSString, pop the view, and reload the tableView in viewWillAppear. Alternatively you could use delegation as Lewen described.
create global NSMutableArray.
Store and add all data in that NSMutableArray.
In -(void) viewwillappear of first class, call [tablename reloadData];
I have an application in which I have tableview in which I return 3 rows in the tableview. When I select a particular row in the table view another tableview should open which should display list of items and when I select a particular item the value of that particular item should be set to the textlabel of previous tableview.
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if (tableView != secondTableview) {
self.secondTableviewArray =[[NSMutableArray alloc]initWithObjects:#"secondfirst",#"secondSecond",nil];
[secondTableview reloadData];
}
}
Pass the second controller (the one that will appear) a weak reference to the first just before showing it. Once the second view controller has appeared and the user has made the selection (you can catch that in (-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;), send a message to the first giving the value selected.
The first view controller, then can store the new value, and even dismiss/pop the second.
This can also be achieved, by writing your own delegate protocol, so the first conforms to it, and is the delegate for the second.
Take NSString in second view and use the property.from the first view to second view set the string and in second view use that String
If you want to open new table view on click of row then you make new xib file and call like as define in below code:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
XMLBooksViewController * xmlBooksViewController = [[XMLBooksViewController alloc] initWithNibName:#"DetailView" bundle:nil];
XMLBooksAppDelegate * appDelegate = [UIApplication sharedApplication].delegate;
xmlBooksViewController.author = [appDelegate.authors objectAtIndex:indexPath.row];
[self.navigationController pushViewController:xmlBooksViewController animated:YES];
[xmlBooksViewController release];
}
In next file you define another table view, so the list or items comes as table view.