How to create an array of arrays in UITableviews - ios

I have two tableViewControllers, my first tableView contains a list of items called folders, on click of which I will open the another tableView called ItemsInfolder and display if they are present or else it will empty.
So for this I know that ItemsInFolder View should be an array of arrays, with each array at index position (row position) , but I am confused, on how to do it , how to call array present at each index on click of each folder.
updated according to comments below
//FolderTableView
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ItemsTableViewController *selectedFolder = [[ItemsTableViewController alloc] initWithNibName:#"ItemsTableViewController" bundle:nil];
selectedFolder.selectedfolder = [indexPath row];
[self.navigationController pushViewController:selectedFolder animated:YES];
}
//ItemsTableView
-(void)xyz operation
{
[m_ItemArray addObject:item];
[appDelegate.2dArray addObject: m_ItemArray];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [[appDelegate.2dArray objectAtIndex:m_selectedfolder]count];(selected folder index coming from, folderTable)
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableArray *testArray = [appDelegate.2dArray objectAtIndex:[indexPath row]];
tableCell.items.text = [testArray objectAtIndex:[indexPath row]];
return tableCell;
}
So friends, please help me out.
Regards
Ranjit

Considered a arrayOfFolders global and initialized, full of arrays containing your files, following this hierarchy :
arrayOfFolders :
{
[0] //Folder 0 (NSArray)
{
file1
file2
file3
}
[1] //Folder 1 (NSArray)
{
file4
file5
}
}
When you'll click on your folder inside your tableView, get the child array like that :
-(void)didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//To retrieve your array within your array at the seleted index
NSArray * arrayOfItemsInFolder = [[NSArray alloc] initWithArray:[self.arrayOfFolders objectAtIndexPath:indexPath.row] copyItems:YES];
//Do your stuff
}
Does this seems right to you?

Related

How to add items to a side menu bar?

Im making my first app. My app will have a side pop out menu. I have gotten the sliding menu part implemented with a UITableView. Now i want to populate the side menu with text and a image next to it and when one is tapped i want to push another view controller. What would be the best way to do this? Thanks
As user132490 said, you probably want to add rows to your tableView. Here's a tutorial: http://www.appcoda.com/uitableview-tutorial-storyboard-xcode5/. It's for Xcode 5 but still will work. You may find it useful from "Adding Table Data" and below. In fact, before the Summary the tutorial teaches you to add a thumbnail next to the text of each of your cells.
Good luck!
When you want to have an image and text for your table, you have to create a UITableViewCell subclass and declare an image view and label. Image view and label must be created in IB, create a prototype cell and add there the image view and label.
Once you've done that you must have an array of what will be the content of your table. It's like this:
In #interface:
#property NSMutableArray *menuArray;
In your viewDidLoad:
NSDictionary *option1 = [NSDictionary dictionaryWithObjectsAndKeys:#"image1.png",#"image",#"Option1",#"desc", nil];
NSDictionary *option2 = [NSDictionary dictionaryWithObjectsAndKeys:#"image2.png",#"image",#"Option2",#"desc", nil];
NSDictionary *option3 = [NSDictionary dictionaryWithObjectsAndKeys:#"image3.png",#"image",#"Option3",#"desc", nil];
NSDictionary *option4 = [NSDictionary dictionaryWithObjectsAndKeys:#"image4.png",#"image",#"Option4",#"desc", nil];
NSDictionary *option5 = [NSDictionary dictionaryWithObjectsAndKeys:#"image5.png",#"image",#"Option5",#"desc", nil];
//assign NSDictionaries to array
self.menuArray = [NSMutableArray arrayWithObjects:option1,option2,option3,option4,option5, nil];
And then you must have table view delegate methods like this:
#pragma mark Table View delegate methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [menuArray count];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//return row height
return 32;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier =#"Cell";
//assign TableCell.h to access custom properties
TableCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
//get dictionary from menuArray
NSDictionary * dict = [self.menuArray objectAtIndex:indexPath.row];
UIImage *imageIcon = [UIImage imageNamed:[dict objectForKey:#"image"]];
//set image
[cell.img setImage:imageIcon];
//set the label text
cell.label.text = [dict objectForKey:#"desc"];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//research more about pushing another view controller.
//if chosen was option1
if (indexPath.row == 0)
{
NSLog(#"option1");
}
//if chosen was option2
if (indexPath.row == 1)
{
NSLog(#"option2");
}
//if chosen was option3
if (indexPath.row == 2)
{
NSLog(#"option3");
}
// if chosen was option4
if(indexPath.row == 3)
{
NSLog(#"option4");
}
// if chosen is option5
if(indexPath.row == 4)
{
NSLog(#"option5");
}
}
In pushing to other view controller, try to research more because it's a lot more explanation. Try this link: https://github.com/ECSlidingViewController/ECSlidingViewController
But with this codes, you must be able to populate your table and when you select a cell there will be a log. Hope this helps :)

Objective-C select part of array

I am quite new to xcode / objective-c and I am facing a problem for a while now.
In my application I have a Json array receiving from my server, I send the array to the secondViewController by segue. This all goes right.
In my secondViewController I receive the array and select the part I needed by;
self.excersiseSection = [self.schemeData objectForKey:#"user_excersise_sections"];
This outputs the part of the array I've pushed to this controller so that's allright. Now, I want
to select the nested 'exercises' array (to print my table cells) in this array I have tried to do it like the code above with the index 'exercises' but no success.
{
"user_training_days": [
{
"day_id": 1,
"day_name": "Monday",
"training": "trainingsdag",
"user_excersise_sections": [
{
"section_title": "Legs",
"exercises": [
{
"exercise_title": "Leg press",
"excercise_sets": "4",
"excercise_reps": "12",
}
]
},...etc
Here is a sample code that will iterate over your json, and simple print it out
for (NSDictionary *section in excersiseSection) {
NSLog(#"--- section_title: %#", section[#"section_title"]);
for (NSDictionary *excercise in section[#"exercises"]) {
NSLog(#"----- exercise_title: %#", excercise[#"exercise_title"]);
NSLog(#"----- excercise_sets: %#", excercise[#"excercise_sets"]);
NSLog(#"----- excercise_reps: %#", excercise[#"excercise_reps"]);
}
}
This should help you, to construct your tableview.
EDIT:
Here is a complete solution to render your tableView.
1) Create a TableViewController in strotybaord, and assign a Custom class in storyboard.
2) Paste below code in the class
3) You are ready to go! :)
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.excersiseSection.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.excersiseSection[section][#"exercises"] count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return self.excersiseSection[section][#"section_title"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
NSDictionary *excercise = self.excersiseSection[indexPath.section][#"exercises"][indexPath.row];
cell.textLabel.text = excercise[#"title"];
cell.detailTextLabel.text = [NSString stringWithFormat:#"Sets: %#, Reps: %#",
excercise[#"excercise_sets"], excercise[#"excercise_reps"]];
return cell;
}
I don't know how your data model is structured, but couldn't you try something like the following:
self.excersiseSection = [[[self.schemeData objectForKey:#"user_excersise_sections"] objectAtIndex:0] objectForKey:#"exercises"];
Just chain the calls together. Note that this won't work if user_excersise_sections and exercises are not NSArray objects.
I'd suggest creating particular classes like UserTrainingDay, UserExcersiseSection and Excercise and use for example Mantle framework to establish mapping between your JSON and model classes.

Blank rows on 2 TableViewController with data from one Viewcontroller in the other viewcontroller

I have 2 UITableViewControllers in my project.
The problem I am having is that I am getting blank cell entries in the tableView opposite to the tableView where the data is entered.
I can't seem to figure out why this is the case.
It's creating blank rows in this tableView even though the information is from the other UITableViewController.
Here's the main tableView part from the one of the 2 UITableViewControllers:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(#"number of addedSpaceObjects %lu",(unsigned long)[self.diaryoptions count]);
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"number of sections %ld",(long)section);
// Return the number of rows in the section.
return [self.diaryoptions count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentification = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentification
forIndexPath:indexPath];
Data2 *diary = [self.diaryoptions objectAtIndex:indexPath.row];
cell.textLabel.text = diary.diaryname;
cell.detailTextLabel.text = diary.diaryWeight;
return cell;
}
And from other UITableViewController:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(#"number of addedSpaceObjects %lu",(unsigned long)[self.addedSpaceObjects count]);
// Return the number of sections.
if ([self.addedSpaceObjects count]) {
return 2;
}
else {
return 1;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"number of sections %ld",(long)section);
// Return the number of rows in the section.
if (section == 1) {
return [self.addedSpaceObjects count];
}
else {
return [self.recipes count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentification = #"Josh";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentification
forIndexPath:indexPath];
if (indexPath.section == 1) {
Data *recipe = [self.addedSpaceObjects objectAtIndex:indexPath.row];
cell.textLabel.text = recipe.name;
}
else {
// Configure the cell...
Data *recipe = [self.recipes objectAtIndex:indexPath.row];
cell.textLabel.text = recipe.name;
}
return cell;
}
Here is the full project on GitHub. https://github.com/josher32/Plant-Diet
Appreciate any help anyone can offer!
Ok, so I checked out the app and I'll try my best to explain the problem as precisely as I can to cover it adequately.
Firstly, the classes in question are:
RecipesTableTableViewController
AddRecipeViewController
Data
DiaryTableViewController
AddDiaryViewController
Data2
Secondly, we'll need to look into your
#define ADDED_SPACE_OBJECTS2 #"Added Space Objects Array"
AddRecipeViewController
So... AddRecipeViewController basically creates a Data object that is kept in an array and eventually stored in NSUserDefaults under the key name Added Space Objects Array.
Great!! So you now have got recipe related stuff in some Data object.
AddDiaryViewController
Same thing here.
AddDiaryViewController creates a Data2 object that is eventually stored in NSUserDefaults under the same key name Added Space Objects Array.
But before storing this, you're taking the old value of the key Added Space Objects Array, which is an array, and adding a new object to it before placing it back into NSUserDefaults.
But now... this array will now have a combination of Data as well as Data2 objects!
RecipesTableTableViewController
When we come here, things get real.
- (void)viewDidLoad
{
//...
NSArray *myRecipeAsPropertyLists = [[NSUserDefaults standardUserDefaults] arrayForKey:ADDED_SPACE_OBJECTS_KEY];
for (NSDictionary *dictionary in myRecipeAsPropertyLists) {
Data *spaceObject = [self spaceObjectForDictionary:dictionary];
[self.addedSpaceObjects addObject:spaceObject];
}
}
Since we already realized that self.addedSpaceObjects can contain Data as well as Data2 objects, in the case whendictionary is containing stuff specific to type Data2, spaceObjectForDictionary will not be able to translate it properly to the required Data object.
We're expecting name, title, ingredients, directions but we're getting diaryentry, diaryname,diaryWeight.
So (in this scenario):
The values of name, title, ingredients, directions will be nil
The section-row count will be incorrect because it will give count of both Data as well as Data2 objects (and we don't care about Data2 objects in the RecipesTableTableViewController class... right?... well anyways, I assumed)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//...
if (indexPath.section == 1) {
Data *recipe = [self.addedSpaceObjects objectAtIndex:indexPath.row];
cell.textLabel.text = recipe.name;
}
//...
}
We see recipe.name is nil, for some indexPaths, ergo blank rows and vice versa in DiaryTableViewController.
Solution:
Firstly, I wouldn't recommend NSUserDefaults for your purposes but anyways...
Basically, don't use a single #"Added Space Objects Array" key for your NSUserDefaults stuff.
I'd suggest you use 2 separate keys.
//replace
//#define ADDED_SPACE_OBJECTS2 #"Added Space Objects Array"
//with
#define ADDED_SPACE_OBJECTS2 #"RecipeEntries" //in RecipesTableTableViewController
//and
#define ADDED_SPACE_OBJECTS2 #"DiaryEntries" //in DiaryTableViewController
Basically, segregate the entries instead of mixing them up under a single key name.
This seems like the quickest way to solve your problem without changing your logic.

cellForRowAtIndexPath not being called - using tag to identify TableView

I've seen a number of people who have asked a similar thing, but answers to their questions are not the answers to mine.
1) I have created a single view application with an empty View Controller. In that, I dragged a new Table View (style Plain) with a single prototype cell of style Basic.
2) I am trying to learn about dynamically changing the behaviour of TableViews, so I have a mutable array called sectionRows, which will contain the number of rows per section. At the moment, a single section with a number of rows would be an achievement :)
3) In my ViewController.h I have set the delegates
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#end
I have also control-dragged from the TableView to the ViewController Yellow-Circle and set the datasource and delegate outlets.
4) In my ViewController.m, I have defined some global variables
#interface ViewController ()
{
NSMutableArray *sectionRows;
UITableView *myTableView;
}
The first is my data array (containing the number of rows per section and the second is a pointer to my TableView, which I have identified using a numeric View tag of '1'.
5) In my viewDidLoad, I initialize everything:
- (void)viewDidLoad
{
[super viewDidLoad];
myTableView = (UITableView *)[self.view viewWithTag:1];
sectionRows = [[NSMutableArray alloc] init]; // Create sectionarray
[sectionRows addObject:[NSNumber numberWithInteger:1]];
myTableView.dataSource = self;
myTableView.delegate = self;
[myTableView reloadData];
}
As you can see, I even make sure that I set the datasource and delegate again but this hasn't made any difference.
5) I have overloaded 3 methods.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"Returning %# rows", [sectionRows objectAtIndex:section]);
return (NSInteger)[sectionRows objectAtIndex:section]; // the number referenced in the array...
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSLog(#"Returning %li sections", sectionRows.count);
return sectionRows.count; // the size of the sectionRows array
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = #"xxx";
NSLog(#"Setting cell to %#", cell);
return cell;
}
Now, when I run this, I am getting NSLog returning confirmation that there is a single section and a single row:
2014-07-27 19:58:34.599 TableViewTests[12877:60b] Returning 1 sections
2014-07-27 19:58:34.600 TableViewTests[12877:60b] Returning 1 rows
However, as you can see cellForRowAtIndexPath is not being called.
None of the other things I have seen point to what I am doing wrong. I am doing what I thought I did successfully in another simple project (to learn) but I must be doing something else differently.
Any ideas what I am missing?
Thanks in advance
Jon
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"Returning %# rows", [sectionRows objectAtIndex:section]);
return (NSInteger)[sectionRows objectAtIndex:section]; // the number referenced in the array...
}
This is incorrect. You cannot cast what you get from your array to an NSInteger. It's a pointer. Assuming you store NSNumbers into the array:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"Returning %# rows", [sectionRows objectAtIndex:section]);
return [[sectionRows objectAtIndex:section] integerValue]; // the number referenced in the array...
}

Get the list of selected cells in different sections

The user can select/deselect cells in each section, so to track all the selected cells in the didSelectRowAtIndexPath is not useful:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"row = %i, section = %i", indexPath.row, indexPath.section);
}
What i want instead is to save time and resources, so to let the user check/uncheck whatever he wants, and when he click on a button (to go to next view), i need to collect all selected cells in the whole table view. I tried to do like this:
-(IBAction)nextView:(id)sender{
themesChoosed=[self.tView indexPathsForSelectedRows];//tView is the outlet of my UITableView and themesChosed is an NSArray declared in the .h file
for (int i=0; i<=[themesChoosed count]; i++) {
NSIndexPath *thisPath = [themesChoosed objectAtIndex:i];
NSLog(#"row = %i, section = %i", thisPath.row, thisPath.section);
}
}
But this doesn't return me the selected cells, it shows me always: row = 0, section = 0 as if i am only selecting the first cell in the first section.
Any thoughts on how to do so?
Take in .h file
NSMutableArray *selectedArray;
in .m
viewDidLoad
selectedArray=[[NSMutableArray alloc]init ];
in tableviewDidSelect
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//According to section take value from table and get string selectedString.
if([selectedArray containsObject:selectedString])
{
[selectedArray removeObject:selectedString];
}
else
{
[selectedArray addObject:selectedString];
}
}

Resources