NSMutableArray - Add array at start - ios

It is a simple pull to refresh case. I have data loaded into table and have a mutable data array at back-end, I receive a array of new data and want to add this complete array at start of existing array.
One workaround is to create new array with new arrived data and then add previous array into it using addObjectsFromArray: method. Is there some workaround to add new data array to the start of previous array directly?

First, build an NSIndexSet.
NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:
NSMakeRange(0,[newArray count])];
Now, make use of NSMutableArray's insertObjects:atIndexes:.
[oldArray insertObjects:newArray atIndexes:indexes];
Alternatively, there's this approach:
oldArray = [[newArray arrayByAddingObjectsFromArray:oldArray] mutableCopy];

NSMutableArray offers the insertObjects:atIndexes: method, but it's easier to append the way you suggest using addObjectsFromArray:.

-insertObject:atIndexes: is easy enough, and should (I believe) be more efficient than using -addObjects and swapping arrays. It'd probably end up looking something like this:
[existingResults addObjects:newResults atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, newResults.count)]]`

Creating a new array is probably your best solution, but you can also use a loop
NSUInteger index;
index = 0;
for ( id item in sourceArray )
{
[destArray insertObject:item atIndex:index];
index++;
}

Just simple way:
NSMutableArray *arrayTmp = [firstArr addObjectsFromArray:myArray];
myArray = arrayTmp;

Related

NSMutableArray Allocate then replaceObjectAtIndex

I have a NSMutableArray that i define in the header file as:
#property (strong, nonatomic) NSMutableArray *tempPhotosArray;
Then i allocate as:
_tempPhotosArray = [[NSMutableArray alloc] init];
What i'd like to know is if i then go to replaceObjectAtIndex the program will complain on an out of bounds. I want to keep only a set number of items in that array, so is it possible to do a insert or replace? i.e. if at index 0 it is empty do an insert, if there is an object already replace it?
Thanks
i think i agree with Hani Ibrahim. Since you said you only want to keep a set number of objects in the array. So how many you want?
// add these code when you initialize the array
int aSetNumber = 5;
_tempPhotosArray = [[NSMutableArray alloc] init];
for (int i = 0; i < aSetNumber; i++)
{
[_tempPhotosArray addobject: [NSNull null]];
}
i guess then you can do whatever you want, i don't know what exactly you want to do in this case, but i would check if the object in that position is NSNUll, if so, replace that, if not, i don't know what you want them
//use these code when you trying to insert the real object
if([[_tempPhotoArray objectAtIndex:anIndex] isKindOfClass: [NSNull class]])
{
//replace it here
}
As to why you are getting an error, what everyone else wrote is accurate, but....
The description of what you want doesn't match what an NSArray is. It sounds like you want a list of up to 5 items and never more than 5. It might be that if you try to add a 6th item the "oldest" goes away. Like a "recently opened" file history. You can make this type of functionality with an NSArray, but that's not what it is out of the box.
I would suggest making your own object class. I'm not going to write all the code for you, because this sounds suspiciously like programming homework, but I will point you in the correct direction.
FivePack <-- our class
NSArray *storage; <-- where we house the data
// a public method which lets you add things.
- (void)addItem:(id)item {
int indexOfLastItemInArrayToSave = 4;
if (storage.length < 4)
indexOfLastItemInArrayToSave = length-1;
NSRange range = NSMakeRange(0, indexOfLastItemInArrayToSave);
NSArray *temp = [storage subArrayWithRange:range];
// now create a new array with the first item being "item" that
// was passed in and the rest of the array being the contents of temp.
// Then save that to storage.
}
What you want to do with the data and writing something to get it from your new object is up to you, because I'm not sure how you want to do it.
There are no objects in the array when you initially created it, so there is nothing to replace.
Like this?
if([_tempPhotosArray count] > 0)
//replace object
else
//add object to array

KVO on removeAllObjects Triggers NSKeyValueChangeRemoval for each Item Separately

I'm watching an NSArray property with KVO. I've implemented KVC like in this post and I also implemented most of the KVC array accessors. To mutate it, I use mutableArrayValueForKey. It works fine, except to 2 issues:
When I call removeAllObjects, I get a NSKeyValueChangeRemoval change for each single removed item. I'd like to receive only one NSKeyValueChangeRemoval notification with all removed indexes in it.
Similarly when I call addObjectsFromArray:, I get NSKeyValueChangeInsertion for each single added item. I'd like to receive only one NSKeyValueChangeInsertion notification with all added indexes in it.
Notice that I do have implemented the KVC methods remove<Key>ItemsAtIndexes: and insert<Key>Items:atIndexes:. They are not called though.
I use the following workarounds:
- (void)removeAllObjectsWorkaroundFromArray:(NSMutableArray *)modelArray {
NSRange indexRange;
indexRange.length = modelArray.count;
indexRange.location = 0;
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:indexRange];
[modelArray removeObjectsAtIndexes:indexSet];
}
- (void)addObjectsFromArrayWorkaroundWithArray:(NSMutableArray *)modelArray arrayToAdd:(NSArray *)arrayToAdd {
NSRange indexRange;
indexRange.length = arrayToAdd.count;
indexRange.location = modelArray.count;
NSIndexSet *indexSet = [[NSIndexSet alloc] initWithIndexesInRange:indexRange];
[modelArray insertObjects:arrayToAdd atIndexes:indexSet];
}
Is there a way to directly use removeAllObjects and addObjectsFromArray: without the need for the above workarounds?
As I am sure you are aware one cannot observe the array itself, just attributes of it. So I think your workaround is unavoidable.
That being said - I really like the way you solved this!

How to remove object at all index except first index in NSMutableArray IOS

I have 1 mutablearray, i want to remove object all indexs but hold object at first index.
EXample : Input : Array (a,b,c,d,e)
Output: Array (a)
Can you help me. Thanks in advance
NSMutableArray *testArray=[[NSMutableArray alloc] initWithObjects:#"A",#"B",#"C", nil];
[testArray removeObjectsInRange:NSMakeRange(1, testArray.count-1)];
But please make sure array count is greater than 1.
Try this one and put your range to remove your object.
[array removeObjectsInRange:NSMakeRange(1, array.count-1)];
Keep a reference to your a object (MyObject temp = [array objectAtIndex:0]), do removeAllObjects, then insertObject:a

passing data to viewcontrollers

I have a mutable array of values used in a tableviewcontroller, a mapviewcontroller, and the callingviewcontroller. I have been updating them all, ie.
[dataArray addObject:object atIndex:0];
[tvc. dataArray addObject:object atIndex:0];
[mvc. dataArray addObject:object atIndex:0];
Is there a way of declaring dataArray in the table and map viewcontrollers that would make them pointers to the dataArray in the callingViewController? So I would just have to update one?
***Okay guys, I made a really stupid mistake here. At some point I changed the initialization and passed nil as the dataArray, and for some reason I had an "if (!dataArray) create new" clause to hide it from myself.
Kaan is correct.
[dataArray addObject:object atIndex:0];
is all that is needed.
This is a little more involved but I think would be the best solution. You should have some way for all of these different ViewControllers to reference a single object that is managing your data. This could be a delegate, or it could be a singleton that owns the main dataArray.
Search here or on google for both of those terms and you should be able to get started with either route.
After your comment:
How about you declare a property called dataArray in both your tableView and mapView and also callingView. Then, in your callingViewController, you initialize a mutable array called lets say myFirstArray and do:
NSMutableArray *myFirstArray = [NSMutableArray array];
self.dataArray = myFirstArray;
myTableView.dataArray = myFirstArray;
myMapView.dataArray = myFirstArray;
This way they will both be pointing to the same object and change you do in one will reflect in the other. Give it a try!
if you create the array in the AppDelegate class then you can access from any other classes within your app.

What's the Best Practice for Implementing Multi-section TableView

All,
I have about 3000 words with definitions that I am loading into a TableView. Right now, it's just a sorted list of words, sans the sections because I haven't added them yet.
I need to add sections to my TableView data (A,B,C ...) and there seems to be several ways to do this so before I jump into this I am looking for some confirmation or correction if I am going down the wrong rabbit hole.
Currently the data that the TableView reads is stored as objects in an NSMutableArray per this code:
//AppDelegate.m
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
//...
NSMutableArray *wordArray = [[NSMutableArray alloc] init];
//Loop through result set from DB and populate objects
while([rs next]){
[wordArray addObject:[Word wordWith:[rs stringForColumn:#"word"]
Definition:[rs stringForColumn:#"definition"]
SectionIndex:[rs stringForColumn:#"sectionIndex"]]];
}
MainViewController *mainViewController =
[[MainViewController alloc] initWithNibName:#"MainView" bundle:nil];
mainViewController.listContent = wordArray;
//...
}
Each object has a section index value ([A-Z0-9]) so I already know which section each word goes in, I know what the sections need to be and I can easily derive a count of objects for each section. All the words have been sorted via SQL before the NSMutableArray was populated so that's already handled.
Can I create multiple sections with the one NSMutableArray or do I need to do something different?
Thanks
You could store your words into arrays inside a NSDictionary holding keys for each letter.
Number of sections would return
[[dictionary allKeys] count];
Title for section
NSArray * keys = [dictionary allKeys];
[keys objectAtIndex:sectionIdx]
Number of rows in section would return
NSArray * keys = [dictionary allKeys];
[(NSArray *)[dictionary objectForKey:[keys objectAtIndex:sectionIdx]] count];
Each word would be
NSArray * keys = [dictionary allKeys];
[(NSArray *)[dictionary objectForKey:[keys objectAtIndex:sectionIdx]] objectAtIndex:indexPath.row];
I have found that you sometimes want to add sorting to your lists and then, another approach might be interesting. Put all your models (Word's in your example) in a dictionary with some unique value of the model as the key.
Implement a sorting method, that you run every time the underlying dictionary changes. The sorting method will use e.g. keysSortedByValueUsingComparator on the dictionary and supply a different blocks for different sort orders. Let the sorting method create section arrays and add keys in the arrays that corresponds to the keys in the dictionary.
You do not store anything twice and you get different sort orders by just providing different sort blocks (that can look at any properties of your model class).

Resources