This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to display an array in reverse order in objective C
I have an NSMutableArray and this array contains information nicely in UITableView.
but I want to display latest information first in UITableView. Right now the earliest information comes first in UITableView. My code is as follows:
NSMutableArray *entries = [NSMutableArray array];
[self parseFeed:doc.rootElement entries:entries];
for (RSSEntry *entry in entries) {
[allEntries insertObject:entry atIndex:0]; //insertIdx];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationRight];
}
then How can I reverse the information in NSMutableArray?
How about just enumerating the contents of entries in reverse order?
for (RSSEntry *entry in [entries reverseObjectEnumerator]) {
...
}
If you just want to take an array and create a reversed array, you can do this:
NSArray *reversedEntries = [[entries reverseObjectEnumerator] allObjects];
You can try like this way:
for (int k = [originalArray count] - 1; k >= 0; k--) {
[reverseArray addObject:[originalArray objectAtIndex:k]];
}
Related
I have a UITableView that gets populated via an array (tableArray), who gets populated from core data.
each UITableViewCell gets assigned a number at creation time and the numbers are stored in an array. (numberArray)
when the user reorders the rows, the numbers get moved around in the array (in conjunction with the tableView of course)
So two Mutable arrays are used here.
The numberArray holds the numbers (or the order) of the TableViewCells.
I need to sort the array that holds the UITableViewCell's text (tableArray)
to reflect the same order that the numberArray holds.
Also, this is important: as i said before, each cell gets assigned a number, this number is stored in the numberArray,
I need both of the arrays to be sorted to hold the same values in the same place.
So for example:
tableArray hold some objects:
1) hi
2) whats Up
3) this
4) is cool!
so as you can see each object here was assigned a number 1-4.
and each of these numbers is added to the numberArray.
The user can move the cells around so obviously the order of the numbers will change.
So when the view loads up, i need to get the exact order of the numberArray whether it is
1,2,3,4 or 2,4,3,1
and i need to sort the tableArray to reflect the same order as the numberArray
so when the view loads up, if the numberArray's order is 2,3,4,1 i want the tableArray's order to be set to
2"whats up", 3"this", 4"is cool!", 1"hi".
I believe i can do this via NSPredicate.
Any help is greatly appreciated!
EDIT
cellForRow:
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString * identifier = #"identifier";
self.myCell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (self.myCell == nil) {
self.myCell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
HandgunAmmo *handgunAmmo = [self.tableArray objectAtIndex:indexPath.row];
self.myCell.brandLabel.text = handgunAmmo.brand;
self.myCell.caliberLabel.text = handgunAmmo.caliber;
self.myCell.numberOfRoundsLabel.text = handgunAmmo.numberOfRounds;
return self.myCell;
}
And in my viewWIllAppear method:
-(void)viewWillAppear:(BOOL)animated{
if (self.context == nil)
{
self.context = [(RootAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
NSFetchRequest *request = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"HandgunAmmo" inManagedObjectContext:self.context];
[request setEntity:entity];
NSError *error;
NSMutableArray *array = [[self.context executeFetchRequest:request error:&error] mutableCopy];
[self setTableArray:array];
[self.ammoTable reloadData];
[super viewWillAppear:YES];
}
So, the reason why the array doesnt stay persistent when being changed is because im loading the data from core data, and i call [self setTableArray:array]; which reloads all of the data from core data into the array, then it populates the tableview with the array. So i need to be able to sort the array before i set it equal to self.tableArray.
Thank you for the help!
Why don't you leave the tableArray unchanged, and use the numberArray as an index into the other array.
You would initialize the numberArray to 0, 1, 2, ..., n-1 with
numberArray = [NSMutableArray array];
for (NSUInteger i = 0; i < [tableArray count]; i++) {
[numberArray addObject:[NSNumber numberWithUnsignedInteger:i]];
}
When you need an item, e.g. in cellForRowAtIndexPath, you access it via the index:
NSUInteger i = [[numberArray objectAtIndex:row] unsignedIntegerValue];
NSString *item = [tableArray objectAtIndex:i];
Now you need to reorder the numberArray only, and the changes will automatically be reflected in the table view.
Update: A good solution to handle the reordering of Core Data objects in a table view can be found here: UITableView Core Data reordering
I cant see a way to solve it with a predicate
NSArray *stringArray = #[#"hi", #"what's up?", #"this", #"is cool"];
NSArray *numberArray = #[#2, #4, #3, #1];
NSMutableArray *combinedArray = [NSMutableArray array];
//connect string with the numbers of there new position
[numberArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSString *string =stringArray[[obj integerValue]-1];
[combinedArray addObject:#[string, obj]];
}];
NSMutableArray *orderedArray = [NSMutableArray array];
[combinedArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[orderedArray addObject:obj[0]];
}];
NSLog(#"%#", orderedArray);
result
(
"what's up?",
"is cool",
this,
hi
)
NSMutableArray *unsortedArray = [NSMutableArray arrayWithObjects:#"1) hi",#"2) whats Up",#"3) this",#"4) is cool!",nil];
NSArray *guideArray = [NSArray arrayWithObjects:#"2",#"4",#"3",#"1", nil];
for(int i=0; i< [guideArray count];i++)
{
for(int j=0; j< [unsortedArray count];j++)
{
if([[[unsortedArray objectAtIndex:j] substringToIndex:[[guideArray objectAtIndex:i] length]] isEqualToString:[guideArray objectAtIndex:i]])
//if([[unsortedArray objectAtIndex:j] containsObject:[guideArray objectAtIndex:i]])
{
[unsortedArray exchangeObjectAtIndex:j withObjectAtIndex:i];
break;
}
}
}
NSLog(#"%#",unsortedArray);
OR
guideArray = #[#"2",#"4",#"3",#"1"];
unsortedArray = [#[#[#"1) hi"],
#[#"2) wats up "],
#[#"3) this,"],
#[#"4) cool"]] mutableCopy];
[unsortedArray sortUsingComparator:^(id o1, id o2) {
NSString *s1 = [o1 objectAtIndex:0];
s1 = [s1 substringToIndex:[s1 rangeOfString:#")"].location];
NSString *s2 = [o2 objectAtIndex:0];
s2 = [s2 substringToIndex:[s2 rangeOfString:#")"].location];
NSInteger idx1 = [guideArray indexOfObject:s1];
NSInteger idx2 = [guideArray indexOfObject:s2];
return idx1 - idx2;
}];
NSLog(#"%#",unsortedArray);
Try this hope this help partially.
I have an Iphone application in which i am trying to load the two arrays in to the same table.for that i combined two arrays and make another array.and load it from that array.that is working fine.My problem i need to make different cell images for these two array items.and also the detail text label is defferent for `
NSMutableArray *dataArray=[[NSMutableArray alloc] init];
NSMutableArray *dataArray1=[[NSMutableArray alloc] init];
NSDictionary *news=[dict objectForKey:#"news"];
NSDictionary *deals=[dict objectForKey:#"deals"];
NSLog(#"%#",[news classForCoder]);
NSLog(#"%#",news);
for(NSDictionary *key in news)
{
if([key isKindOfClass:[NSDictionary class]])
{
[dataArray addObject:key];
}
}
for(NSDictionary *key in deals)
{
if([key isKindOfClass:[NSDictionary class]])
{
[dataArray1 addObject:key];
}
}
self.newsarray = [[dataArray arrayByAddingObjectsFromArray:dataArray1] mutableCopy];
//self.newssarray=dataArray;
[self.mTableView reloadData];
` i need to change the cell image for the array elements from the two arrays.if the element is from first then the cell image is this else the other?can anybody show me the code snippet to achieve that?
I would make a property and set its value to [dataArray count].
In cellForRowAtIndexPath just do something like the following:
if(indexPath.row < dataArraySize)
{
// current row belongs to an element from the first array
}
else
{
// second array
}
You will have to reset dataArraySize anytime you update your data source if the size changes.
Alternatively, you don't even really need to create a new combined array if you just want to display the data.
if(indexPath.row < [dataArray count])
{
// populate row from first array
}
else
{
// second array
}
Once you combine them there will be no way to tell which array they came from. I believe you will need to keep a variable that is set to [dataArray1 count]; Then when doing your cells, decrement the counter and once its 0 start using the other cell image
I'm having a bit of trouble trying to delete rows that haven't been loaded (or not visible) from a UITableview.
My setup is as follows -
There are two sections in the tableview and each element in section 1 is associated with multiple elements from section two.
To give you an example (The data isn't really related to what I'm trying to do, but I believe this will be an example that doesn't really require much explanation)
Section 1
BMW
Acura
Merc
Section 2
328i
335i
RX
LX
TX
C300
C550
My internal model goes something like this -
NSMutableArray Cars[]
NSMutableArray Models[]
cars[0] = "BMW"
cars[1] = "Acura"
cars[2] = "Merc"
Each element in Models[] is a vector and their conents are listed below
Models = [ ["328i", "335i"], ["RX", "LX", "TX"], ["C300", "C550"] ];
So for the functionality I'm trying to build. If the user clicks delete and tries to delete BMW, the App needs to remove the entry for BMW from section 1 and the entries for 328i and 335i in section two. However, the user is free to delete any single row of section two independently.
Can anyone point me to a way I can proceed with this?
NSMutableArray *Cars = [[NSMutableArray alloc] initWithObjects:#"BMW",#"Acura",#"Merc",nil];
NSMutableArray *Arr1 = [[NSMutableArray alloc]initWithObjects:#"328i", #"335i",nil];
NSMutableArray *Arr2 = [[NSMutableArray alloc]initWithObjects:#"RX", #"LX", #"TX",nil];
NSMutableArray *Arr3 = [[NSMutableArray alloc]initWithObjects:#"C300", #"C550",nil];
NSMutableArray * Models = [[NSMutableArray alloc] initWithObjects:Arr1,Arr2,Arr3,nil];
On delete if you delete BMW then remove 1st element from Models array and and 1st element from Cars array and reload table.
i.e.
[Cars removeObjectAtIndex:0];
[Models removeObjectAtIndex:0];
[tableview reload]; //tableview - object of UiTableView
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
int row = indexPath.row;
if(indexPath.section ==0) {
// Need to remove both the Car and the Models associated with it.
// Begin updates. Doesn't commit edits till endUpdates;
[tableView beginUpdates];
// Get the indexPaths to be removed.
// Cars is straight forward.
NSMutableArray *carsIndexPath = [[NSMutableArray alloc] init];
NSIndexPath *carsIndexPathObj = [NSIndexPath indexPathForRow:indexPath.row inSection:0];
[carsIndexPath addObject:carsIndexPathObj];
// Manually make index paths for models associated with the car.
NSMutableArray *modelIndexPaths = [self getIndexPaths:indexPath.row];
// Now remove from model
[models removeObjectAtIndex:indexPath.row];
[cars removeObjectAtIndex:indexPath.row];
// Remove from Table
[tableView deleteRowsAtIndexPaths:carsIndexPaths withRowAnimation:UITableViewRowAnimationLeft];
[tableView deleteRowsAtIndexPaths:modelIndexPaths withRowAnimation:UITableViewRowAnimationLeft];
// Commit updates
[tableView endUpdates];
// Reload data.
[tableView reloadData];
}
}
-(NSMutableArray *) getIndexPaths:(NSInteger) index {
NSMutableArray *indexPathArray = [[NSMutableArray alloc] init];
int offset = 0;
for (int i=0; i<index; i++) {
NSMutableArray *tempArr = [models objectAtIndex:i];
offset += [tempArr count];
}
NSMutableArray *currentModels = [models objectAtIndex:index];
for (int i=0; i<[currentModels count]; i++) {
NSIndexPath *indexPathTemp = [NSIndexPath indexPathForRow:offset+i inSection:1];
[indexPathArray addObject:indexPathTemp];
}
return indexPathArray;
}
(If this makes any sense at all)
My iPhone application has a UITable View implemented with search functionality in it. The values in the table are grouped into sections from A-Z. Whenever a user tap on particular cell in the table it loads a detail view controller which gives all the values of that particular user. Now my problem is whenever I search some contact and tap on a particular user to check his detail view it always returns a contact starting with letter A. So, my doubt is how to implement this search functionality. Is there a way to get the name of the contact I tapped..Please check this screenshot.. For example if I search some contact starting with letter 'B' and tap on that contact it loads the detail view of a contact starting with letter 'A'. I get all the values from the database. Can you please help me out...
This is the code:
The code I wrote here is in a method:
I am getting all the contacts from database and assigning to an array contacts. Then I am grouping all the contacts according to the alphabets and grouping everything into a dictionary with keys as A-Z and values as name of contacts starting with these letters. Now when I search for a particular contact his name may start with either A ,B or Z..so in the search bar when I search for a particular contact for example a contact starting with letter Z, in this case it gives the details of a person with A. I want this to change so that whenever I tap on a particular contact it should load its details. I am unable to figure out how to do it..
contacts = [[db getContacts:#"Contacts"] componentsSeparatedByString:#","];
[db cleanup];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
NSString *charString;
for (int i=65; i<91; i++) {
charString = [NSString stringWithFormat:#"%c",(char *)i];
[tempArray addObject:charString];
}
[charString release];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for (int i=0; i<[tempArray count]; i++) {
NSMutableArray *contactsByIndex = [[[NSMutableArray alloc] init]autorelease];
NSString *tempChar = [tempArray objectAtIndex:i];
for (int j=0; j<[contacts count]-1; j++)
{
NSString *test = [contacts objectAtIndex:j];
NSString *tempString = [test substringToIndex:1];
if ([tempString isEqualToString:tempChar]) {
[contactsByIndex addObject:[contacts objectAtIndex:j]];
}
}
[dict setObject:contactsByIndex forKey:[tempArray objectAtIndex:i]];
}
self.contactNames = dict;
NSArray *array = [[contactNames allKeys] sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
self.contactKeys = array;
[dict release];
[tempArray release];
//---display the searchbar---
self.tableView.tableHeaderView = searchBar;
searchBar.autocorrectionType = UITextAutocorrectionTypeYes;
listOfContacts = [[NSMutableArray alloc] init];
for (NSString *key in array)
{
NSArray *contactsArray = [contactNames objectForKey:key];
for (NSString *name in contactsArray) {
[listOfContacts addObject:name];
}
}
- (void) searchContactsTableView {
//---clears the search result---
[searchResult removeAllObjects];
for (NSString *str in listOfContacts) {
NSRange titleResultsRange = [str rangeOfString:searchBar.text options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
[searchResult addObject:str];
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.
NSString *selectedRow=nil;
if (isSearchOn) {
selectedRow=[searchResult objectAtIndex:indexPath.row];
}
DetailViewController *detailViewController;
int section_index=[indexPath indexAtPosition:[indexPath length]-2];
int sugarid_Index = [indexPath indexAtPosition: [indexPath length]-1];
NSString* sectionName=[contactKeys objectAtIndex:section_index];
NSLog(#"%#",sectionName);
//This is a method which gets the details of a particular contact based on the section and the row selected..Contacts is the table name
NSString *getContact=[db getId:#"Contacts" bySection:sectionName andIndex:sugarid_Index];
id=[db getContact:#"Contacts" id:getContact];
// Pass the selected object to the new view controller.
detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
detailViewController.eachContact=contactForSugarId;
[self.navigationController pushViewController:detailViewController animated:YES];
}
When I search for a contact it should search for the name in database and should return its details. Is there a way to do it..please let me know or is there a way to get the name of the cell i.e. the contact name so that I can use that in one of my database methods to retrieve the details of the contact I selected.
Off hand it sounds like you're looking in the wrong array of contacts after the search. You need to have two arrays. One with all the contacts, and one with the filtered contacts. When you search, put all the results in order in the filtered list, and pull the details from that one.
Does this make sense?
If not, try posting a bit of code, and explaining your structure.
In iPhone native Phone book - there is a search character at the top & # character at the bottom.
I want to add both of that character in my table Index.
Currently I have implemented following code.
atoz=[[NSMutableArray alloc] init];
for(int i=0;i<26;i++){
[atoz addObject:[NSString stringWithFormat:#"%c",i+65]];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{
return atoz;
}
How to have # character & search symbol in my UITableView?
The best way to tackle this is to make use of the tools the framework provides. In this case, you want to use UILocalizedIndexedCollation (developer link).
I also have a decorator for this class that is designed to insert the {{search}} icon for you and handle the offsets. It is a like-for-like drop-in replacement for UILocalizedIndexedCollation.
I've posted a more in-depth description of how to use this on my blog. The decorator is available here (Gist).
The basic idea is to group your collection into an array of arrays, with each array representing a section. You can use UILocalizedIndexedCollation (or my replacement) to do this. Here's a small NSArray category method I use to do this:
#implementation NSArray (Indexing)
- (NSArray *)indexUsingCollation:(UILocalizedIndexedCollation *)collation withSelector:(SEL)selector;
{
NSMutableArray *indexedCollection;
NSInteger index, sectionTitlesCount = [[collation sectionTitles] count];
indexedCollection = [[NSMutableArray alloc] initWithCapacity:sectionTitlesCount];
for (index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *array = [[NSMutableArray alloc] init];
[indexedCollection addObject:array];
[array release];
}
// Segregate the data into the appropriate section
for (id object in self) {
NSInteger sectionNumber = [collation sectionForObject:object collationStringSelector:selector];
[[indexedCollection objectAtIndex:sectionNumber] addObject:object];
}
// Now that all the data's in place, each section array needs to be sorted.
for (index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *arrayForSection = [indexedCollection objectAtIndex:index];
NSArray *sortedArray = [collation sortedArrayFromArray:arrayForSection collationStringSelector:selector];
[indexedCollection replaceObjectAtIndex:index withObject:sortedArray];
}
NSArray *immutableCollection = [indexedCollection copy];
[indexedCollection release];
return [immutableCollection autorelease];
}
#end
So, given an array of objects, for example books that I want to divide into sections based on their name (the Book class has a name method), I would do this:
NSArray *books = [self getBooks]; // etc...
UILocalizedIndexedCollation *collation = [UILocalizedIndexedCollation currentCollation];
NSArray *indexedBooks = [books indexUsingCollation:collation withSelector:#selector(name)];