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.
Related
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 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.
I have a parent view (table) that passes a detail object to the child view (table).
The parent view has a network request that gets data and passes data to the child view.
I want to be able to update the data when I'm in the child view. I think I need to call the parent view's network request method while viewing the child view, and update the child table. Is this possible?
In Parent VC:
- (void)fetchAppointmentsForVisibleDate {
self.appointmentArray = [DataSource getTodayData:self.visibleDate];
NSMutableArray *array = [NSMutableArray arrayWithCapacity:50];
for (NSDictionary *appointment in self.appointmentArray)
{
[array addObject: [NSString stringWithFormat:#"%#: %#", [appointment objectForKey:#"scheduled_time"], [appointment objectForKey:#"patient"]]];
}
self.listData = array;
[self.appointmentTableView reloadData];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ChildVC *vc = [Child VC alloc]initWithNib#"ChildVC"];
vc.appointmentDictionary = [self.appointmentArray objectAtIndex:path.row];
}
Is your network request is bound to be called by parent view.
If its just a method you can set the delegate of your child to the parent.
i.e in the parent view you can do
create child object and just do
child.delegate=self;
and call your network method from child
i.e [delegate networkMethod];
Ok so lets assume that you code works do the following.
in the .h file of your child class add
{
id delegate;
}
#property(nonatomic,retain) id delegate;
in the .m file of you child do all the needed things like synthesize it etc.
Now in you parent class do
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ChildVC *vc = [Child VC alloc]initWithNib#"ChildVC"];
vc.delegate=self; //here you set the delegate of your child.
vc.appointmentDictionary = [self.appointmentArray objectAtIndex:path.row];
}
Now in your child .m class if you want to call any function that resides in parent view class then just do.
[delegate myNetworkFunction] //it will give warning but dont worry
you can also pass argument if you want
[delegate myNetworkFunction:myArgument];
I have a UITableViewController that has data populated from an NSMutableArray called userList. When specific user is selected, it goes to a detail view, and updates the title in the NavBar, but it wont pass the data to update a UILabel in the UIView.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
//Attempt at a singleton to pass the data
DetailView *details = [[DetailView alloc] init];
details.userNameLbl = [userList objectAtIndex:indexPath.row];
DetailView *detailVC = [[DetailView alloc] initWithNibName:nil bundle:nil];
//This line doesn't pass the data
detailVC.userNameLbl.text = [userList objectAtIndex:indexPath.row];
//This line does update the title in the NavBar
detailVC.navigationItem.title = [userList objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailVC animated:YES];
[details release];
[detailVC release];
}
Should I be trying to push the data from the table view to the detail view, or have the detail view try to pull the data from the table view?
DetailView.h has the following line that is in fact hooked up in IB.
IBOutlet UILabel *userNameLbl
The userNamelbl isn't instantiated until the view is loaded from the nib file. This doesn't happen immediately at initialisation, but will have happened by the time viewDidLoad is called.
So, you should to declare a property in DetailView to store your title, and then assign that value to userNamelbl.text in the viewDidLoad method.
For example, in your table viewController:
DetailView *detailVC = [[DetailView alloc] initWithNibName:nil bundle:nil];
detailVC.userName = [userList objectAtIndex: indexPath.row];
and in your detail viewController:
- (void) viewDidLoad
{
[super viewDidLoad];
self.userNameLbl.text = self.userName;
}
The viewController's navigationItem property is created when the viewController is initialised, hence you can assign to the navigationItem.title immediately.
Swift code
let detailVC = DetailView(nibName: nil, bundle: nil)
detailVC.userName = userList.objectAtIndex(indexPath.row) as? NSString
and
class DetailView: UIViewController {
#IBOutlet var userNameLbl: UILabel
var userName:NSString?
override func viewDidLoad() {
super.viewDidLoad()
self.userNameLbl.text = self.userName
}
}
Are you mixing UIViews and UIViewControllers? You should have a DetailViewController class that inherits from UIViewController or some sublcass (like UITableViewController); it will have DetailViewController.m and DetailViewController.h files to declare and define your class. It should have a corresponding nib that defines the UIView that the UIViewController loads; it will have a DetailView.xib file.
You can't assign the value to the UILabel directly because UIView hasn't been loaded at the time you need to assign the user name value.
In order to do what you want, you should declare a public property (userName) to "push" the value onto the detail view controller from the master controller. Once the detail view is loaded, it can assign the value from the property to the label and nav bar.
In your master view controller (UITableViewController):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
DetailViewController *detailVC = [[DetailView alloc] initWithNibName:#"DetailView" bundle:nil];
detailVC.userName = [userList objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailVC animated:YES];
[detailVC release];
}
In your detail view controller:
DetailViewController.h
#property (retain) NSString* userName;
#property (nonatomic, retain) IBOutlet UILabel *userNameLbl;
DetailViewController.m
#synthesize userName;
#synthesize userNameLbl;
-(void) viewDidLoad {
[super viewDidLoad];
self.userNameLbl.text = self.userName;
self.navigationItem.title = self.userName;
}
Presumably your DetailView requires the data from your selected row to function?
If so, I'd say the 'correct' approach would be to create a custom init method that passed in the data you required. For example:
[[DetailView alloc] initWithTitle:(NSString *)title text:(NSString *)text]
There's nothing inherently wrong with your approach, but passing the data the view controller requires at its creation is architecturally better (in my opinion, I'm sure someone will disagree!). For example, think of a table view controller - you pass in the table view style in the init method, you don't set it later on. Same for a UIImageView - you have an initWithImage method that lets you set the image at creation.
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];