Passing NSDictionary to another controller using UITableView - ios

I have this NSDictionary:
{
Name =
(
"Lucas",
"Tom"
);
Surname =
(
"Jhon",
"Smith"
"Hop"
);
Name is a simple NSArray and Surname is a NSMutableArray.
Ok now my problem is this:
Starting from this dictionary, I must show in UITableView the key of each element of the NSDictionary. For example, in this case, UITableView will have two items, one call Name and the other Surname.
When I click on an element of the UITableView I will have to go to another controller that will show me all the data of the clicked cell. If for example, I click on Surname, when I open the new controller, I'll have to get it like Jhon, Smith and Hop.
To get started, I tried to show the UITableView before all the keys by writing:
self.KeyArray = [myDictionary allKeys];
and in the cellForRowAtIndexPath method:
cell.textLabel.text = [self.KeyArray objectAtIndex: indexPath.row];
But this is a wrong approach, because I'm going to lose all the information related to that specific key. Do you have any idea how I can do it?

You can use delegate to send that NSMutableArray to another controller.
Lets say your first view controller is "A" which has those name and surname keys. And second Controller is "B" which will has the array that you want to send.
Now,
1. Create a protocol in A controller.
2. Create the delegate object of that protocol.
3. Create 1 Method in A controller which can have a parameter Like :- (NSMutableArray *).
4. Implement that protocol in to B Controller.
5. Declare the method in Controller B that you defined in Controller A
6. Call that method with the help of delegate object in didSelectRowAtIndexPath and Pass that Object in that method.
7. Now you have the NSMutableArray in that method and you are free to use that values.

You can do like that in didSelectRowAtIndexPath write below code
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *keyOfMainDic = [self.KeyArray objectAtIndex:indexPath.row]; // in the keyOfMainDic, you will get selected key name of your main dictionary
NSMutableArray *temArray = [yourMaindict objectForKey:keyOfMainDic] // You will get array of specific key.
// Here you just need to pass "temArray" to your destination controller.
}

First you should define a segue from your view controller that has tableview to your detail controller and give it an identifier in storyboard.
Then define a property into your detail controller header inherit from KeyArray type.
After that, just code it like below. This is just suggestion, please use a model for your array instead of dictionary.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
self.KeyArrayItem = [self.KeyArray objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"yourSegueID" sender:self.KeyArrayItem];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
AnotherController *controller = segue.destinationViewController;
controller.KeyArrayItem = sender;
}

Related

numberOfRowsInSection and prepareForSegue method problems

I am new to iOS development and I am having a trouble with counting objects from Array which contains Dictionaries.
My data structure looks like this and it's located in another custom class:
Library header file
Library implementation file
There will be quite a lot of them (now only 4 just for testing) and I need to count NSStrings with key kEviela.
I need this counting to calculate number of rows required for my tableView:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return ?;
Also I have a detailView where I need to show each of this String separately. So how can I do this in prepareForSegue method?
It's just
return _library.count;
which is the number of dictionaries in the array.
Anyway I recommend to map the dictionary to a custom class.
To get an array of all values for key kEviela write
NSArray *kEvielaArray = [_library valueForKey: kEviela];
This is one of the rare cases where valueForKeyis intended as a KVC method.
First of all,i think you can show number of rows by counting your dictionary objects. I use NSMutableArray converting from dictionary because it's easier for me to manipulate.It's totally personal though.
Also I have a detailView where I need to show each of this String separately.
What you can do?
There is function called didSelectRowAtIndexPath delegate method.
When you select row this function is called.In this function you grab your detailView controller and keep value to one of it's variable(NSString or Something) according to your data.
you can call segue programmatically from here after assigning value.
As an example:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
DetailViewController *detailVC = [[DetailView alloc] initWithNibName:#"DetailView" bundle:nil];
detailVC.userName = [userList objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailVC animated:YES];
}
or, If you don't want to use like this, then in prepareForSegue method (what you called)
grab your destination view controller and assign value just like previous. That's it.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// Get reference to the destination view controller
YourViewController *vc = [segue destinationViewController];
vc.dictionary = [youdictionary mutableCopy];
// Pass any objects to the view controller here, like...
[vc setMyObjectHere:object];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _library.count;
}
Above is the Way you get the count of array check it out.
Here first you have Array and then you can find out the dictionary value.
NSString *kEvielaValue = [_library valueForKey: "kEviela"];
Try this [[_library valueForKey: kEviela]count];
[_library valueForKey: kEviela] will pick up an NSArray that contains all the values of kEviela and the count message will give you the number of those elements from the main array of _library

Values are not displaying in table view in ios

I have declared an array in ViewController and displaying it in table view. I am passing values for an array from EditViewController. But the values are not displaying in table view. I am using following code.
ViewController.h
#property (nonatomic, strong) NSMutableArray *tableData;
ViewController.m
ViewDidLoad:
tableData = [NSMutableArray arrayWithObjects:#"",nil];
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
EditViewController.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
ViewController *vc;
vc = [segue destinationViewController];
NSString *str = [NSString stringWithFormat:#"%ld", selectedRow];
[vc.tableData addObject:str];
}
Please advice.
Connect the delegate and datasource to self in the viewDidLOad of editViewController
tableView.delegete=self;
tableView.Datasource=self;
If there is no data in the tableview itself, hit a breakpoint at
cellForRowAtIndexPath,
and Still if it dsnt hits the breakpoint,connect the Delegate and Data source for the tableview with the View Controller.
[EDIT]
If it is still not called, go to storyboard, check if the bounds of the tableview, is more than that of the vc, that means, check if the tableview is inside the view controller and no part of the tableview is crossing the bounds of the view controller.
Plz make sure you have
-tableView:numberOfRowsInSection:
method defined. This method should return value greater than 0 so that
-tableView:cellForRowAtIndexPath:
gets called.
you are add string to nsarray object which is not allocated.
you have to create nssarray with string and pass to the vc.tableData.
There may be a few problems with this.
First, it's best to set a the NSMutableArray property "tableData" to an existing array passed in during the segue. Right now you're adding a single string to a mutable array which, unless you wrote a custom initializer for the ViewController in which you alloc-init'ed the NSMutableArray, it can't exist until ViewDidLoad which is after the segue is performed, so you're passing the string to black abyss of "nil".
It's best to use base types as receiving properties in prepareForSegue, and then in your case to pass the ViewController's array an already existing array from the EditViewController.
Also, you may not be telling the view controller how many cells to actually create. Make sure numberOfSectionsInTableView returns a value (in this case just 1), and that numberOfRowsInSection returns "[self.tableData count]".
And if you didn't create ViewController as inheriting from UITableViewController, you'll need to set that, and connect the delegate and datasource manually in the storyboard like Light Yagami pointed out. Though it would probably be easier to just create a new custom class file that inherits from UITableViewController because it will give you some good boilerplate code.
And also make sure that in your storyboard, your TableViewController's class is set to your custom class file.
I hope you did not pass numberOfSectionsInTableView as 0. Please check that once. It must be 1 or more based on requirement. And same for numberOfRowsInSection.
Remove this line from your ViewDidLoad Method
tableData = [NSMutableArray arrayWithObjects:#"",nil];

Passing data from custom table cell to text fields

I am creating a demo app of an Address Book, which saves people info in an array and displays it in a custom table cell.
The first controller saves the info entered by the user in text fields in an array.
The second controller displays the info in a custom table cell.
The third controller is the same as the first with the only difference is that it will be used not for storing data, but to update the data.
What I now want is to update the table cell data. I have created an update button, on click I am segueing to the 3rd controller.
What I want is the information displayed in a particular cell, to be passed to the 3rd view controller text fields, when the update button is clicked.
How can I achieve this?
I think you store your data in some array or something similar structure. So you can get data from it like this
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)newIndexPath {
MyThirdViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"ThirdViewController"];
vc.dataToDisplay = self.myDataArray[indexPath.row];
}
Then in your third view controller you will have data you need to display.
For example if you know order of data in your new array, you can fill your text fields like this
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
//if your data is an array
self.firstTextField.text = self.dataToDisplay[0];
self.secondTextField.text = self.dataToDisplay[1];
//and so on
//if your data is a dictionary
self.firstTextField.text = self.dataToDisplay[#"name"]; //for string objects
self.secondTextField.text = [self.dataToDisplay[#"age"] integerValue]; //for integer values
}
//in your third viewcontroller.h
#property NSString * textfieldname;
#property NSString * textfieldage;
//in your second viewcontroller.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([[segue identifier] isEqualToString:#"identifiername"]){
NSIndexPath *ip = [yourtablename indexPathForSelectedRow];
thirdviewcontrollerr *targetVC = [segue destinationViewController];
targetVC.textfieldname=[[arrayname objectatindex:ip.row]valueforkey:name];
targetVC.textfieldage=[[arrayname objectatindex:ip.row]valueforkey:age];
//in your thirdviewcontroller.m
nametextfield.text=_textfieldname;
agetextfield.text=_textfieldage;

UICollectionView - pass array date via segue for selected indexpath

I have used a collectionview to present some data - all is fine but I'm struggling with passing the data to a child view by a segue - basically I need to pass the array data for the index path clicked - this is what I have at the mo -
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"sightSeg"]) {
NSArray *thisarr = [_sightsColView indexPathsForSelectedItems];
SightViewController *destController = [segue destinationViewController];
destController.viewTit = thisarr.siteTitle;
}
}
I currently get an error stating 'property not found on type nsarray'.
cheers
You are calling a property "siteTitle" of an object of type NSArray that is not natively provided by iOS, since it is your custom property not a native NSArray property.
Supposing that your array contains a dictionary for each element into the array, you could do something like this:
// Implement the collection view delegate method
- (void)collectionView:(UICollectionView *)collectionView
didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
self.selectedItemIndex = indexPath.row; // define NSInteger selectedItemIndex property in your interface
}
// then in your prepareForSegue
...
..
.
NSDictionary* selectedItem = (NSDictionary*)[yourDatasource objectAtIndex:self.selectedItemIndex ];
SightViewController *destController = [segue destinationViewController];
destController.viewTit = [selectedItem objectForKey:#"siteTitle"];
// Otherwise if it is a simple nsarray contains strings only
// ( so each element in the array is directly the title of a different view ) you could simply:
NSString* selectedTitle = (NSString*)[yourDatasource objectAtIndex:self.selectedItemIndex ];
SightViewController *destController = [segue destinationViewController];
destController.viewTit = selectedTitle ;
Hope it helps
I guess you data source object for the selected collection cell implements a siteTitle property? However, thisarr contains objects of the class NSIndexPath, i.e. just a "pointer" where to find the object for the selected cell you are interested in. Use the index path(s) to get the approriate object(s) from your actual data source.
Collection views support multiple selection. For that reason, the indexPathsForSelectedItems method returns an array of NSIndexPath objects, one for each selected item.
As Luca Iaco suggests in his post, you can set up your code to respond do the didSelectRowAtIndexPath message, and record the row of the item the user selected.
Based on what you're trying to do, you likely only want single selection. You should set the allowsMultipleSelection flag to false on your collection view in that case.
You can ask the collection view for the current selection using indexPathsForSelectedItems, then fetch the first item in the array:
NSArray *selectedItems = [self.collectionView indexPathsForSelectedItems;
NSIndexPath *selectedItem = selectedItems[0];
int selectedIndex = selectedItem.row;
MyClass *item = (MyClass *) thisarr[selectedIndex];
NSString title = item.siteTitle;
Where you would replace "MyClass" above with the class of your object that is in the thisArr array and has a "siteTitle" property.

Get NSDictionary Selected row in Push for Segue [IOS]

Hey guys I have an array of dictionaries plist file that I am reading from. I am using a Push for Segue method to pass on my data(a dictionary) to the next view controller. How can I get the selected row using a dictionary? I am making a table view app and I have already nade the (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath and it works.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSDictionary *d = [self.model.players objectAtIndex:0]
nextVC.title = [d valueForKey:#"Player"]
nextVC.info = d
}
When I use the above code and use the ObjectAtIndex:0 and specify 0 I can extract the data for that specific player in the next view controller. But I want to get the correct one based on the user selected row. How can I do that?
[self.model.players objectAtIndex:[self.tableView indexPathForSelectedRow]];
should do it

Resources