I know how I would achieve this using NSMutableArray, but whats the correct way of emptying a whole array of class NSArray. I need to do this because I need to reload a tableView. Im using ARC.
NSArray is an immutable type. You cannot alter it's contents after creation.
Either use an NSMutableArray or replace it with a new (empty) NSArray.
NSArray *yourArray = [ whatever objects you have ]
//to empty this array
yourArray = [NSArray array];
NSArray is an immutable (unchangeable) class so there is no way to remove elements from the array. Basically, you will have to throw the array away and replace it with a new NSArray. Alternatively, you could just use an NSMutableArray.
You cant empty a non mutable NSArray, the best approach is to get a mutable copy of your array:
NSMutableArray *arr=[yourArr mutableCopy];
[arr removeAllObjects];
Related
I learn objective-C from Stanford iTunes and i wonder how i should copy a NSMutableArray to NSArray without initialization. I mean:
Is this is correct? with "lazy initialization".
-(void)copyAnArray:(NSMutableArray*)listOfElements {
if(privateElementsLists == nil)
privateElementsLists = [[NSArray alloc] initWithArray:listOfElements copyItems:YES];
else
privateElementsLists = listOfElements;
}
is this a bad design?
I want to addobjects to mutable array in one class, and then when i'm finish copy entire NSMutableArray to NSArray.
And another question: Why i have to use copyItems:YES when I use initWithArray? And what's deep copy?
You can copy a mutable array to a new array with initWithArray: or this way:
privateElementsLists = [NSArray arrayWithArray:listOfElements];
then you are creating a new array where each of its elements is the same object that figures in the original array. If you write:
privateElementsLists = [NSArray arrayWithArray:listOfElements copyItems:YES];
then the new array have, for each element, a copy of the element in original array. They are not the same object but a copy. Of course, that objects have to be able to respond to copy.
You can even do this:
privateElementsLists = (NSArray*) listOfElements ;
Then the array is exactly the same as the original one. No new array here. But as you have casted it with NSArray pointer class, you can use it as if it is a NSArray instead of a NSMutableArray. As you know, every NSMutableArray is a NSArray (inherited class).
As Joseph DeCarlo stated, you don't need to copy NSMutableArray to NSArray if the only thing you do is to create the array in one place to use it somewhere else. For example this statement is valid:
NSArray* newArray = [NSMutableArray array];
Or in the code:
-(NSArray*)returnAnArray
{
NSMutableArray* editableArray = [NSMutableArray array];
[editableArray addObject:[[NSObject alloc] init]]; //an exemplary object added to the array
return editableArray;
}
That said, however, in some specific cases casting NSMutableArray to NSArray may not be safe, e.g. if the original array was stored in an instance variable. Adding or removing objects to/from that array may cause a crash if the returned array is enumerated at the same time. For example:
-(void)createArray
{
self->editableArray = [NSMutableArray array]; // instance variable: NSMutableArray* editableArray
}
-(void)addObjectToArray
{
[self->editableArray addObject:[[NSObject alloc] init]];
}
-(NSArray*)getArray
{
return self->editableArray;
}
-(void)enumerateArray
{
for(NSObject obj in [self getArray])
{
// do something with obj
}
}
If addObjectToArray is called at the same time as enumerateArray (e.g. from a background thread) the application will crash because the underlying array is changing while it is being enumerated. It doesn't matter that it was returned as NSArray*. In a case like this you would need to either add #synchronized to synchronize access to the same object by multiple threads, or copy the entire array with arrayWithArray: as suggested. Note, however, that the documentation doesn't say if arrayWithArray: is thread safe so I would add #synchronized around the call to arrayWithArray: anyway.
I need reverse(sort in descending order) a NSMutablearray.I tried the following code and it works,but got a warning. How could I remove the warning?
NSMutablearray *resStatusArray;
[resStatusArray sortUsingSelector:#selector(compare:)];
resStatusArray=[[resStatusArray reverseObjectEnumerator] allObjects];
Warning:Incompitable pointer types assigning to 'NSMutablearray*_strong' from ' NSarray *'
user1118321 is correct in the explanation. To fix it, you would create a new mutable array. I suspect this is safer than a cast.
resStatusArray = [NSMutableArray arrayWithArray:[[resStatusArray reverseObjectEnumerator] allObjects]];
The allObjects method returns an NSArray*, not an NSMutableArray*, so the compiler is telling you that your assignment to an NSMutableArray* variable is incorrect.
If your are sure what your are doing, you can use a cast:
resStatusArray=(NSMutableArray*_strong)[[resStatusArray reverseObjectEnumerator] allObjects];
However, I doubt that this is semantically correct.
Set it to be equal to:
[NSMutableArray arrayWithArray:[[arrayNameToReverse reverseObjectEnumerator] allObjects]];
This is essentially creating a new array, from the old mutable array, but reversed. The reason it works is because NSMutableArray is a subclass of NSArray. So, your code to reverse your array would be:
resStatusArray = [NSMutableArray arrayWithArray:[[resStatusArray reverseObjectEnumerator] allObjects]];
I have a NSMutableArray (tripHistory) that gets a NSMutableDictionary (currentUpdate) added to it every second with new data.
[currentUpdate setObject:testVariable forKey:#"Test"];
[tripHistory addObject:currentUpdate];
[currentUpdate removeAllObjects];
Yet when I loop through tripHistory calling [[tripHistory objectAtIndex:i] description] everything is null.
My loop is as follows:
for (int i=0; i<[tripHistory count]; i++)
{
NSLog(#"%#", [[tripHistory objectAtIndex:i] description]);
}
To initialize my variables, the following code is called only for the first update.
tripHistory = [[NSMutableArray alloc] init];
currentUpdate = [[NSMutableDictionary alloc] init];
Any ideas?
Adding an object to an NSArray doesn't make a copy of it. All that happens is its reference count is incremented. Therefore currentUpdate and the NSDictionary added to tripHistory are one-and-the-same. If you remove objects from currentUpdate you are also removing objects from the NSDictionary in tripHistory.
After adding currentUpdate to tripHistory all you need to do is release currentUpdate and start again with a new empty NSDictionary for the next update.
Do not remove objects. Dictionary and array are keeping references to the same objects. If you want to add another dict to array then release first dict and create a new one
You are removing all of the contents of the dictionary. Adding the dictionary to your array doesn't make a copy: The array will retain a reference to the dictionary, which you proceed to empty out each time you add something to it.
You should allocate a new dictionary each time through the loop and then add that dictionary o the array. If you are not using garbage collection or ARC you should also release the dictionary after it is added to the array.
i am wondering how its possible to add an index for a tableview to an array. i am trying to save this index to the array in order to be able to view it later. i just am interested in knowing how to save the index to the array. thanks
Use a NSMutableArray and send it an addObject: message with the NSIndexPath as an argument.
Same way you save anything to an array:
NSMutableArray *myArray = [NSMutableArray array];
[myArray addObject:myIndexPath];
I need to copy the contents of an NSArray to NSMutable array. In other words, I want to copy arrayCountryChoices to arraySearchResults. Any ideas????
//main data
NSArray *arrayCountryChoices;
//search results buffer
NSMutableArray *arraySearchResults;
//create data
arrayCountryChoices = [[NSArray alloc] initWithObjects:#"foo",#"bar",#"baz",nil];
//copy the original array to searchable array ->> THIS IS NOT WORKING AS EXPECTED
arraySearchResults = [[NSMutableArray alloc] arrayWithArray:arrayCountryChoices];
Thanks in advance.
it's either
[NSMutableArray arrayWithArray:anArray];
or
[[NSMutableArray alloc] initWithArray:anArray];
or
[anArray mutableCopy];
The code in your example doesn't work because you're calling arrayWithArray on an instance of NSMutableArray, but arrayWithArray is a class method.
As a general rule, initalization methods that start with init are instance methods, and those that start with the name of the class (array, etc.) are class methods. Class methods return autoreleased objects, while instance methods return retained objects.
You can also create empty mutable array and add objects to it using -addObjectsFromArray method
Please note that when using:
[NSMutableArray arrayWithArray:anArray];
or
[[NSMutableArray alloc] initWithArray:anArray];
you'll always get an array even if anArray was nil, but with:
[anArray mutableCopy];
you'll get nil if anArray is nil. So if you want to be sure that you actually get an array even if it may be empty, use one the former methods.
It's not working because arrayWithArray is a class method, not an instance method.
You can do [NSMutableArray arrayWithArray:arrayCountryChoices] to do what you need.
You could just call [arrayCountryChoices mutableCopy] to return a new mutable array with the contents of arrayCountryChoices.