To Segue or to didSelectRowAtIndexPath? - ios

Below is the code that I am currently running. I have a storyboard setup with a nav controller and tableview controller and a view controller. I am trying to pass the name from the NSDictionary that I have setup for the Table to the detail view controller. Should I use prepareforsegue or didselectrowatindexpath and how would I get the name out of the dictionary to pass it along?
#import "FMInboxViewController.h"
#import "FMDetailViewController.h"
#interface FMInboxViewController ()
#end
#implementation FMInboxViewController
#synthesize keyArray;
#synthesize tableArray;
#synthesize tblDictionary;
#synthesize filteredArray;
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *ary=[[NSMutableArray alloc]init];
[ary addObject:#"Adam"];
[ary addObject:#"Fred"];
[ary addObject:#"Angel"];
// ... many similar entries
[ary addObject:#"James"];
[ary addObject:#"Mukthesh"];
self.tblDictionary =[self fillingDictionary:ary];
}
Table View Data Source
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [keyArray count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSArray *ary = [self.tblDictionary valueForKey:[keyArray objectAtIndex:section]];
return [ary count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSString *key = [keyArray objectAtIndex:[indexPath section]];
NSArray *array = (NSArray *)[self.tblDictionary valueForKey:key];
NSString *cellTitle = [array objectAtIndex:[indexPath row]];
cell.textLabel.text = cellTitle;
// Configure the cell...
return cell;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *title = [keyArray objectAtIndex:section];
return title;
}
//-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// NSString *key = [keyArray objectAtIndex:[indexPath section]];
// NSArray *array = (NSArray *)[self.tblDictionary valueForKey:key];
// self.selectedName = [array objectAtIndex:indexPath.row];
// NSLog(#"Selected Name in Did select: %#", self.selectedName);
//
// [self performSegueWithIdentifier:#"showDetail" sender:self];
//}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showDetail"]) {
NSIndexPath *section = [self.tableView indexPathForSelectedRow];
NSString *key = [keyArray objectAtIndex:section];
NSArray *array = (NSArray *)[self.tblDictionary valueForKey:key];
NSString *cellTitle = [array objectAtIndex:[indexPath row]];
NSLog(#"Selected Name in Did select: %#", self.selectedName);
}
}
Helper methods
#pragma mark - Helper Methods
- (NSMutableDictionary *)fillingDictionary:(NSMutableArray *)sentArray {
keyArray = [[NSMutableArray alloc] init];
[keyArray removeAllObjects];
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[sentArray sortUsingSelector:#selector(compare:)];
for ( NSString *str in sentArray) {
NSString *charVal = [str substringToIndex:1];
NSString *charStr = [NSString stringWithString:charVal];
NSLog(#" charStr = %#", charStr);
if (![keyArray containsObject:charStr]) {
NSMutableArray *charArray = [[NSMutableArray alloc] init];
[charArray addObject:str];
[keyArray addObject:charStr];
[dic setValue:charArray forKey:charStr];
}
else {
NSMutableArray *prevArray = (NSMutableArray *)[dic valueForKey:charStr];
[prevArray addObject:str];
[dic setValue:prevArray forKeyPath:charStr];
}
}
return dic;
}
#end
OK, I changed that section to look like this
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *key = [keyArray objectAtIndex:[indexPath section]];
NSArray *array = (NSArray *)[self.tblDictionary valueForKey:key];
self.selectedName = [array objectAtIndex:indexPath.row];
NSLog(#"Selected Name in Did select: %#", self.selectedName);
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
FMDetailViewController *dvc = (FMDetailViewController *)segue.destinationViewController;
dvc.name = self.selectedName;
}
However now when I select row the name won't show up in the detail controller on the first press. If you go back and select another name the first name that you pressed then shows up in the view controller. Any suggestions on why this occurs?

You need to use both, in didSelectRowAtIndexPath you should call [self performSegueWithIdentifier:#"identifier" sender:self];
In the same View Controller you should have the prepareForSegue method grab the destinationViewController out of the segue, and then set whatever properties on that view controller that you wish to set.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.someProperty = [self.someArray objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"segueID" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UIViewController *vcToPushTo = segue.destinationViewController;
vcToPushTo.propertyToSet = self.someProperty;
}

If possible (and this is the case in almost all standard scenarios), I would use Interface Builder to trigger the segue. You still need to implement prepareForSegue: to configure the destination view controller.
In order to create a segue in IB which triggers a detail view when tapping on a cell or an accessory button (on the right most side of the cell) perform these steps:
Control drag from Table View Cell to the destination view controller and release the mouse or trackpad. This opens small selection panel.
Choose the source of the trigger, either "Selection segue" or "Accessory action" and the type of the segue ("push", "modal" or "custom").
In the Attributes Inspector pane define the "Identifier" of the segue, e.g. "UserShowSegue".
Here's an image from a Demo storyboard in IB which illustrates how the "Table View Cell" in the "Users" view controller is setup to trigger a "push" segue to a detail view controller:

Might be an old question, but to be more detailed for whom it may concern:
1- Use both as '(#Peter-Foti)' mentioned.
2- Segue should be linked from the ParentVC to the DestinationVC (NOT from the Prototype Cell).
3- Sender should be set properly.
4- set your '#property (someProperty)'.
SAMPLE CODE:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.someProperty = [self.someArray objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"segueID" sender:self.someProperty];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UIViewController *vcToPushTo = segue.destinationViewController;
vcToPushTo.propertyToSet = sender;
}

Because didSelectRowAtIndexPath can be replaced with storyboard visual programming, I recommend to do all the logic in the prepareForSegue like this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let cell = sender as! UITableViewCell
let indexPath = tableView.indexPath(for: cell)!
... and then use indexPath to set up the destination
}

Related

tableviewcontroller not working when called from other viewcontroller

I have two tableViewControllers created in storyboard:
categories and stores.
When I select a category, it's supposed to show all stores that are in that category.
(I'm getting stores data from server, but I set a fixed category in the url so it should fetch the same two stores no matter what.)
The weird thing is that when I choose a category, storesController shows up empty,
but if I set it as initial controller, it works.
StoreTableViewController_as_initial.png
StoreTableViewController_from_categories.png
this is how I setup the cells in storeController.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
StoresCell *cell = [tableView dequeueReusableCellWithIdentifier:#"storetile"];
if(cell == nil){
cell = [[StoresCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"storetile"];
}
cell.storelabel.text = [[_results objectAtIndex:[indexPath row]]objectForKey:#"name"];
[cell.storelabel sizeToFit];
cell.subtitleOneLabel.text=[[_results objectAtIndex:[indexPath row]]objectForKey:#"neighborhood"];
cell.subtitleTwoLabel.text = [[_results objectAtIndex:[indexPath row]]objectForKey:#"city"];
NSString *distance = [NSString stringWithFormat:#"~%# km",[[_results objectAtIndex:[indexPath row]]objectForKey:#"distance"]];
cell.distanceLabel.text = distance;
NSString *imgPath = [[_results objectAtIndex:[indexPath row]]objectForKey:#"imgUrl"];
UIImage *thumb = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://andrafterdevelopment.com.br/apps/buscaabc/img/%#",imgPath]]]];
[cell.thumbImage setImage:thumb];
return cell;
}
I break at the return, the method is always called but when it's from categoriesController all labels in my cell are nil.
this is how I call storeController from categoriesController
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath{
NSDictionary *item = [_results objectAtIndex:[indexPath row]];
BOOL hasSub = [[item objectForKey:#"hasSub"] boolValue];
StoreTableViewController *storesTableViewController = [[StoreTableViewController alloc]init];
//storesTableViewController.title = [item valueForKey:#"name"];
//storesTableViewController.category = (int)[item valueForKey:#"id"];
[storesTableViewController.tableView registerClass:[StoresCell class] forCellReuseIdentifier:#"storetile"];
[self.navigationController pushViewController:storesTableViewController animated:YES];
}
I'm guessing this has to do with custom cell or maybe I'm doing it wrong by calling it this way.
If you use Storyboard, you should create your controller via Storyboard.
Set Storyboard ID in Identity inspector for your StoreTableViewController and change your method on:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath{
NSDictionary *item = [_results objectAtIndex:[indexPath row]];
BOOL hasSub = [[item objectForKey:#"hasSub"] boolValue];
StoreTableViewController *storesTableViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"storyboard id"];
storesTableViewController.title = [item valueForKey:#"name"];
storesTableViewController.category = (int)[item valueForKey:#"id"];
[self.navigationController pushViewController:storesTableViewController animated:YES];
}
Or you can use segues and configure your StoreTableViewController in prepareForSegue method:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"StoreTableViewControllerSegureIdentifier"]) {
StoreTableViewController *storesTableViewController = segue.destinationViewController;
storesTableViewController.title = _selectedItem.title;
storesTableViewController.category = _selectedItem.identifier;
}
}
I am guessing you have declared _results as a property in StoreTableViewController right?
If so, change your categoriesController method to:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath{
NSDictionary *item = [_results objectAtIndex:[indexPath row]];
BOOL hasSub = [[item objectForKey:#"hasSub"] boolValue];
StoreTableViewController *storesTableViewController = [[StoreTableViewController alloc]init];
storesTableViewController.title = [item valueForKey:#"name"];
storesTableViewController.category = (int)[item valueForKey:#"id"];
[self.navigationController pushViewController:storesTableViewController animated:YES];
}
And register cell in viewDidLoad.
Their are few things that i think you should check in your code.
When you are opening second view controller for selected category, did your service giving you data?
If you are getting data, then is it getting filled in array in right way?
And if everything above is fine, then had you called [tableView reloadData] method after filling data in array.

TableViewCell title and subtitle to detail view controller (segue help)

i got a problem with my tableview segue and the detail view controller. i managed to populate my table view with titles and subtitles with nsdictionary. however i could not push my title and subtitle to the detail view. i need my title to go on the navigation bar and the subtitle to a label in the detail view. here is the code and the screenshots of my table view and the detail view:
#import "TableViewController.h"
#import "DetailViewController.h"
#interface TableViewController (){
NSDictionary *sarkilar;
NSArray *sarkilarSectionTitles;
NSArray *sarkilarIndexTitles;
}
#end
#implementation TableViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *newButton = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStylePlain target:nil action:nil];
[[self navigationItem] setBackBarButtonItem:newButton];
sarkilar = #{
#"A" : #[#{#"title":#"Alayına İsyan",#"subtitle":#"Seslendiren: Mustafa Sandal"},
#{#"title":#"Ardindan",#"subtitle":#"Seslendiren: Sinasi Gurel"}],
#"B" : #[#{#"title":#"Birak Gitsin",#"subtitle":#"Seslendiren: Tarkan"},
#{#"title":#"Buralar",#"subtitle":#"Seslendiren: Duman"}],
#"C" : #[#{#"title":#"Cephaneler",#"subtitle":#"Seslendiren: Burak Kut"},
#{#"title":#"Cari Acik",#"subtitle":#"Seslendiren: Kristal"}],
};
sarkilarSectionTitles = [[sarkilar allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
sarkilarIndexTitles = #[#"A", #"B", #"C",#"Ç", #"D", #"E", #"F", #"G", #"H", #"I",#"İ", #"J", #"K", #"L", #"M", #"N", #"O", #"Ö", #"P", #"R", #"S",#"Ş", #"T", #"U",#"Ü", #"V", #"Y", #"Z"];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [sarkilarSectionTitles count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSString *sectionTitle = [sarkilarSectionTitles objectAtIndex:section];
NSArray *sectionSarkilar = [sarkilar objectForKey:sectionTitle];
return [sectionSarkilar count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [sarkilarSectionTitles objectAtIndex:section];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSString *sectionTitle = [sarkilarSectionTitles objectAtIndex:indexPath.section];
NSArray *sectionSarkilar = [sarkilar objectForKey:sectionTitle];
NSDictionary *dict = [sectionSarkilar objectAtIndex:indexPath.row];
NSString *title = [dict objectForKey:#"title"];
NSString *subtitle = [dict objectForKey:#"subtitle"];
cell.textLabel.text = title;
cell.detailTextLabel.text = subtitle;
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
// return animalSectionTitles;
return sarkilarIndexTitles;
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return [sarkilarSectionTitles indexOfObject:title];
}
//-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
//
// if ([[segue identifier] isEqualToString:#"ShowDetails"]) {
// DetailViewController *detailView = [segue destinationViewController];
//
// NSIndexPath *myindexpath = [self.tableView indexPathForSelectedRow];
//
// int row = [myindexpath row];
// detailView.DetailModal = #[_title[row], subtitle[row],];
// }
//
//
//
//}
//
#end
as you can see i couldn't figure out how to set my segue up. and here are the screenshots. i hope it is not too much to ask how to set up the segue
You can get the currently selected cell and pass the values in the prepareForSegue: method.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
UIViewController *destinationViewController = segue.destinationViewController;
UITableViewCell *selectedCell = [self.tableView cellForRowAtIndexPath:self.tableView.indexPathForSelectedRow];
destinationViewController.title = selectedCell.textLabel.text;
//Add code to set label to selectedCell.detailTextLabel.text
}
To be clear, you will need to implement the delegate method for when a cell is selected, then call your segue. (Assuming this is the way your app will operate)
//TableViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"ShowDetails" sender:self];
}
Then before the transition the method prepareForSegue will be called, where you can set up any properties on your DetailViewController.
//TableViewController.m
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"ShowDetails"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
DetailViewController *detailVC = segue.destinationViewController;
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
detailVC.myTitle = cell.textLabel.text;
detailVC.mySubtitle = cell.detailTextLabel.text;
}
}
Add these properties to your DetailViewController header file to pass the references to your title and subtitle.
//DetailViewController.h
#property (nonatomic, strong) NSString *myTitle;
#property (nonatomic, strong) NSString *mySubtitle;
Then in the viewDidLoad method of your DetailViewController set the navigation title and label properties
//DetailViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = self.myTitle;
self.myLabelName.text = self.mySubtitle;
}

pass value in splitview detailview

I have a splitview app, a table with customers to the left and their info on the right so i have to pass witch customer that is clicked and i can't use the name in case of two have the same so im trying to pass over the customer id in the tag property of the cell but i dont get it to work.
Here is where i set the value, i can see it's working when debugging
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
Customer names
NSDate *object = _objects[indexPath.row];
//Customer number
NSString *nr = _kundnr[indexPath.row];
//Customer name
cell.textLabel.text = [object description];
//Customer number
NSInteger Ftgnr = [nr intValue];
//Setting the customer number to cell tag
cell.tag = Ftgnr;
return cell;
}
Here i pick up the cell.tag it's the detailview viewdidload, i tried many different ways to save the id to a variable but the app crashes and i don't know if the value gets passed.
It's working to pick up the description (customer name) but i want the id.
- (void)configureView
{
// Update the user interface for the detail item.
if (self.detailItem) {
// NSString *strCellTag = [NSString stringWithFormat:#"%d", [self.detailItem tag]];
//here im trying to pick up the tag value this is where the app craches
NSInteger Ftgnr = [self.detailItem tag];
// NSString *stringformat = [NSString stringWithFormat:#"%d", Ftgnr];
//Its working to pick up the text from the cell
self.detailDescriptionLabel.text = [self.detailItem description];
}
Thank you for your help!
Add a property to your detail view controller so you can set the id when you set the detail item. Then:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.detailViewController.detailIdentity = _kundnr[indexPath.row];
self.detailViewController.detailItem = _objects[indexPath.row];
}
And then use self.detailIdentity instead of [self.detailItem tag]. And, it's already a string so you don't need to convert to integer and back.
You should probably also:
Rename detailItem to be more specific, like detailDate
Think about creating a custom class to hold the full detailItem (so it contains the identity and the date)
My final code
Masterviewcontroller
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSDate *object = _objects[indexPath.row];
cell.textLabel.text = [object description];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDate *object = _objects[indexPath.row];
NSDate *kundnr = _kundnr[indexPath.row];
self.detailViewController.detailItem = object;
self.detailViewController.detailIdentity = kundnr;
}
Detailviewcontroller
- (void)setDetailItem:(id)newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
if (self.masterPopoverController != nil) {
[self.masterPopoverController dismissPopoverAnimated:YES];
}
}
- (void)setDetailIdentity:(id)newDetailItentity
{
if (_detailIdentity != newDetailItentity) {
_detailIdentity = newDetailItentity;
// Update the view.
[self configureView];
}
if (self.masterPopoverController != nil) {
[self.masterPopoverController dismissPopoverAnimated:YES];
}
}
- (void)configureView
{
// Update the user interface for the detail item.
if (self.detailItem) {
// NSString *stringformat = [NSString stringWithFormat:#"%d", Ftgnr];
self.detailDescriptionLabel.text = [self.detailItem description];
}
if (self.detailIdentity) {
NSString *kundnr = [self.detailIdentity description];
}
}

Adding additional data to inner array with sorted outer array

I have a plist with contacts: the root is an array, items 0-150 are dictionaries, each dictionary is a single contact with a "name", "number", and "email" string.
The code below sorts the contacts alphabetically into sections based upon the "name" string. Then uses the inner array to populate the cells for each section. I then pass the name from the inner array to my detail view.
However, I can not figure out how to pass the correct number and email for each contact into the detail view. I've been working on this issue for a long while and can not find a solution.
#interface ContactsViewController ()
-(void)configureSectionData;
#end
#implementation ContactsViewController
#synthesize tableData;
#synthesize collation;
#synthesize outerArray;
#synthesize indexTitlesArray, namesDictionary;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - Table view methods
-(void)configureSectionData {
NSUInteger sectionTitlesCount = [collation.sectionTitles count];
self.outerArray = [NSMutableArray arrayWithCapacity:sectionTitlesCount];
for (NSUInteger index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *array = [NSMutableArray array];
[self.outerArray addObject:array];
}
for (NSString *nameString in tableData)
{
NSInteger sectionNumber = [collation sectionForObject:nameString collationStringSelector:#selector(lowercaseString)];
NSMutableArray *sectionNames = [outerArray objectAtIndex:sectionNumber];
[sectionNames addObject:nameString];
}
for (NSUInteger index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *namesForSection = [outerArray objectAtIndex:index];
NSArray *sortedNamesForSection = [collation sortedArrayFromArray:namesForSection collationStringSelector:#selector(lowercaseString)];
[self.outerArray replaceObjectAtIndex:index withObject:sortedNamesForSection];
}
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.collation.sectionTitles count];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *theLetter = [self.collation.sectionTitles objectAtIndex:section];
if (![theLetter isEqualToString:#"#"]) {
NSString *titleString = [NSString stringWithFormat:#"%#", theLetter];
return titleString;
}
return nil;
}
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.collation.sectionTitles;
}
-(NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return [self.collation sectionForSectionIndexTitleAtIndex:index];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray *innerArray = [self.outerArray objectAtIndex:section];
return [innerArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
// Get the inner array for this section
NSArray *innerArray = [self.outerArray objectAtIndex:indexPath.section];
// Get the name from the inner array
NSString *theName = [innerArray objectAtIndex:indexPath.row];
cell.textLabel.text = theName;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainiPhoneStoryboard" bundle:nil];
DetailViewController *detailView = (DetailViewController *)[storyboard instantiateViewControllerWithIdentifier:#"DetailViewController"];
// Get the inner array for this section
NSArray *innerArray = [self.outerArray objectAtIndex:indexPath.section];
// Get the name from the inner array
NSString *tmpname = [innerArray objectAtIndex:indexPath.row];
detailView.lblname = tmpname;
[self presentViewController:detailView animated:YES completion:nil];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.namesDictionary = [NSMutableArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"contacts" ofType:#"plist"]];
self.tableData = [namesDictionary valueForKey:#"name"];
self.collation = [UILocalizedIndexedCollation currentCollation];
[self configureSectionData];
}
Since you're populating your table from an array of just the names from your plist, you'll have to search that array using the name to find the dictionary that it belongs to, so you can pass that to the detail view controller (you would need to create a property in your detail view controller, passedInDictionary in my example):
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainiPhoneStoryboard" bundle:nil];
DetailViewController *detailView = (DetailViewController *)[storyboard instantiateViewControllerWithIdentifier:#"DetailViewController"];
// Get the inner array for this section
NSArray *innerArray = [self.outerArray objectAtIndex:indexPath.section];
// Get the name from the inner array
NSString *tmpname = [innerArray objectAtIndex:indexPath.row];
NSInteger indx = [self.namesDictionary indexOfObjectPassingTest:^BOOL(NSDictionary *dict, NSUInteger idx, BOOL *stop) {
return [dict[#"name"] isEqualToString:tmpname];
}];
NSDictionary *dict = self.namesDictionary[indx];
detailView.passedInDictionary = dict;
[self presentViewController:detailView animated:YES completion:nil];
}

UITableView to UICollectionView with prepareForSegue not getting called

I'm still kinda new to this; so be gentle.
I want to download a setlist from flickr then select the following set and view its pictures.
Sp far I've contracted a way to get setlist. Now I want to be able to click one of the set lists and move to UICollectionsView and view its images. I need help with being able to select the row in the UITableView.
I think I'm missing a step somewhere but can't seem to find the hole I'm missing.
Anyway here's the code
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.rowHeight = 44;
photoURLs = [[NSMutableArray alloc] init];
photoSetNames = [[NSMutableArray alloc] init];
photoids = [[NSMutableArray alloc] init];
[self loadFlickrPhotos];
}
- (void)loadFlickrPhotos
{
// 1. Build your Flickr API request w/Flickr API key in FlickrAPIKey.h
NSString *urlString = [NSString stringWithFormat:#"http://api.flickr.com/services/rest/?method=flickr.photosets.getList&api_key=%#&user_id=%#&per_page=10&format=json&nojsoncallback=1", FlickrAPIKey, #"62975213#N05"];
NSURL *url = [NSURL URLWithString:urlString];
// 2. Get URLResponse string & parse JSON to Foundation objects.
NSString *jsonString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
// NSDictionary *results = [jsonString JSONValue];
NSDictionary *results = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
// 3. Pick thru results and build our arrays
NSArray *photosets = [[results objectForKey:#"photosets"] objectForKey:#"photoset"];
for (NSDictionary *photoset in photosets) {
// 3.a Get title for e/ photo
NSString *title = [[photoset objectForKey:#"title"] objectForKey:#"_content"];
[photoSetNames addObject:(title.length > 0 ? title : #"Untitled")];
NSString *photoid = [photoset objectForKey:#"id"];
[photoids addObject:photoid];
}
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"viewGallery"]){
flickrGalleryViewController *controller = (flickrGalleryViewController *)segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
controller.photoids = [photoids objectAtIndex:indexPath.row];
NSLog(#"photoid = %#", controller.photoids);
}
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [photoSetNames count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell Identifier"];
cell.textLabel.text = [photoSetNames objectAtIndex:indexPath.row];
return cell;
}
If you want to push/present new view after you press row in table view you need to implement tableView:didSelectRowAtIndexPath: method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Present new view here
}
didSelectRowAtIndexPath: method is called by table view every time you press the row.
You can use it to handle the row press event or you can do it via storyboard. In storyboard you can control drag from table view row to other view controller to set up segue, in that scenario you don't even need to use didSelectRowAtIndexPath: method, prepareForSegue: is enough if you need to pass some data between view controllers. The other way is control drag from table view controller (not row) to another view controller. In that case you need to call this segue in some way. I believe you set up your segue in the second way.
To call it when you press the row add this line to didSelectRowAtIndexPath: method, replace comment from code above with:
[self performSegueWithIdentifier:#"YOURSEGUENAMEFORMSTORYBOARD" sender:nil]
//EXTENDED
If you want to pass a data to the other view you can use the second parameter - sender. You can pass require object or any other object there, for example:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//I pass NSIndexPath to prepare for segue
[self performSegueWithIdentifier:#"YOURSEGUENAMEFORMSTORYBOARD" sender: indexPath]
}
And in prepareForSeque: method you can retrieve this object and use it:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"viewGallery"]){
flickrGalleryViewController *controller = (flickrGalleryViewController *)segue.destinationViewController;
// HERE I retrieve index path from parameter
NSIndexPath *indexPath = (NSIndexPath*)sender;
controller.photoids = [photoids objectAtIndex:indexPath.row];
NSLog(#"photoid = %#", controller.photoids);
}
}
This is an example you can ament to your needed.

Resources