UITableView to UICollectionView with prepareForSegue not getting called - ios

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.

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.

How can I select the one of row from table view in iOS?

I have local JSON and have display on the first page.
After that I want to select one of the row from tableview. When I select the row, it will be display the other JSON from url, different rows have different json. However, I don't know how to find out the one of row. I try many ways but it can't work.
Here is the code of the first page:
#implementation HKTableViewController{
NSArray *_location_array,*_hki;
}
- (void)viewDidLoad {
[super viewDidLoad];
JSONLoader *location_jsonLoader = [[JSONLoader alloc] init];
NSURL *url = [[NSBundle mainBundle] URLForResource:#"locations" withExtension:#"json"];
//NSURL *url = [NSURL URLWithString:#"http://127.0.0.1/funhiking/index.php/index/getHKIsland"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
_location_array = [location_jsonLoader locationsFromJSONFile:url];
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
});
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
DistrictTableViewController *district = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
district.location = [_location_array objectAtIndex:indexPath.row];
if (indexPath.row == 0) {
// Create a new JSONLoader with a local file URL
JSONLoader *jsonLoader = [[JSONLoader alloc] init];
//go to web to take json file
NSURL *url = [NSURL URLWithString:#"http://127.0.0.1/funhiking/index.php/index/getHKIsland"];
// Load the data on a background queue...
// As we are using a local file it's not really necessary, but if we were connecting to an online URL then we'd need it
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
_hki = [jsonLoader hkiFromJSONFile:url];
// Now that we have the data, reload the table data on the main UI thread
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
});
}
}
#pragma mark - Table View Controller Methods
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"HKCell"];
Locations *location = [_location_array objectAtIndex:indexPath.row];
cell.textLabel.text = location.title;
NSLog(#"%#", location.title);
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_location_array count];
}
You can use didselectrowatindex delegate method of table view after setting delegate of table view, then you can get object from your array in this method and and can simply show the JSON url.
Happy coding...

How can I display multiple parameters of the same key from a .plist File on Objective-c?

I have this arquivo.plist below.
I looked at Apple's documentation, but I could not find how to make the listing look and I hope someone can help me.
In the first UITableView, I make a list of names present in arquivo.plist using the following code and loading the following method below.
What I'm trying to do is: When the user clicks on a tableView name, he is taken to a second screen with a new tableView that will display the "frams" of that user.
The problem is that the code I'm using to select the "frams" is the same code that I am using for listing the names on the first screen, but it is not working, because each user has only one name, but it has several "frams".
When I try to implement this, I can even assemble the array with the "frams" and pass using segue (i'll show the array with an NSLog), but this array can not be displayed as a tableView for an error that Xcode is giving me:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary length]:
unrecognized selector sent to instance 0x8b87a60'
The code from the fist view (ViewController.m) is below the contatos.plist
I hope you understand what I'm trying to do and bring me a light!
Thank you all!
a screenshot of the .plist file is bellow:
http://img268.imageshack.us/img268/7356/jl26.png
For reference and for you to better understand the issue, when the user clicks on a table name, an array is generated with "frams" this patient (patients have on average 3 frams each). The Array NSLog that it should be passed to the other page and comport a new table generates the following text:
12/12/2013 16:10:13.513 rer [24251:70 b] (
{
1 = 11;
2 = 12;
3 = 13;
}
I think that's where the problem lies, because this method of Array can not be implemented in a TableView, so I look a light of a better way to mount this array and select frams when I click a patient
So here is my ViewController.m:
#import "ViewController.h"
#import "Contato.h"
#import "perfilViewController.h"
#interface ViewController ()
-(void) loadContacts;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self loadContacts];
}
-(void) loadContacts
{
NSString *plistCaminho = [[NSBundle mainBundle] pathForResource:#"contatos"
ofType:#"plist"];
NSDictionary *pl = [NSDictionary dictionaryWithContentsOfFile:plistCaminho];
NSArray *dados = [pl valueForKey:#"contatos"];
contatos = [[NSMutableArray alloc] init];
for (NSDictionary *item in dados) {
NSString *nome = [item valueForKey:#"nome"];
NSString *telefone = [item valueForKey:#"telefone"];
NSString *fram = [item valueForKey:#"fram"];
Contato *c = [[Contato alloc] initWithNome:nome andTelefone:telefone andFram:fram];
[contatos addObject:c];
}
}
#pragma mark UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return contatos.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CelulaContatoCacheID = #"CelulaContatoCacheID";
UITableViewCell *cell = [self.tabelaContatos dequeueReusableCellWithIdentifier:CelulaContatoCacheID];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CelulaContatoCacheID];
}
Contato *contato = [contatos objectAtIndex:indexPath.row];
cell.textLabel.text = contato.nome;
return cell;
}
#pragma mark -
#pragma mark UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Contato *contato = [contatos objectAtIndex:indexPath.row];
NSString *msg = [NSString stringWithFormat:#"Fram:%#",contato.fram];
fran = [[NSMutableArray alloc] init];
fran = [NSMutableArray arrayWithObject:contato.telefone];
NSLog(#"finalmente eu consegui essa porra!!!%#", fran);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Contato"
message:msg
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[self.tabelaContatos deselectRowAtIndexPath:indexPath animated:YES];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"vai"]) {
NSIndexPath *indexPath = [self.tabelaContatos indexPathForSelectedRow];
perfilViewController *destViewController = segue.destinationViewController;
Contato *contato = [contatos objectAtIndex:indexPath.row];
fran = [[NSMutableArray alloc] init];
fran = [NSMutableArray arrayWithObject:contato.fram];
destViewController.frans = fran;
NSLog(#"%#%#", fran, destViewController.frans);
}
}
#end
I'd firstly do:
//declare NSDictionary *pl; in the ViewController.h
pl = [NSDictionary dictionaryWithContentsOfFile:plistCaminho];
Then to display Names, i'd simply use the dictionary as such:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[pl objectForKey:#"contatos"] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//...
//following commented line not needed anymore
//Contato *contato = [contatos objectAtIndex:indexPath.row];
cell.textLabel.text = [[[pl objectForKey:#"contatos"]
objectAtIndex:indexPath.row]
objectForKey:#"nome"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//following commented line not needed anymore
//Contato *contato = [contatos objectAtIndex:indexPath.row];
//NOTE: fran is a dictionary now
//change "fran" declaration in the ViewController.h to
//NSDictionary *fran;
fran = [[NSDictionary alloc] init];
fran = [[pl objectForKey:#"contatos"]
objectAtIndex:indexPath.row];
NSLog(#"finalmente eu consegui essa porra!!!%#", fran);
//...
//don't deselectRow (the indexPathForSelectedRow will not work correctly later)
//[self.tabelaContatos deselectRowAtIndexPath:indexPath animated:YES];
}
then on -prepareForSegue i'd pass the dictionary associated with the selected row:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"vai"]) {
NSIndexPath *indexPath = [self.tabelaContatos indexPathForSelectedRow];
perfilViewController *destViewController = segue.destinationViewController;
//following commented line not needed anymore
//Contato *contato = [contatos objectAtIndex:indexPath.row];
//NOTE: fran is a dictionary now
//change "fran" declaration in the ViewController.h to
//NSDictionary *fran;
fran = [[NSDictionary alloc] init];
fran = [[[pl objectForKey:#"contatos"]
objectAtIndex:indexPath.row]
objectForKey:#"fram"];
//NOTE: destViewController.frans should be a dictionary
//handle it appropriately
destViewController.frans = fran;
}
}
so basically, all dictionary use, no need for Contato *contato at all.
EDIT: As for your current method, you would be better off replicating the same structure.
As in:
[array of names] has {dictionary with user details} having a key that has {dictionary of frams}
I'd recommend you not using a dictionary to store your Fram values, use an array instead.
This way, you can get the Fram values like this:
for (NSDictionary *item in dados) {
NSString *nome = [item valueForKey:#"nome"];
NSString *telefone = [item valueForKey:#"telefone"];
NSArray *fram = [item valueForKey:#"fram"];
Contato *c = [[Contato alloc] initWithNome:nome andTelefone:telefone andFram:[fram objectAtIndex:index]];
[contatos addObject:c];
}
Where index is an integer variable you'll have to work out how to handle.
PS: be a little more polite when logging you app ;)

To Segue or to didSelectRowAtIndexPath?

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
}

iOS program to display database contents in app seperated by tabs

I have a program that connects to a MAMP server and selects my database and displays the contents in the Xcode simulator. Right now I have 2 tabs and the data is the same for both. I want the tabs to seperate the type of data to display in each tab. (1 tab should display types of wine grape and the other displays wine countries)
I think that I have to make a class (subclass of NSObject) that pulls the data, then another view controller with a mutable array that holds the data needed for each tab but HOW do I do this? How do I create a MutableArray?
Here the code in my TableViewController.m, which connects to my database using JSON:
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:#"http://[localhost]:8888/wine.php"]; // Modify this to match your url.
NSString *jsonreturn = [[NSString alloc] initWithContentsOfURL:url]; // Pulls the URL
NSLog(jsonreturn); // Look at the console and you can see what the restults are
NSData *jsonData = [jsonreturn dataUsingEncoding:NSUTF32BigEndianStringEncoding];
NSError *error = nil;
// In "real" code you should surround this with try and catch
NSDictionary * dict = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:&error];
if (dict)
{
rows = [[dict objectForKey:#"wine"] retain];
}
NSLog(#"Array: %#",rows);
[jsonreturn release];
}
Then I created another method for the tableview:
pragma mark - Table view data source
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [rows count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
NSDictionary *dict = [rows objectAtIndex: indexPath.row];
//cell.textLabel.text = [dict objectForKey:#"id"];
//cell.textLabel.text = [dict objectForKey:#"wineColor"];
//cell.textLabel.text = [dict objectForKey:#"wineGrape"];
cell.textLabel.text = [dict objectForKey:#"wineCountry"];
cell.detailTextLabel.text = [dict objectForKey:#"id"];
return cell;
}
with this, the same data (the wine countries) is displayed in both Grape & Country tabs. How can I create a Mutable Array that will grab what data should be displayed in each tab?
You need the second (Grape) view controller to implement the tableView datasource and delegate methods for its own tableview, but you don't need another array, you can use your JSON dictionary, but add the proper text to labels within your cells for grapes (in the cellForRowAtIndexPath UITableView datasource method). You would use the lines above that are currently commented out to populate your labels in cells of your "Grape" table view:
//cell.textLabel.text = [dict objectForKey:#"wineColor"];
//cell.textLabel.text = [dict objectForKey:#"wineGrape"];
You could add a custom UITableViewCell or use the subtitle style and set the subtitle to color.

Resources