Master-Detail using Parse - ios

Then I have my MasterViewController with its DetailViewController segued both.
I'm using Parse for backend platform, and I have a little problem for this: How to pass displaying datas of the MasterViewController to the DetailViewController
I'm using a NSArray called "RetrievingObjects" to retrieve it, For my Parse class querying it works successfully (I already used my query and my Array to display cells in MasterViewController), I use that method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailViewController *detailVc = [self.storyboard instantiateViewControllerWithIdentifier:#"detailVC"];
detailVC.lblDescription = [self.RetrievingObjects objectAtIndex:indexPath.row];
detailVC.lblTitleForDescr.text = [self.RetrievingObjects objectAtIndex:indexPath.row];
detailVC.dateForDescr.text = [self.RetrievingObjects objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"goToDetailSg" sender:self];
}

It looks like you're not actually using detailVc anywhere. You should set it up in MasterViewController's prepareForSegue:sender: You can access what will become the DetailViewController through the segue object's destinationViewController property and set everything you need there.

Don't create the detail controller in code. If you have your segue set up correctly in the storyboard, that work will be done for you.
Instead, implement - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender, get the detail controller from the segue parameter, and pass the information you want it to display in that method.
Note that the destination controller's view will not have loaded at that point, so don't try to update IBOutlets.

Related

UIViewController appears as Black screen when doing programmatically

UIViewController appears as black screen when handling programmtically
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *user = (NSString *) [self.friends objectAtIndex:indexPath.row];
ChatViewController *chatController = [[ChatViewController alloc] initWithUser:user];
[self presentModalViewController:chatController animated:YES];
}
This below given code is in the chatviewcontroller
- (id) initWithUser:(NSString *) userName {
if (self = [super init]) {
chatWithUser = userName;
}
return self;
}
and when i do it using storyboard segue then only tableview row gets selected but doesn't shows ChatViewController
else if ([segue.identifier isEqualToString:#"showChatView"]) {
ChatViewController *viewController = (ChatViewController *)segue.destinationViewController;
viewController.chatWithUser = friends;
}
If anyone can figure out what i m doing wrong. Will appreciate so much.
Thanks for help though.
presentModalViewController:animated: is deprecated (since iOS 6), you should use presentViewController:animated:completion:
However, it looks like you are using a segue to get to your ChatViewController, so you shouldn't even have to present the view controller since this is handled by Interface Builder. If your segue is set up correctly, replace presentModalViewController:animated: with [self performSegueWithIdentifier:#"showChatView" sender:nil];
EDIT
You should just move your ChatViewController setup to the prepareForSegue:sender: method, like so:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *user = (NSString *)[self.friends objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"showChatView" sender:user];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showChatView"]) {
NSString *user = (NSString *)sender;
ChatViewController *chatVC = (ChatViewController *)[segue destinationViewController];
// No need to have an init method with the user property since Interface Builder does that for you.
chatVC.chatWithUser = user; // Expose this property in ChatViewController's header file if it's not already
}
That should be all you need to do in your code.
Presenting Versus Showing a View Controller
The UIViewController class offers two ways to display a view controller:
The showViewController:sender: and showDetailViewController:sender: methods offer the most adaptive and flexible way to display view controllers. These methods let the presenting view controller decide how best to handle the presentation. For example, a container view controller might incorporate the view controller as a child instead of presenting it modally. The default behavior presents the view controller modally.
The presentViewController:animated:completion: method always displays the view controller modally. The view controller that calls this method might not ultimately handle the presentation but the presentation is always modal. This method adapts the presentation style for horizontally compact environments.
The showViewController:sender: and showDetailViewController:sender: methods are the preferred way to initiate presentations. A view controller can call them without knowing anything about the rest of the view controller hierarchy or the current view controller’s position in that hierarchy. These methods also make it easier to reuse view controllers in different parts of your app without writing conditional code paths.
Refer this link to know about what is the difference between segue programmatically and using interface builder. I hope it is helpful.
#timgcarlson's answer is great for solving your problem.
As per #Sneha's suggestion I have added a paragraph that feel is useful.

Storyboard Segue with popup button and detailview

I am creating a news app that has title, description, video and details.
this is displayed on UIViewCell on TableView, when a user clicks on that
particular cell, corresponding news is displayed as shown below
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NewsViewController *newsdetail = [[NewsViewController alloc] initWithNibName:#"NewsDetailView" bundle:nil];
self.newsdetails = detail;
[detail release];
newsdetails.title = [NSString stringWithFormat:#"%#",[titleData objectAtIndex:indexPath.row]];
newsdetails.itemID = [NSString stringWithFormat:#"%#",[NewsIds objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:newsdetails animated:YES];
}
The variables (which hold JSON data) are properly defined in NewsViewController and synthesised as follows
NSMutableArray *NewsIds;
NSMutableArray *titleData;
NSMutableArray *descriptionData; etc
Now, what I want is to add a video button as shown on the storyboard, so that a user can click it and be able to see details of corresponding video through modal /popup
any suggestions or help?
In the Storyboard, just use an Action segue on the UIButton and select modal. Control Drag from the button to the Video Details VC. Give that segue a name, let's say
playVideo
Then inside the prepareForSegue method in your PlayersViewController.m you just add this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"playVideo"]) {
// set properties on your destinationVieController to pass the data you need
}
}
Also use unwind segues on the buttons 'Cancel' and 'Done' in your destination VC to return to the previous TVC. Alternatively you could also use dismissViewControllerAnimated: that will be passed to the calling VC.
you should have a custom table view cell which will be handling actions and data on cell.

In prepareforsegue how datas are passed by using arguments

In storyboard I want to pass the datas from one viewcontroller to another but only the properties are shared but how can i share the datas by using the arguments(method).In below I have tried like this
Tableview didselect Method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self performSegueWithIdentifier:#"ASEventDetail" sender:self];
}
In prepare for segue I pass the argument value in method "[vc loadDict:[eventArr objectAtIndex:0]]"
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"ASEventDetail"]){
// Get reference to the destination view controller
ASEventDetail *vc = [segue destinationViewController];
// Pass any objects to the view controller here, like...
[vc loadDict:[eventArr objectAtIndex:self.view.tag]];
}
}
Could you please any one help me to pass the datas from one to another using methods from storyboard.
You can pass data in via properties or methods (as long as that method is storing the data). However, you shouldn't be updating the UI in your loadDict method.
Instead, save your data in a property or instance variable, then in viewWillAppear on the destination controller, update the UI based on the data.
Set your custom properties on the destination view controller,Use this method to pass the property in all of your view controllers
ASEventDetail *vc = [segue destinationViewController];
vc.someobject=[eventArr objectAtIndex:self.view.tag];
for reference you can refer Pass Data Between View Controllers

tableview to detailviewcontroller storyboard issue

Here's my problem. I have data being passed into the 'second view controller' by mySQL which currently works great. But when I select on any of the from (UITableView) cells, I am currently not able to open a new view to show the data.
I believe the code issue is with
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
detailedViewController *productinfo = [self.storyboard instantiateViewControllerWithIdentifier:#"productDetails"];
//Retrieve current user array
foodProducts *currentProduct = [bakeryProductArray objectAtIndex:indexPath.row];
productinfo.productName = currentProduct.productName;
productinfo.productImage = currentProduct.productImgUrl;
productinfo.productDescription = currentProduct.productDescription;
[self.navigationController pushViewController:productinfo animated:YES];
}
There have been others who have over came this using nibs but not storyboard.
Can someone point out where I have gone wrong or something I have fundamentally missed?
(I have another project which fully working with navigation controller only. Though this is the 1st project which I have tried to use with the tab bar navigation).
The best way to handle this with a storyboard is to create a segue to the detail view from your mainViewController. This can be from your actual cell or from the controller. In your prepare for segue method, pass the object to the detail view. This uses a fetchedResultsController but the idea is the same. Get the selected cell and pass the object to the detail view.
Here is a sample of how you could pass it while using a segue from the cell itself. Create a segue from the tableViewCell in IB for "selection". Drag that segue to your detailViewController and set the identifier to ShowDetailView then add the following prepareForSegue method.
Make sure to have a property (foodProduct) on your detailViewController that will hold the reference to your selected object. That's what you will pass from your mainViewController.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ShowDetailView"])
{
DetailViewController *detailViewController = [segue destinationViewController];
foodProducts *currentProduct = [bakeryProductArray objectAtIndex:[self.tableView indexPathForSelectedRow]];
detailViewController.foodProduct = currentProduct;
}
}
try this .....
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Decriptionview *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"Decription"];//#"Decription" is Storybord Id of UiViewController of Decriptionview
detail.wndecDecription=[SortedDecription1 objectAtIndex:indexPath.row];
detail.wndectitle=[SorttedTitle1 objectAtIndex:indexPath.row];
detail.wndeclink=[SortedLink1 objectAtIndex:indexPath.row];
detail.wndecdate=[SorttedDate1 objectAtIndex:indexPath.row];
detail.imgeurl=[sorttedMainImage1 objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detail animated:YES];
}

UITableView Passing Data Between Controllers Embedded Inside Containers

I have a simple test project. A UITableViewController (MasterViewController) embedded inside a navigation controller in storyboard. I am NOT segueing using the prepareForSegue to pass data to another view controller (DetailViewController). Instead, didSelectRowAtIndexPath is use to update a label in the detailviewcontroller as below:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *detailViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"DetailViewController"];
NSMutableString *object = thisArray[indexPath.row];
detailViewController.passedData = object;
[self.navigationController pushViewController:detailViewController animated:YES];
}
Everything till this point works fine.
Now i have added another view controller in my storyboard. Made it the initial view controller, added two containers in it, then embedded both MasterViewController and DetailViewContainer in these containers.
Now instead of showing passed data inside the DetailViewController on the right side, its showing the passed data on the left side by replacing the controller view.
If i am not able to clarify what i am trying to say, here is the link to the project https://jumpshare.com/v/UiTFEB6AamIo8qX9sinW , its just for learning purpose.
Thanks
You're getting this problem because you are still doing this:
[self.navigationController pushViewController:detailViewController animated:YES];
The navigation controller you're referencing here is the one your master controller is embedded in, so you create an instance (different than the one that's already on screen) of detailController and push that onto the navigation controller.
What you want to do, is get a reference to the detail controller that's already on screen -- both child view controllers (the ones in the container views) are already instantiated when the app starts. So, you need to do this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailViewController *detailViewController = [self.navigationController.parentViewController childViewControllers][1];
NSMutableString *object = thisArray[indexPath.row];
detailViewController.passedData = object;
}
This will pass the value to the detail controller, but you can't have the code to update the label in viewDidLoad, since that view is already loaded, and won't be called again. Instead, override the setter for passedData, and update the label there (note that I changed the name of the argument to passedInData, so it doesn't conflict with your property passedData):
-(void)setPassedData:(NSString *)passedInData {
passedData = passedInData;
detailDescriptionLabel.text = passedData;
}
Bu the way, unless you're planning on adding other controllers after your master view controller, there's no reason to have it embedded in a navigation controller at all, given this set up. If you take it out, then you need to remove the reference to self.navigationController when you get the reference to the detail controller. It would then just be:
DetailViewController *detailViewController = [self.parentViewController childViewControllers][1];

Resources