Ipad MasterDetail Template - ipad

I have a question:
I am on a MasterDetail ipad template, Xcode42 in OSX1068 and loading my MasterDetail with a DYNAMIC tableview data source.
The table´s cell is linked by a Push segue to the DetailView, destination = Detail Split.
My problem is that the DetailViewController keeps looping on load a choice. Here is the code:
In MasterViewController:
#pragma mark – Table view delegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.detailViewController.detailItem =[NSString stringWithFormat:#"You choose %#",[_myList objectAtIndex:indexPath.row]];
}
//
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// create an instance of DetailView
DetailViewController *dVC = [[DetailViewController alloc] init];
//sets dVC to the destinationViewController property of the segue
dVC = [segue destinationViewController];
//create the index path object
NSIndexPath * path = [self.tableView indexPathForSelectedRow];
NSString * theItem = [_myList objectAtIndex:path.row];
dVC.rowNumber = path.row;
dVC.itemName = theItem;
}
And on DetailViewController.h:
// tracking the items in the table
#property int rowNumber;
#property (nonatomic,strong) NSString * itemName;
Nothing fancy anywhere else.
Thanks for any help !

Related

selected row in custom cell doesn't pass complete data from segue to another view controller

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
self.data= [self.nameList objectAtIndex:indexPath.row];
self.data= [self.rollList objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"DetailVC" sender:self];
}
I've displayed student's name and roll number in custom cell. Now when i select one row i would like to pass those data to another UIViewController and display in labels. For I've one NSObject type file called 'Name' and i've one variable called 'data' which is of type 'Name'. Now here's my code in didSelectRowAtIndexPath where the nameList is overlapped by rollList which are stored on same variable self.data. if rollList line is removed then it works good. But when I store rollList in self.data it will overlap other.
Where, self.nameList is variable of type NSMutableArray which contains name of student and similarly, self.rollList contains student's roll.
Below is the code to pass data from segue. Here DetailVC is the destinationViewController, vc.data is the variable of type 'Name' and self.data is also the variable of same type.
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"DetailVC"]){
DetailVC *vc = (DetailVC *) segue.destinationViewController;
vc.data = self.data;
}
}
Overlapping is fundamental thing.
In your case your in NSObject type file (Name) you have to add two variable
NSNumber *rollNo;
NSString *name;
After that
-- UPDATE --
#interface TableVC : UIViewController {
Name *data;
}
-(void)viewDidLoad {
data = [[Name alloc] init]
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
self.data.name = [self.nameList objectAtIndex:indexPath.row];
self.data.rollNo = [self.rollList objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"DetailVC" sender:self];
}
Then
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"DetailVC"]){
DetailVC *vc = (DetailVC *) segue.destinationViewController;
vc.data = self.data;
}
}
------ Detail VC ---
#property (nonatomic, strong) Name *data;
-(void)viewDidLoad {
self.labelRollNo.text = self.data.rollNo;
self.labelName.text = self.data.name;
}
try this way
#interface ViewController ()
{
NSString *name;
NSString *roll;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
name= [self.nameList objectAtIndex:indexPath.row];
roll= [self.rollList objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"DetailVC" sender:self];
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"DetailVC"]){
DetailVC *vc = (DetailVC *) segue.destinationViewController;
vc.name = name;
vc.roll = roll;
}
}
you create two NSString name and roll properties in your DetailVC
DetailVC.h
#property (strong, nonatomic) NSString *name;
#property (strong, nonatomic) NSString *roll;

Touch cell and open a new view controller

The following code is in my menuViewController.m. Now I want to go to another view when touch on a specific cell. What should I do to go to contactViewController?(I am using storyboard)
storyboard image:
https://drive.google.com/file/d/0BwOYR2GMJ7l8U1lYYVFVTWVkOG8/edit?usp=sharing
code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
NSString *CellIdentifier = [menuItems objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row==2)
{
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Set the title of navigation bar by using the menu items
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UINavigationController *destViewController = (UINavigationController*)segue.destinationViewController;
destViewController.title = [[menuItems objectAtIndex:indexPath.row] capitalizedString];
if ( [segue isKindOfClass: [SWRevealViewControllerSegue class]] ) {
SWRevealViewControllerSegue *swSegue = (SWRevealViewControllerSegue*) segue;
swSegue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc) {
UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
[navController setViewControllers: #[dvc] animated: NO ];
[self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
};
}
I want to go to another view when touch on a specific cell.
For this, I'd do it this way:
Step 1:
Drag from TableViewController to ContactViewController:
Step 2:
Select segue and specify the Segue Identifier (Show attributes Inspector tab in the right side bar)
I have named the Segue Identifier as SegueTestID
I chose Push as my style but it seems you might need Modal
And the corresponding code (in your MenuViewController.m) should be something like:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 2) {
[self performSegueWithIdentifier:#"SegueTestID" sender:self];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
//following lines needed only if you need to send some detail across to ContactViewController
if ([segue.identifier isEqualToString:#"SegueTestID"]) {
ContactViewController *destinationViewController = segue.destinationViewController;
destinationViewController.strTest = #"Check";
//where strTest is a variable in ContactViewController. i.e:
//"#property (nonatomic, strong) NSString *strTest;"
//declared in `ContactViewController.h`
}
//...
}
PS: It seems you have alot in your -prepareForSegue: already.
Obviously... you'll need to hook things up properly.
In Storyboard , Do this ( In your case its contactviewcontroller ) give the name identifier name to contactViewController whatever you want as shown in image for showRecipeDetail
and you can go to the contactviewcontroller
and then
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipeDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
RecipeDetailViewController *destViewController = segue.destinationViewController;
destViewController.recipe = [recipes objectAtIndex:indexPath.row];
}
}
In above method it shows how to pass the data from current viewcontroller to destviewcontroller
where We simply set the property (i.e. recipeName) in the RecipeDetailViewController to pass the recipe name. Obviously, you can add other properties in the detail view controller to pass other recipe-related values. ( In your case it will be data you want to pass to contactviewcontroller)
When a segue is triggered, before the visual transition occurs, the storyboard runtime invokes prepareForSegue:sender: method of the current view controller. By implementing this method, we can pass any needed data to the view controller that is about to be displayed. Here, we’ll pass the selected recipe object to the detail view controller.

Pass JSON data to another View

I have a TableView that load JSON content from web.
I use AFNetworking and JSONModel. And I use this tutorial do Receive and Parse the Data
Here is the code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"CellIdentifier";
__weak ProgramacaoTableCell *cell = (ProgramacaoTableCell *)[self.tableView dequeueReusableCellWithIdentifier:identifier];
ProgramacaoModel* programacao = _programacao.programacaoArray[indexPath.row];
// NameLabel is the Label in the Cell.
cell.nameLabel.text = [NSString stringWithFormat:#"%#", programacao.atracao ];
return cell;
}
I want to know how pass this data to a Detail ViewController.
In my DetailViewController i have the properties to receive the data.
#property (nonatomic, strong) IBOutlet UILabel *programacaoNomeLabel;
You can access to your controller through your navigation:
NSArray* vcStack=[self appDelegate].myNavigationController.viewControllers;
UIViewController* vcUnder;
if(vcStack.count > 0)
vcUnder=[vcStack objectAtIndex:(vcStack.count-1)];
// -1 depends when you called your controller that's why we test the kind of class
if([vcUnder isKindOfClass:[DetailViewController class]]){
((DetailViewController*) vcUnder). programacaoNomeLabel = #"some data";
}
I find the answer
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Pass the selected object to the new view controller.
if ([[segue identifier] isEqualToString:#"pushDetalhesView"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
// Pega o objeto da linha selecionada
ProgramacaoModel *object = [_programacao.programacaoArray objectAtIndex:indexPath.row];
// Pass the content from object to destinationViewController
[[segue destinationViewController] getProgramacao:object];
}
}
In my Details ViewController I create an iVar
#interface ProgramacaoDetalhesViewController ()
{
ProgramacaoModel *_programacao;
}
And set two method, one to receive the content and another to set the Labels
- (void) getProgramacao:(id)programacaoObject;
{
_programacao = programacaoObject;
}
- (void) setLabels
{
programacaoNomeLabel.text = _programacao.atracao;
}

How to transition from UITableViewCell to another view controller

I am trying to go from a UITableView with prototype cells to a detailviewcontroller of the item I selected on.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"historyToDetail"])
{
BYFHistoryDetailViewController *controller = (BYFHistoryDetailViewController *)segue.destinationViewController;
controller.workOut = [[BYFWorkOut alloc] init];
controller.workOut=_selectRow;
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
BYFHistoryTableViewController *detailViewController =[[BYFHistoryTableViewController alloc] init];
NSArray *items = [[BYFworkOutStore sharedStore] allItems];
BYFWorkOut *selectedItem = items[indexPath.row];
_selectRow = selectedItem;
}
What is not happening is the transition from the table to detail I have a push segue from the prototype cell to the details.
What am I missing?
You are doing quite a lot wrong here. When using segue's you don't create an instance of the class. You simply call:
[self performSegueWithIdentifier:#"MySegue" sender:self];
This will use the segue you have defined in the storyboard. Where MySegue is the segue ID you created.
When you want to pass in data you use the callback
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
BYFHistoryDetailViewController *vc = (BYFHistoryDetailViewController *)[segue destinationViewController];
vc.workOut = selectedItem;
}
But using this callback will mean you will need to store selectedItem somewhere after you click the row so you can access it here.
EDIT
Your code seems a bit odd here also.
You set workout to a new object.
detailViewController.workOut = [[BYFWorkOut alloc]init];
Create another object from data.
NSArray *items = [[BYFworkOutStore sharedStore] allItems];
BYFWorkOut *selectedItem = items[indexPath.row];
And then assign the new object, overwriting the previous one.
//give detail view controller a pointer to the item object in row
detailViewController.workOut = selectedItem;
There is no need to have the first line of code at all
EDIT 2
If you only going to be using the one selected item at a time. you can do this in your UITableViewController class.
#implementation MyTableViewControllerClass
{
BYFWorkOut *_selectedItem;
}
inside didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *items = [[BYFworkOutStore sharedStore] allItems];
_selectedItem = items[indexPath.row];
}
EDIT 3
I've modified the code you posted here. You didn't add the first line of code i posted. Please look at this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"historyToDetail"])
{
BYFHistoryDetailViewController *controller = (BYFHistoryDetailViewController *)segue.destinationViewController;
controller.workOut = _selectRow;
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *items = [[BYFworkOutStore sharedStore] allItems];
_selectRow = items[indexPath.row];
[self performSegueWithIdentifier:#"historyToDetail" sender:self];
}
You need to name your segue and call the method:
[self performSegueWithIdentifier:#"MySegue" sender:self];

Transfering NSString from prototype cell not working with prepareForSegue

I am just trying to transfer a simple string from a UILabel in a prototype cell into a label in the next View Controller. Value of label.text in the viewDidLoad of the View Controller is returning (null).
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
mainCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (mainCell == nil) {
mainCell = [[dictionaryTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString* date = [dateArray objectAtIndex:indexPath.row];
mainCell.viewLabel.text = date;
return mainCell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"View Segue"]) {
NSLog(#"View Load Segue Success");
ViewController *one = segue.destinationViewController;
one.label.text = mainCell.viewLabel.text;
}
}
What am I doing wrong here?
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"View Segue"]) {
NSLog(#"View Load Segue Success");
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ViewController *one = segue.destinationViewController;
one.label.text = [dateArray objectAtIndex:indexPath.row];
}
}
And actually, assigning text to text label you should do in your viewController one's method(viewDidLoad or viewWillAppear). So, you need to make a property in viewController one for transferring NSString.
You can use indexPathForSelectedRow:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"View Segue"]) {
ViewController *one = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
one.textProperty = [dateArray objectAtIndex:indexPath.row];
}
}
Or you can also use sender if your segue is from the cell to the next scene, e.g.:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"View Segue"])
{
ViewController *one = segue.destinationViewController;
NSAssert([sender isKindOfClass:[UITableViewCell class]], #"Not cell");
UITableViewCell *cell = sender;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
one.textProperty = [dateArray objectAtIndex:indexPath.row];
}
}
Two things to note:
As a matter of good programming style, I am not retrieving the text value from the cell. I'm retrieving the text value from the model. You should not be relying upon the view for information to be passed along. Go back to the model, the original source of the information.
Do not set the text property of the label in the destination controller directly. The controls of the destinationController have not been created yet. You should defer setting controls until the destinationController's viewDidLoad. So, instead, create a NSString property in the destination controller:
#property (nonatomic, strong) NSString *textProperty;
Clearly, you should use a more descriptive name than textProperty, but hopefully you get the idea. Anyway, prepareForSegue can set this new property and the viewDidLoad of the destination controller should then use that NSString property to populate the text property of the UILabel, e.g.:
- (void)viewDidLoad
{
[super viewDidLoad];
self.label.text = self.textProperty;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
YourViewController *controller =[[YourViewController alloc] init];
[self presentModalViewController:controller animated:YES];
one.label.text = [dateArray objectAtIndex:indexPath.row];
}
Change the label.text after presentModalViewController. Now what happens?
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion
I understand you are already using Segue. You should follow the other answer.

Resources