Populating UITableView cells - iphone

Ok so I have wrote some code in this function:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"tableviwcell is getting called");
properties = [NSUserDefaults standardUserDefaults];
NSDictionary *events_dict = [properties objectForKey:#"events_dict"];
NSDictionary *events = [events_dict objectForKey:#"event"];
am_participants = [events objectForKey:#"amParticipants"];
pm_participants = [events objectForKey:#"pmParticipants"];
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"currentCell"];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"currentCell"];
}
int sizeofam = [am_participants count];
int sizeofpm = [pm_participants count];
NSMutableArray *participants =[[NSMutableArray alloc] init];
NSLog(#"size of am: %i", sizeofam);
if(sizeofam > 0 && sizeofpm > 0){
for(int i = 0; i < sizeofam; i++){
NSDictionary *ampart_dict = [am_participants objectAtIndex:i];
NSString *ampart_email = [ampart_dict objectForKey:#"email"];
NSString *ampart_email_extra = [#"am" stringByAppendingString:ampart_email];
[participants addObject:ampart_dict];
}
for(int i = 0; i < sizeofpm; i++){
NSDictionary *pmpart_dict = [pm_participants objectAtIndex:i];
NSString *pmpart_email = [pmpart_dict objectForKey:#"email"];
NSString *pmpart_email_extra = [#"pm" stringByAppendingString:pmpart_email];
[participants addObject:pmpart_dict];
NSLog(#"%#", participants);
}
int sizeofparticipants = [participants count];
for(int i = 0; i < sizeofparticipants; i++){
NSString *participanti = [[participants objectAtIndex:i] objectForKey:#"email"];
for(int j = 0; j < sizeofparticipants; j++){
NSString *participantj = [[participants objectAtIndex:j] objectForKey:#"email"];
if([participanti isEqualToString:participantj]){
NSLog(#"Participant j: %#", participantj);
[participants removeObjectAtIndex:j];
sizeofparticipants = [participants count];
}
}
}
Basically I need to merge together the two arrays am_participants and pm_participants in to one array of participants. Each object in the array is a dictionary full of various values such as name, email etc. I then have to remove any duplicate values from the list (for example if someone is in the am list and pm list. I am doing that by removing values if their email address is the same in either list.
After this I need to display the new array of participants called 'participants' in one list by populating the cells with the list of participants.
I have set the number of cells to 30.
However The cells get populated with different names randomly when scrolling down the list as thought the array positions are being moved around aswell as duplicate values appearing.
Can someone explain what I am doing wrong?
Thanks!

the cell assignment code is not mentioned above but i assume that you are assigning values from participants as your cell's content as explained. The problem is you are creating your array inside cellForRowAtIndexPath:. This method gets called every time a new cell is to be displayed, thus, you are recreating your participants for every row. You need to move the code you have above to viewDidLoad or viewDidAppear.

Related

Sort NSArray with NSPredicate then store in a new array

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.

NSMutableArray insertObject at random indexes

I have a NSDictionary that contains objects and keys. The Keys hold a Name and number. I would like to insert those objects into a NSMutableArray by using insertObject: atIndex: . Object being the name and the number is the index I would like to place the object in. I now know that NSMutableArrays are able to insert objects at index:6 if there is no 1-5 so how do I make this possible? Any suggestions are very appreciated!
Example Dictionary [dict objectForKey:#"array"]:
preferences as whole (
{
Name = PowerDown;
btnIndex = 3;
},
{
Name = ClearCache;
btnIndex = 5;
},
{
Name = KillBGApps;
btnIndex = 6;
},
{
Name = InfoPanel;
btnIndex = 2;
},
{
Name = Lock;
btnIndex = 4;
},
{
Name = Reboot;
btnIndex = 0;
},
{
Name = Respring;
btnIndex = 1;
}
)
What I have so far but crashes when adding objects out of bounds of the array
-(void)loadArray{
self.buttons = [NSMutableArray array];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
tempArray = [buttonsPrefs objectForKey:#"buttonsToOrder"];
for(NSDictionary * dict in tempArray)
{
if (dict) {
NSString *btnName = [dict objectForKey:#"Name"];
NSString *btnIndex = [dict objectForKey:#"btnIndex"];
NSUInteger index = [btnIndex integerValue];
NSLog(#"Name = %#",btnName);
NSLog(#"at index %i",index);
[self.buttons insertObject: btnName atIndex: index];
}
}
}
EDIT: These values "indexes" for the names with change when a user moves the cell
- (void) tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath
*)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
NSUInteger fromIndex = [fromIndexPath row];
NSUInteger toIndex = [toIndexPath row];
if (fromIndex == toIndex)
return;
NSMutableDictionary *selectedButton = [[[_buttons objectAtIndex:fromIndex] retain]
autorelease];
[_buttons removeObjectAtIndex:fromIndex];
[_buttons insertObject:selectedButton atIndex:toIndex];
//[buttonsPrefs setObject:_buttons forKey:#"buttonsToOrder"];
//[buttonsPrefs writeToFile:[self getFilePath] atomically: YES];
}
Try to fill your target array with some dummy data according to yourDict count like this:
for (int i=0, i<[yourDict count], ++i){
[yourArray addObject:#"dummyData"];
}
And when you will need to insertObject do this:
for(NSDictionary * dict in tempArray)
{
if (dict) {
NSString *btnName = [dict objectForKey:#"Name"];
NSString *btnIndex = [dict objectForKey:#"btnIndex"];
NSUInteger index = [btnIndex integerValue];
[yourArray insertObject:btnName atIndex:index];
[yourArray removeObjectAtIndex:index+1];
}
}
NSMutableArray insertObject: atIndex:
as per apple docs `
"Note that NSArray objects are not like C arrays. That is, even though
you specify a size when you create an array, the specified size is
regarded as a “hint”; the actual size of the array is still 0. This
means that you cannot insert an object at an index greater than the
current count of an array."
Can only fill within valid array value set.Two things you can do.
Sort and fill the array
Fill the array with some default object like a string(cannot be nil) and then replace it.This option is valid if you are filling all the values in array because when used later you have to check weather the value is right there or the default value is in that position

Objective-C - unidentified Error in for Loop

the following code attempts to search for a String given by a cell.textlabel.text in a CSV-File
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//create singleton instance
Globals *myGlobals = [Globals sharedGlobals];
//get searchstring form cell
NSString *stringToFind = [self.tableView cellForRowAtIndexPath:indexPath].textLabel.text;
//get Path of csv and write data in string:allLines
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"ITILcsv" ofType:#"txt"];
if(filePath){
NSString *wholeCSV = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSArray *allLines = [wholeCSV componentsSeparatedByString:#"\n"];
//declaration
NSArray *currentArray = nil;
NSString *currentSearchString = nil;
//look for searchstring in 4th line of csv, if found write whole line to a singleton-variable
for (int i=0 ; i < [allLines count]; i++){
currentArray = [[allLines objectAtIndex:i] componentsSeparatedByString:#";"];
currentSearchString = [currentArray objectAtIndex:3];
if ([stringToFind isEqualToString:currentSearchString]){
[myGlobals setCurrentLine:currentArray];
}
}
}
Working quite a bit with csv-files in my current project I'm pretty sure this should work, but somehow the app always crashes when the function is called.
Through a whole bunch of testing I'm pretty sure that the problem is in the following lines:
currentArray = [[allLines objectAtIndex:i] componentsSeparatedByString:#";"];
currentSearchString = [currentArray objectAtIndex:3];
The program works with these two lines commented out, but doesnt implement the desired function ;)
I have no clue what the problem might be?
The Error is a SIGABRT in "main".
Thanks in advance everybody.
Might crash when your currentArray has elements less than 3 and you are referring index 3. So in that case your finding for an index which is out of reach.
So better approach would be
for (int i=0 ; i < [allLines count]; i++)
{
currentArray = [[allLines objectAtIndex:i] componentsSeparatedByString:#";"];
// check and then pick
if ([currentArray count] > 3)
{
currentSearchString = [currentArray objectAtIndex:3];
if ([stringToFind isEqualToString:currentSearchString])
{
[myGlobals setCurrentLine:currentArray];
}
}
}

Deleting multiple (not yet loaded) rows in UITableView

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)

Filter a NSMutableArray index beyond bounds Problem

I am trying to filter a NSMutableArray. Search array for items by certain country. I have tried NSpredicate which works great however I need to re-use the original array which I cannot with NSpredicate. So I am trying the below code.
Q. What is the best way to filter an NSMutableArray keeping the original array intact?
//The following code works
filteredArray = [[NSMutableArray alloc] init];
unsigned int i;
for (i = 0; i < [appDelegate.arrayToBeFiltered count]; i++) {
id session = [appDelegate.ads objectAtIndex: i];
id Country = [[appDelegate.arrayToBeFiltered objectAtIndex: i] TheCountry];
[filteredArray addObject: session];
However when I add the if statement as below I get index beyond bounds
filteredArray = [[NSMutableArray alloc] init];
unsigned int i;
for (i = 0; i < [appDelegate.arrayToBeFiltered count]; i++) {
id session = [appDelegate.ads objectAtIndex: i];
id Country = [[appDelegate.arrayToBeFiltered objectAtIndex: i] TheCountry];
if (Country == #"United States"){
[filteredArray addObject: session];
}
}
Use - (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate
As a side-note, in the code above you probably mean to do this [Country isEqualToString: #"United States"]
As an extra side note - don't capitalise variables and method names. Just a style thing but capitalisation is usually reserved for Class names