I have a UICollectionView that I am populating with a nested array to help me create sections in my UICollectionView. The final array that I use to populate my UICollectionView looks like this with each nested array representing a different section in my view:
Array
Array
Dictionary
txt
utc
...
Dictionary
txt
utc
...
Array
Dictionary
txt
utc
...
I want the user to be able filter the collections view based on the txt (or other elements of the dictionary) and then animate the changes in the view using - (void)insertItemsAtIndexPaths:(NSArray *)indexPaths; or - (void)deleteItemsAtIndexPaths:(NSArray *)indexPaths;.
Where I need help
I am stuck trying to create the NSArray of NSIndexSets that I need for the methods I mentioned above. It seems like indexesOfObjectsPassingTest of NSIndexSets would be involved but I can not get it to work properly and any examples I can find are typically just for a single array (How retrieve an index of an NSArray using a NSPredicate?) and I have not been able to adjust the code for my purposes.
Any code to help would be greatly appreciated. Thanks in advance.
I am able to create the NSArray by nesting for loops (which I am not that excited about doing) but it works. If you have any more efficient way to create the array please do let me know!
NSMutableArray *arrayOfIndexes = [[NSMutableArray alloc]init];
for (int i = 0; i < [finalCellData count]; i++) {
for (int ii = 0; ii < [[finalCellData objectAtIndex:i] count]; ii++) {
if (![[[[finalCellData objectAtIndex:i]objectAtIndex:ii]valueForKey:#"txt"] isEqualToString:#""]) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:ii inSection:i];
[arrayOfIndexes addObject:indexPath];
}
}
}
Related
Ok here is a challenge before me I am having trouble with:
I need to create multiple arrays in a custom object dynamically
heres the idea a student enters their assignments including class name I want to add it to an array dependent on the class name. This is dynamic so i need to create an array of arrays the main array named for the class name. This allows for unlimited number of classes.
I know how to do this with arrays pre named in my object and to load to these array. I am having trouble figuring out the dynamic creation of these array names.
Any ideas I am stuck.
Like I said, just stuck on where to go next so that it can be assigned to an array of ADP1 or ADP2 and if I add an English assignment it load into an array for English and then if I take Calculus I can add that assignment and it will create a new array to load my calculus assignments into.
solved with this:
for (int i =0; i < [classList.classesArray count]; i++)
{
NSString *classy = [classList.classesArray objectAtIndex:i];
NSMutableArray *classless = [classList.classesArray objectAtIndex:i];
classless = [[NSMutableArray alloc] initWithObjects: nil];
for (int a =0; a < [assignmentList.assignmentsArray count]; a++)
{
if ([educate containsObject:classless])
{
if (classy == [[assignmentList.assignmentsArray objectAtIndex:a] classSched])
{
Assigned *assignments = [assignmentList.assignmentsArray objectAtIndex:a];
[classless addObject: assignments];
}
}
else
{
[educate addObject:classless];
if (classy == [[assignmentList.assignmentsArray objectAtIndex:a] classSched])
{
Assigned *assignments = [assignmentList.assignmentsArray objectAtIndex:a];
[classless addObject: assignments];
}
}
}
}
It sounds like what you want is an NSDictionary. Arrays don't have names, but dictionaries can have arbitrary keys that correspond to objects, which is basically a "name" for the object (since you can ask the dictionary for an object by "name").
I am trying to make a method in which the data source for my NATableView is cleared, but I cannot figure out how to do this anywhere.
Here is the code I am using to send an array called final to my table view.
// I want to clear it here before filling it again.
for (int i = 0; i < [final count]; i++) {
[myArrayController addObject: [NSMutableDictionary dictionaryWithObjectsAndKeys:final[i], #"File Name", nil]];
}
Any help would be great!
If you are using an NSMutableArray and myArrayController is your mutable array you want to call
[myArrayController removeAllObjects];
before you enter the for-loop.
I have an issue that (I think) might have to do with scope, but I'm not sure. I'm trying to do something that I think should be simple, but I am getting a strange result, and I could truly use some advice. I would say I'm an early-objective-c programmer, but not a complete newb.
I have written a function in objective-c that I would like to use to change the key-names in a mutable array of mutable dictionary objects. So, I want to pass in a mutable array of mutable dictionary objects, and return the same mutable array with the same dictionary objects, but with some of the key-names changed. Make sense?
I have tried several log statements in this code, which seem to indicate that everything I'm doing is working, except when the for loop is finished executing (when I try to test the values in the temp array), the array appears to contain only the LAST element in the source array, repeated [source count] times. Normally, this would lead me to believe I'm not writing the new values correctly, or not reading them correctly, or even that my NSLog statements aren't showing me what I think they are. But might this be because of scope? Does the array not retain its changes outside of the for loop?
I have put a fair amount of time into this function, and I have exhausted my bag of tricks. Can anyone help out?
-(NSMutableArray *)renameKeysIn:(NSMutableArray*)source {
/*
// Pre:
// The source array is an array of dictionary items.
// This method renames some of the keys in the dictionary elements, to make sorting easier later.
// - "source" is input, method returns a mutable array
*/
// copy of the source array
NSMutableArray *temp = [source mutableCopy];
// a temporary dictionary object:
NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
// These arrays are the old field names and the new names
NSMutableArray *originalField = [NSMutableArray arrayWithObjects:#"text", #"created_at",nil];
NSMutableArray *replacedField = [NSMutableArray arrayWithObjects:#"title", #"pubDate", nil];
// loop through the whole array
for (int x =0; x<[temp count]; x++) {
// set the temp dictionary to current element
[dict setDictionary:[temp objectAtIndex:x]];
// loop through the number of keys (fields) we want to replace (created_at, text)... defined in the "originalField" array
for (int i=0; i<[originalField count]; i++)
{
// look through the NSDictionary item (fields in the key list)
// if a key name in the dictionary matches one of the ones to be replaced, then replace it with the new one
if ([dict objectForKey:[originalField objectAtIndex:i]] != nil) {
// add a new key/val pair: the new key *name*, and the old key *value*
[dict setObject:[dict objectForKey:[originalField objectAtIndex:i]]
forKey:[replacedField objectAtIndex:i]];
// remove the old key/value pair
[dict removeObjectForKey:[originalField objectAtIndex:i]];
}// end if dictionary item not null
}// end loop through keys (created_at, text)
[temp replaceObjectAtIndex:x withObject:dict];
}// end loop through array
// check array contents
for (int a=0; a<[temp count]; a++){
NSLog(#"Temp contents: ############ %#",[[temp objectAtIndex:a] objectForKey:#"pubDate"]);
}
return temp;
} // end METHOD
I think the issue is on the line with:
[dict setDictionary:[temp objectAtIndex:x]];
Since these things are almost all working in pointers (instead of copying contents), every element of your temp array will point to the dict dictionary, which is set to be whatever the latest key's dictionary is. I think setting the actual pointer will fix the issue.
dict = [temp objectAtIndex:x];
So far I have:
//read in data from CSV file and separate it into 'row' strings:
// where dataString is simply a CSV file with lines of CSV data
// 31 lines with 9 integers in each line
NSArray *containerArray = [dataString componentsSeparatedByString:#"\n"];
NSArray *rowTemp; //local variable just for my sake
NSMutableArray *tableArray;//mutable array to hold the row arrays
//For each index of containerArray:
//take the string object (string of CSV data) and then,
//create an array of strings to be added into the final tableArray
for (int i = 0; i < [containerArray count]; i++) {
rowTemp = [[containerArray objectAtIndex:i] componentsSeparatedByString:#","];
[tableArray addObject:rowTemp];
}
Then when I try the following, it returns: (null)
NSLog(#"Row 6, cell 1 is %#", [[tableArray objectAtIndex:5] objectAtIndex:0]);
Any ideas? is there a better way?
FYI this data is static and very unlikely to change. Any way to create and populate a static array rather than using a mutable array, would be much appreciated.
Thanks in advance.
I just got the answer! with some help from iPhoneSDK forums, and what I failed to do was actually create the tableArray. What I did in the code above was merely create the variable. NSMutableArray *tableArray; and did not actually create the mutable array I wanted. Instead what I should have done was: NSMutableArray *tableArray = [NSMutableArray arrayWithCapacity: [containerArray count]]; Which worked like a charm.
I have two arrays, each containing strings. The first array is a list of words, the second array contains alternatives to those words in different languages.
The arrays are matched such that the word at index n in the second array is a translation of the word at index n in the first array.
The words and their translations are displayed in a table view. The user can filter the table view by entering text in a search field. When this is done, I create a filtered array from the first array like this:
- (void)filterContentForSearchText:(NSString*)searchText
[self.filteredarray removeAllObjects];
[firstarray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
if ([obj compare:searchText options:NSCaseInsensitiveSearch range:NSMakeRange(0, [searchText length])] == NSOrderedSame)
{
idx= [firstarray indexOfObjectIdenticalTo:obj];
NSUInteger maxindex = idx + 50;
for (idx ; (idx < [firstarray count] && idx <= maxindex && idx!= NSNotFound); idx ++)
{
[self.filteredarray addObject:[firstarray objectAtIndex: idx]];
}
*stop = YES;
}
}];
Then, when I am displaying the values in my table view, I use the following code. This is an exerpt from my cellForRowAtIndexPath method. I am trying to get the index from the original array using the object that has been added to the filtered array.
contentForThisRow = [self.filteredarray objectAtIndex:row];
NSUInteger index = [self.firstarray indexOfObjectIdenticalTo:contentForThisRow];
contentForThisRow2 = [self.secondarray objectAtIndex:index];
This works on the simulator, but on the device I will sometimes get repeats of the same entry from the second array. For example, my first array contains the word "hello" three consecutive times, at indexes x, y and z. My second array contains "hei", "heisan" and "hoppsan", which are all translations of "hello", at indexes x, y and z.
On the simulator, I get three cells, each with a different translation. On the device, I get three cells, all with "hei", the first translation. This does not happen for all repeated translations.
Why is this happening, and how can I get around it?
I think the problem is that iOS (on the device) may be using a slightly different optimisation to the emulator somewhere, either in NSString or NSArray. That is a guess.
indexOfObjectIdenticalTo: returns the index of the first object that has the same memory address as the object you are passing in. On the phone it appears to have re-used the identical string objects in your first array when building the filtered array (possibly even when building firstArray), so you are getting the same index value back each time.
A better solution would be to build your filtered array as an array of dictionaries, storing the values from the correct indexes of firstArray and secondArray at that point. You can then use these values directly when populating the cell instead of searching through both arrays again. This should also have some performance benefits.
You would achieve this using the following code. First, inside your loop when you are building the filtered array, instead of adding the object from firstarray, do this:
[self.filteredArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:[firstarray objectAtIndex:idx],#"english",[secondarray objectAtIndex:idx],#"translated",nil];
Then, in your cellForRowAtIndexPath, to get your two content variables:
NSDictionary *rowData = [self.filteredarray objectAtIndex:row];
contentForThisRow = [rowData objectForKey:#"english"];
contentForThisRow2 = [rowData objectForKey:#"translated"];
An even better solution would be to hold your data like this in the first place, and not try to keep two separate arrays synchronised. I imagine if you want to add or alter anything in your two separate files you could quickly get them out of step. However, I feel I've done enough for the day...
else
contentForThisRow = [self.firstarray objectAtIndex:row];
contentForThisRow2 = [self.secondarray objectAtIndex:row];
You see anything wrong with that?