IOS storyboard - show different views on selection of table cells - ios

i am new to ios programming. I have multiple view controllers. i am showing the tableView Controller first and there is a navigation controller before it .. i want to show the specific view controller depending on the cell selected.. i have set tableView Controller to dynamic and prototype Cell to 1
and i have segue which connected from table to my one of view controller name APP1ViewController i have another two controllers name APP2 and APP3 .. how can i connect them so that on the specific cell specific view controller loads.
here is the code of displaying cells .. at the moment there is one section and three rows in my table
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"AppCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
switch (indexPath.row)
{
case 0:
cell.textLabel.text = #"APP 1 ";
cell.detailTextLabel.text = #"Detail of App 1...";
break;
case 1:
cell.textLabel.text = #"App2";
cell.detailTextLabel.text = #"Detail of App 2 app...";
break;
case 2:
cell.textLabel.text = #"App3";
cell.detailTextLabel.text =
#"Detail of App 3...";
break;
default:
cell.textLabel.text = #"Unkown";
cell.detailTextLabel.text = #"Unknown";
break;
}
return cell;
}

Create your three segues from the controller that has the table rather than from the table or the cell itself. Give each segue a unique identifier. In tableView:didSelectRowAtIndexPath:, call the table view controller's performSegueWithIdentifier:sender: method and select the identifier that matches the chosen row.

Try this,
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"your storyboard" bundle:nil];
UIViewController *viewController = nil;
switch (indexPath.row) {
case 0:
viewController = [storyboard instantiateViewControllerWithIdentifier:#"viewController1"];
break;
case 1:
viewController = [storyboard instantiateViewControllerWithIdentifier:#"viewController2"];
break;
case 2:
viewController = [storyboard instantiateViewControllerWithIdentifier:#"viewController3"];
break;
default:
viewController = [storyboard instantiateViewControllerWithIdentifier:#"viewController4"];
break;
}
[[self navigationController] pushViewController:viewController animated:YES];
}

Implement One of Tablview's delegate method
tableView:didSelectRowAtIndexPath:
and on the above delegate method you can fetch particular view controller form your storyboard and instantiate and push to your navigation's controller as follows
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"your storyboard" bundle:nil];
UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"Your Storyboard's identifier that you want to push"];
[[self navigationController] pushViewController:viewController animated:YES];

Related

Passing data between viewcontroller through property

I have a dictionary on Viewcontroller A .I am passing it on viewcontroller B.On ViewController A it shows data on the dictionary of viewcontroller B.But ,In Viewcontroller it doesnt show any data in it?
ViewController A:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if (cell== nil) {
cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
if(_List.count>0) {
[cell setupCell:[_List objectAtIndex:indexPath.row]];
ViewControllerB *vc=[[ViewController alloc]init];
vc.userIdInfo=[_List objectAtIndex:indexPath.row];
}
return cell;
}
ViewController B:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"_userIdInfo %#",userIdInfo);
if([userIdInfo valueForKey:#"UserID"]) {
[self fetchDataFromServer:getdetail];
}
}
This NSLog(#"_userIdInfo %#",userIdInfo) prints null. while vc.userIdInfo prints dictionary
{
Count = 3;
UserID = "6gdab241-j176-1121-lde2-as8d21f62231";
UserName = "abc#gmail.com";
}
In objective C, cellForRowAtIndexPath methods is used for showing the data.
As per code, you are intiallising the ViewController B in cellForRowAtIndexPath.
it will allocate ViewController B multiple time which lead to memory consumptions.
I would suggest you to initialise in ViewDidLoad of ViewController A.
For Passing the data from A to B, you need to Use didSelectRowAtIndexPath method of UITableViewDelegate.
Example:
ViewController A:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if (cell== nil) {
cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
if(_List.count>0) {
//Use to show data
cell.textLabel.text = [NSString stringWithFormate:#"%#",[_List objectAtIndex:indexPath.row]]];
// [cell setupCell:[_List objectAtIndex:indexPath.row]];
// ViewControllerB *vc=[[ViewController alloc]init];
// vc.userIdInfo=[_List objectAtIndex:indexPath.row];
}
return cell;
}
ViweController B
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 1st Type
ViewControllerB *vc=[[ViewController alloc]init];
vc.userIdInfo=[_List objectAtIndex:indexPath.row];
[self.navigartionController pushViewController:aVC animated:YES];
}
You need to do ViewController B initialization in DID select method like below.
Don't initialize it in cellForRowAtIndexPath.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 1st Type
ViewControllerB *vc=[[ViewController alloc]init];
vc.userIdInfo=[_List objectAtIndex:indexPath.row];
[self.navigartionController pushViewController:aVC animated:YES];
//2nd Type
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewControllerB *aVC = [storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
aVC.userInfo = <set your data>;
[self.navigartionController pushViewController:aVC animated:YES];
}
Hope this will helps.
The code
ViewControllerB *vc=[[ViewController alloc]init];
vc.userIdInfo=[_List objectAtIndex:indexPath.row];
only creates ViewController; it doesn't present it anywhere. moreover, the instance vc will be deallocated right after you leave the scope of
if(_List.count>0){}
your method
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"_userIdInfo %#",userIdInfo);
if([userIdInfo valueForKey:#"UserID"])
{
[self fetchDataFromServer:getdetail];
}
}
will never be called, because your view will never load.
I assume, that what you really want is to present your vc instance with navigationController instance, or from current viewController
[self.navigationController presentViewController: vc animated: YES completion: nil];

Passing to correct view controller on table view datasource selection

I am loading table view cell with two different plist based on selection -
Problem is this. In MoreScreenOptionsData plist all elements are there and in Guest_More plist less items r there. so based on condition i m loading array.
Now when table gets load in both scenario login and logout, when row is selected it always redirect to MoreScreenOptionsData plist row index value. it is not redirecting to Guest_More plist plist array index.
if i load guest screen
Scenario- if user is signed in or not
- (NSArray *)moreScreenElements
{
NSString *plistPath;
if ([VCConfiguration isUserAlreadyLoggedIn])
plistPath = [[NSBundle mainBundle] pathForResource:#"MoreScreenOptionsData" ofType:#"plist"];
else
plistPath = [[NSBundle mainBundle] pathForResource:#"Guest_More" ofType:#"plist"];
moreScreenItems = [[NSArray alloc] initWithContentsOfFile:plistPath];
return moreScreenItems;
}
// Table View Row selection
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
switch (indexPath.row)
{
case RowSelectedMethodMyOrder:
{
VCMyOrderViewController *myOrderVC = [self.storyboard instantiateViewControllerWithIdentifier:#"VCMyOrderViewController"];
[self.navigationController pushViewController:myOrderVC animated:YES];
}
break;
case RowSelectedMethodMyAddresses:
{
VCMyAddressViewController* infoController = [self.storyboard instantiateViewControllerWithIdentifier:#"VCMyAddressViewController"];
[self.navigationController pushViewController:infoController animated:YES];
}
break;
case RowSelectedMethodTrackOrder:
{
VCTrackOrderViewController *myOrderVC = [self.storyboard instantiateViewControllerWithIdentifier:#"VCTrackOrderViewController"];
[self.navigationController pushViewController:myOrderVC animated:YES];
}
break;
case RowSelectedMethodMyWallet:
{
}
break;
case RowSelectedMethodSetting:
{
}
break;
case RowSelectedMethodInviteFriends:
{
}
break;
case RowSelectedMethodRatetheApp:
{
}
break;
case RowSelectedMethodHelp:
{
}
break;
case RowSelectedMethodLogout:
{
[VCConfiguration clearLoggedUserData];
moreScreenItems = [[NSArray alloc] initWithArray:[self moreScreenElements]];
[self.tblMore reloadData];
VCLoginViewController * loginVC = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"VCLoginViewController"];
[loginVC setIsLoginForCart:NO];
UINavigationController * navControllerLogin = [[UINavigationController alloc] initWithRootViewController:loginVC];
[navControllerLogin setNavigationBarHidden:YES];
[self presentViewController:navControllerLogin animated:YES completion:nil];
}
break;
default:
break;
}
}
In didSelectRowAtIndexPath, you need to keep condition based on login or not , like you did in moreScreenElements method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([VCConfiguration isUserAlreadyLoggedIn]) {
//Here you can write code for selecting MoreScreenOptionsData plist table cell
} else {
//Here you can write code for selecting Guest_More plist table cell
}
}
Let me know if you need more assistence
Edit
After a long discussion with #imran, he need to do same actions based on row number and value so I suggested him same index kay and value in his both plists and use the index key to judge your action in cell selection.

Data does not get updated on the table view from one view to the next

What I am trying to do is moving from one table view controller to another. I am sending some data and the data is passed but id does not get updated in the table view. That is, when i click on one of the options in the table view, it shows the same screen again. Here is the code snippet I am using to push the table view:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.
devicedetailTableViewController *detailViewController = [[devicedetailTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
// NSLog(#"%#",detailViewController.details);
[self.navigationController pushViewController:detailViewController animated:YES];
detailViewController.details = self.data[indexPath.row];
}
Please help! Please note: I am not using storyboard here because the previous screen is a login screen ad segues are causing a problem for me there. So I decided to switch to code only. So, I cannot use storyboard.
PS: I know that the data is getting passed because i can see it in my log.
This is how I am loading data:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView registerNib:[UINib nibWithNibName:#"nibname"
bundle:nil]
forCellReuseIdentifier:#"Cell"];
//static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (!cell)
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
switch (indexPath.row) {
case 0:
cell.textLabel.text = [self devices];
cell.detailTextLabel.text = #"Name";
break;
case 1: {
NSString *battlife = [details objectForKey:#"battlife"];
cell.textLabel.text = battlife;
cell.detailTextLabel.text = #"Battery Life";
break;
}
case 2:{
cell.textLabel.text = [details objectForKey:#"location"];
cell.detailTextLabel.text = #"Location";
break;}
default:
break;
}
return cell;
}
you are pushing the view before setting the data,
[self.navigationController pushViewController:detailViewController animated:YES];
detailViewController.details = self.data[indexPath.row];
do first the data set then push
detailViewController.details = self.data[indexPath.row];
[self.navigationController pushViewController:detailViewController animated:YES];
also you might need to do [table reloadData] depending on how u load the data on the second VC

Programmatically Push VC on Table Row Tap

I am attempting to do a onRowTap method without using a storyboard segue to push to a new View Controller, however when tapped it only displays information from the first item of the indexPath no matter which row is tapped. Here is my code:
- (void)tableView:(UITableView *)theTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
NSInteger row = [[self tableView].indexPathForSelectedRow row];
NSDictionary *insta = [self.instaPics objectAtIndex:row];
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"Main"
bundle:nil];
InstaPicDetailViewController* vc = [sb instantiateViewControllerWithIdentifier:#"InstagramDetail"];
vc.detailItem = insta;
[self.navigationController pushViewController:vc animated:YES];
}
Move your deslectRowAtIndexPath message call below the assignment of your row variable:
NSInteger row = [[self tableView].indexPathForSelectedRow row];
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];

how to make pushViewController: work in the following case?

I have a Navigation Controller embedded in a RootViewController. The elements present inside the RootViewController are a segmented control and a UIView. As the different segments are selected, the UIView displays a corresponding ViewController.
Now each of the ViewController being displayed in the UIView is a UITableViewController.
I need to display the table values as per the segment selections. And also if any of the row of the table is selected, it has to move to a newer ViewController with the detailed view.
I am able to display the UITableViewControllers as per the segment change. However, when i click on the row of the table, the newer ViewController that comes up is blank (Black Screen) even though I have created the particular ViewController in the Storyboard and set up an identifier as well.
Code for the Segmented Control change in ViewController.m
- (void)segmentedControlChangedValue:(UISegmentedControl*)segmentedControl {
int selIndex = segmentedControl.selectedIndex;
if (selIndex == 0)
{
aTable = [[aTableViewController alloc] init];
aTable.view.frame = self.myView.bounds;
[self.myView addSubview:aTable.view];
[self addChildViewController:aTable];
}
if (selIndex == 1)
{
bTable = [[bTableViewController alloc] init];
bTable.view.frame = self.myView.bounds;
[self.myView addSubview:bTable.view];
[self addChildViewController:bTable];
}
if (selIndex == 2)
{
//NSLog (#"Well you selected a 3rd option");
}}
Code for the didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
newDetailController* newController = [self.storyboard instantiateViewControllerWithIdentifier:#"Detail"];
newController = [[newDetailController alloc] init];
[[self navigationController] pushViewController:newController animated:YES];}
The pushViewController pushes an empty view for me even though I have specified the ViewController to use in the Storyboard design and also using an identifier.
Please help me in understanding what I must do to rectify this error.
UPDATE - The above problem has been resolved.
The problem I face now is being unable to access the data in the newViewController.
I pass the data to the newViewController as follows:
Create a class named newClass which contains all the elements I want to pass across.
Create a NSMutableArray "newObjects" in the firstViewController.
Create each newClass object at this method.
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *CellIdentifier = #"Cell";
customBigTableCell *cell = (customBigTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[customBigTableCell alloc] init];
}
cell.name.text = [object objectForKey:#"objName"];
newClass* newObj = [[newClass alloc] init];
newObj.objName = cell.name.text;
[newObjects addObject:newObj];
return cell;
}
Pls pardon me .. for the indenting with the code block is messed up...
Also the PFObject is cos i use Parse for database.
Add the created object to the newObjects array.
In the - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath method, this is the code
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:[NSBundle mainBundle]];
newDetailController* newController = [storyboard instantiateViewControllerWithIdentifier:#"UpcomingDetail"];
obj = [[newClass alloc] init];
NSIndexPath* path = [self.tableView indexPathForSelectedRow];
obj = [newObjects objectAtIndex:path.row];
NSLog(#"Row selected is %ld", (long)path.row); //this returns the correct row selected
NSLog(#"Movie selected is %#", [[newObjects objectAtIndex:path.row] objName]);//however this is not the right one as per the cellForRowAtIndexPath method.
[newController setNewObj:obj];
[[self navigationController] pushViewController:newController animated:YES];
}
When I run this code, the row is selected correctly. However I dont get the corresponding row in the database. The array gets stored with redundant data.
You need to get rid of that middle line:
newController = [[newDetailController alloc] init];
That just redefines newController (as an empty controller with no view set up), which you defined in the first line.

Resources