iPhone:Got warning when reverse a NSMutablearray - iphone

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]];

Related

RemoveAllObjects equivalent fror NSArray

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];

NSMutableArray automatically typecasting into NSArray

I created an NSMutableArray object by
NSMutableArray *array = [[NSMutableArray alloc]init];
and used method componentsSeperatedByString: as
array = [myString componentsSeperatedByString:#"++"];
but when I performed operation on array like,
[array removeAllObjects];
I got exception like "removeAllObjects unrecognized selector send to instance".
I solved this issue by modifying code like,
NSArray *components = [myString componentsSeperatedByString:#"++"];
array = [NSMutableArray arrayWithArray:components];
and I after that could perform operation like
[array removeAllObjects];
My doubt is why did NSMutableArray automaticaqlly converted to NSArray? How Can I avoid automatic type conversion like this, to prevent exceptions? Thanks in advance....
There is a mistake in your understanding of how Objective-C works. This line:
NSMutableArray *array = [[NSMutableArray alloc]init];
allocates and initializes the array, and the pointer array points to this object. Now, this line:
array = [myString componentsSeperatedByString:#"++"];
makes the array pointer to point to the new array returned by componentsSeparatedByString method. You loose the reference to your alloced and inited mutable array when you do this, and you create the memory leak if you don't use ARC.
This is happening because [myString componentsSeperatedByString:#"++"] returns an NSArray. You can try something like this:
array = [[myString componentsSeperatedByString:#"++"] mutableCopy];
or
array = [NSMutableArray arrayWithArray:[myString componentsSeperatedByString:#"++"]];
This is because – componentsSeparatedByString: returns a NSArray: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/occ/instm/NSString/componentsSeparatedByString:
Do something like:
array = [NSMutableArray arrayWithArray:[myString componentsSeperatedByString:#"++"]];
On the line
array = [myString componentsSeperatedByString:#"++"];
you are replacing the NSMutableArray you allocated with a new NSArray (and leaking your NSMutableArray. Try using this:
NSMutableArray *array = [NSMutableArray arrayWithArray:[myString componentsSeperatedByString:#"++"]];
It's not converted, the array pointer could be UIButton* if you write something like
array = [self likeThatButton];
where likeThatButton is your method returning UIButton*. As always in objective c, NSMutableArray *array means only the Xcode will try to analyze your code and suggest convenient warnings and code completion.
An NSMutableArray instance won't be converted automatically.
The method componentsSeperatedByString returns an NSArray-Object. You should get a compiler warning when assigning the return-value to a NSMutableArray-Pointer.

NSMutableArray is deleting all object with same string

I am using one NSMutableArray with same string object.
Here is the code
NSMutableArray *arr = [[NSMutableArray alloc]initWithObjects:#"hello",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",nil];
NSObject *obj = [arr objectAtIndex:2];
[arr removeObject:obj];
NSLog(#"%#",arr);
When i try to remove 3rd object of array, its removing all object with "hi" string.
I am not getting why its happening.
my doubt is while removing object, NSMutableArray match string or address.
It's because you're using removeObject which removes all objects that are "equal" to the one you pass in. As per this Apple documentation:
This method uses indexOfObject: to locate matches and then removes
them by using removeObjectAtIndex:. Thus, matches are determined on
the basis of an object’s response to the isEqual: message. If the
array does not contain anObject, the method has no effect (although it
does incur the overhead of searching the contents).
You're seeing the effects of literal strings here where each of those #"hi" objects will turn out to be the same object just added many times.
What you really want to do is this:
NSMutableArray *arr = [[NSMutableArray alloc]initWithObjects:#"hello",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",nil];
[arr removeObjectAtIndex:2];
NSLog(#"%#",arr);
Then you're specifically removing the object at index 2.
According to https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html
removeObject:
Removes all occurrences in the array of a given object.
which is exactly the behaviour you're seeing. If you want to remove the object at a particular position, you want removeObjectAtIndex:.
NSMutableArray *arr = [[NSMutableArray alloc]initWithObjects:#"hello",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",nil];
NSUInteger obj = [arr indexOfObject:#"hi"]; //Returns the lowest integer of the specified object
[arr removeObjectAtIndex:obj]; //removes the object from the array
NSLog(#"%#",arr);

Adding string to an array

i wanted to know how to add strings into an array.
I used the following methods but it is showing null.
1) [arrData addObject:[NSString stringWithString:strlast]];
2) [arrData addObject:strlast];
Thanks in advance
You can't add anything to an NSArray once it's created. You need to use an NSMutableArray if you want to make changes to it.
Update: You may actually have two problems.
Using an NSArray instead of an NSMutableArray when mutability is needed.
Not initializing the array object (either kind). If arrData is nil, you can happily send as many messages as you want to nil. Nothing will happen.
If it is showing null (nil) you need to make sure you set arrData somewhere in your code before trying to addObject:.
arrData = [[NSMutableArray alloc] init];
Also strlast is a string so use your second example, the first example is pointless.
[arrData addObject:strlast];
Did you allocate an array and assign it to arrData?
Try:
NSMutableArray *arrData = [NSMutableArray array];
NSString *string = #"My string";
[arrData addObject:string];
NSLog(#"%#", [arrData objectAtIndex:0]); //logs "My string"
If you're using a non-mutable array, you can also use arrayByAddingObject:
arrData = [arrData arrayByAddingObject: strlast];
but a mutable array is probably a better idea.

NSMutableArray when using arrayWithArray the mutable array becomes the right size, but the object are all out of scope

NSArray * ComicArray = [TCSDataBase fetchManagedObjectsForEntity:#"ComicDB" withPredicate:nil];
[ComicArray retain];
arrayOfComics = [NSMutableArray arrayWithArray:ComicArray];
[[arrayOfComics valueForKey:#"Name"] sortUsingSelector:#selector(caseInsensitiveCompare:)];
[ComicArray release];
Why are all the object in the arrayOfComics out of scope?
EDIT: I tried doing this:
NSArray * ComicArray = [TCSDataBase fetchManagedObjectsForEntity:#"ComicDB" withPredicate:predicate];
arrayOfComics =[[NSMutableArray alloc] init];
for (int i = 0; i < [ComicArray count]; i++) {
[arrayOfComics addObject:[ComicArray objectAtIndex:i]];
}
[[arrayOfComics valueForKey:#"Name"] sortUsingSelector:#selector(caseInsensitiveCompare:)];
All the objects in arrayOfComics are still out of scope....
EDIT: This works, the objects in arrayOfComicsTest are NOT "out of scope". I am not sure why this works yet when i do arrayOfComics they are out of scope. arrayOfComics is a class variable NSMutableArray * arrayOfComics in the .h. It is not used anywhere until this point.
NSMutableArray * arrayOfComicsTest = [NSMutableArray arrayWithArray:ComicArray];
NSArray *comicArray = [TCSDataBase fetchManagedObjectsForEntity:#"ComicDB" withPredicate:nil];
NSArray *sortedComicNamesArray = [[comicArray valueForKey:#"Name"] sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
Note that the latter array only has the names of the comics sorted. It does not contain a sorted list of your comics.
BTW, if you want a sorted list for your comics (not just the names) simply create the proper predicate to use in the -fetchManagedObjectsForEntity:withPredicate: method.
Try this....still i m not getting why u r not using executeFetchRequest
NSArray * ComicArray = [TCSDataBase fetchManagedObjectsForEntity:#"ComicDB" withPredicate:nil];
[ComicArray retain];
arrayOfComics = [NSMutableArray arrayWithArray:ComicArray];
[[arrayOfComics valueForKey:#"Name"] sortedUsingSelector:#selector(caseInsensitiveCompare:)];
You have to retain your array "arrayOfComics". Put a break point in your code and immediately when it is created, all the objects will be available. But if you want to use that array in some other method, all the objects go out of scope as you are not retaining.
Else it will have the scope upto the method in which it is assigned.
After correction, your code must look like:
NSArray * ComicArray = [TCSDataBase fetchManagedObjectsForEntity:#"ComicDB" withPredicate:nil];
[ComicArray retain];
arrayOfComics = [NSMutableArray arrayWithArray:ComicArray];
[arrayOfComics retain];
[[arrayOfComics valueForKey:#"Name"] sortUsingSelector:#selector(caseInsensitiveCompare:)];
[ComicArray release];
Please note that if you want to reassign arrayOfComics, you have to release and then assign.
When you say the objects are "out of scope" I presume you mean you can't see them in the debugger. If this is the case, stop worrying about it as it happens quite a lot, it's just an implementation feature. In particular, core data doesn't always fetch an actual object till it's needed (read about faulting in the Core Data Programming Guide). If you right click on the array in the debugger display and select "print description to console", it'll print the array and all its objects quite happily.
Your code does have a problem though. This line:
[[arrayOfComics valueForKey:#"Name"] sortUsingSelector:#selector(caseInsensitiveCompare:)];
is nonsense. First it gets an array of the name keys of your objects and then it tries to sort it (which may fail unless the array of names happens to be mutable). Then it throws away the result.
At the time I was having a bunch of problems because I did not fully understand the difference between mutable and non mutable arrays, as well as the various return values from array operations.
I eventually fixed this by making a bunch of changes.
Thanks to everyone that provided help.