I got a table view with approx 45k items. I want to use the indexbar to be able to scroll faster through my list.
Now I've looked at other questions on here, but I just can't figure out what to do.
I've got the following two functions:
-(NSArray*)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return alphabetsArray;
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return index;
}
I don't understand what I should do next. Like, I have an array called airports which is sorted alphabetically. What should I be doing with this array?
update
so I found an article I could use and I'm pretty close now, I think. My table view only shows 2 items now though.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"ROWS METHOD CALLED");
NSArray *unsortedKeys = [alphabetizedAirports allKeys];
NSArray *sortedKeys = [unsortedKeys sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSString *key = [sortedKeys objectAtIndex:section];
NSArray *airportsForSection = [alphabetizedAirports objectForKey:key];
return [airportsForSection count];
}
I have about 60 items in my sortedKeys array. The airportsForSection array only gets 2 items though so when it returns the array, the tableview only shows 2 items. Any ideas how to solve?
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
Unfortunatly I dont currently have internet on my laptop so I will have to describe my code, I have a mutable array of alphabetically sorted song titles. I have a uitableview that is currently displaying these however I want to have section heads and an alphabet index at the side of the table so I need to put these songs into an nsdictionary to display it, however I cant work out an an efficent method of sorting the array into the alphabetical sections (also has a # section, ive made a nsarray of section heads) in the nsdictionary.
There are many possibilities to prepare your data. But since your songs are already sorted your view controller could look something like this:
#interface TableViewController ()
#property (strong, nonatomic) NSArray *sectionTitles;
#property (strong, nonatomic) NSArray *songsInSections;
#end
#implementation TableViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *songs = #[#"A song", #"Another song", #"Some other song", #"Yet another song"];
// store all the needed section titles
NSMutableArray *sectionTitles = [NSMutableArray array];
// store the songs in sections (arrays in array)
NSMutableArray *songsInSections = [NSMutableArray array];
// prepare the data for the table view
for (NSString *song in songs) {
// get the song's section title (first letter localized and uppercased)
NSString *sectionTitle = [[song substringToIndex:1] localizedUppercaseString];
// check if a section for the song's section title has already been created and create one if needed
if (sectionTitles.count == 0 || ![sectionTitle isEqualToString:sectionTitles[sectionTitles.count - 1]]) {
// add the section title to the section titles array
[sectionTitles addObject:sectionTitle];
// create an (inner) array for the new section
[songsInSections addObject:[NSMutableArray array]];
}
// add the song to the last (inner) array
[songsInSections[songsInSections.count - 1] addObject:song];
}
// "store" the created data to use it as the table view's data source
self.sectionTitles = sectionTitles;
self.songsInSections = songsInSections;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.songsInSections count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return self.sectionTitles[section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.songsInSections[section] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = self.songsInSections[indexPath.section][indexPath.row];
return cell;
}
- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.sectionTitles;
}
#end
How to iterate from this multi-dimensional array in iOS ?
This data is coming from JSON
(
(
"burger meal",
"getImage.ashx?id=1",
150,
300,
"get a free burger"
),
(
"chinese combo",
"getImage.ashx?id=2",
350,
700,
"get a combo free"
),
(
"cheeese cake",
"getImage.ashx?id=3",
350,
700,
"get a cake free with meal"
)
)
I need to use object at index 3 e.g. = 150,350,350 in UITableView .
I have tried this
NSArray *array = jsonArray;
for (NSArray *newArray in array) {
[newArray addObjectFromArray:array];
}
Try This, In this code arrResult contain all values have you required at particular position.
NSArray *array = jsonArray;
NSMutableArray *arrResult = [[NSMutableArray alloc]init];
for (NSArray *newArray in array) {
[arrResult addObject:[newArray objectAtIndex:2]];
}
This is simple. Let TableView iterate the arrays for you. Your tableView is already iterating, don't add to overhead by iterating over the array yourself. You will just waste processing power if you do.
First, modify your numberOfRowsInSection delegate method like this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [jsonArray count]; //Provide your json array here.
}
Then you have to do this in your cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Do everything that you need to do to get the cell. Here we will deal with only string retrieval from json array.
if(jsonArray count]>indexPath.row){
NSArray *innerArray = [jsonArray objectAtIndex:indexPath.row]; //You got the inner array
if(innerArray count]>2){
NSString *yourDesiredString = [innerArray objectAtIndex:2]; //You got the string. Use it now as you wish. It will be 150 for the first cell, 350 for the second and 350 for the third one as well.
}
}
}
I have not added any exception checks here, that's what you have to do yourself. I have added basic checks to prevent crashes in case of irrelevant data, you should expand on that.
This is with the assumption that you wish to set this string to each cell. If I have misunderstood your question or you need to ask something, leave a comment
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.
I have a tableView where I have implemented section headers and I have the section titles appearing along the right hand side. However, when I tap the index it doesn't scroll to that section even though I can see in my logs that it is returning the correct section.
Here is my method for tableView:sectionForSectionIndexTitles:atIndex
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
NSLog(#"Title: %#", title);
NSLog(#"index: %d", index);
return [[UILocalizedIndexedCollation currentCollation] sectionForSectionIndexTitleAtIndex:index];
}
Any help would be great, thanks.
If you want to create alphabets scroll. This will helps.
-(void)viewDidLoad {
//section index in tableview
alphabetsArray = [[NSArray alloc] initWithObjects:#"#",#"A",#"B",#"C",#"D",#"E",#"F",#"G",#"H",#"I",#"J",#"K",#"L",#"M",#"N",#"O",#"P",#"Q",#"R",#"S",#"T",#"U",#"V",#"W",#"X",#"Y",#"Z", nil];
}
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return alphabetsArray;
}
I have a table view which populates from a plist. in a plist I have a Categories array:
Catgeories - Array
item 0 - Maths
item 1 - English
....
in the same plist i have a Notes array
Notes - Array
item 0 - Dictionary
Title - My maths note 1
Text - This is algebra
Category - Maths
item 1 - Dictionary
Title - My English
Text - This is algebra
Category - English
in number of sections i have...
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [self.categories count];
}
In numberOfRowsInSection before i added the categories array to the plist i could simply use
return self.notes.count;
which produces a duplicate in every category: http://i.stack.imgur.com/9xScH.png
but now in this method i should expect to return the number of rows based on the section, not sure how to do this
You need to do something like that:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
{
return self.notes.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.notes[section].count;
}
You get array of you notes base on the section and return count of the array.
//EXTENDED
If you want to have as many section as data in Category array use:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
{
return self.catgeories.count;
}
The self.note array contain dictionaries object with Category key and I believe you want to show all of the data for section where category is equal section category. To do that you have to filter your notes array, try this (I assume that you have distinct objects in Caregory plist):
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Get category
NSString *cat = self.catgeories[section];
//Filter notes array
NSPredicate *pred = [NSPredicate predicateWithFormat:#"Category =[cd] %#", cat];
NSArray * catArray = [self.notes filteredArrayUsingPredicate:pred];
return catArray.count;
}
I have edited the answer.
If you wanna access large amount of data, i suggest that you store your data in core data instead of plist,
For getting number of rows for each section you can use this
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// check if the count of the array is greater than number of sections
if (self.notes.count > section)
return [[[self.notes objectAtIndex:section]allObjects]count];
}
Hope it helps :)
You can try like this if you want to return different number of rows in each section:-
- (NSInteger)tableView:(UITableView
*)tableView numberOfRowsInSection:
(NSInteger)section
{
int rows=0;
if(section==0)
{
rows=1;
}
if(section==1)
{
rows=2;
}
rerurn rows;
}