Recently I have upgraded XCode8 I am facing issue in isKindOfClass method this code is working till to iOS9 but in iOS10 suddenly [items isKindOfClass: [NSMutableArray class]] compiler not going in for loop condition may I know what is the reason?
NSMutableArray is child class of NSArray so when I am changing to [NSArray class] then it works fine so I am confuse why this change affect to NSMutableArray class which is child class of NSArray ?
NSMutableArray *items = [jsonDictionary objectForKey:#"items"]; // Here i am taking response in NSMutableArray
if ([items isKindOfClass: [NSMutableArray class]] && items != nil) // not working {
for (NSMutableDictionary *item in items)
{
// Rest of Code
}
}
This code works for me I m confuse the above code working until iOS9 when I change this below code then after working in iOS10:
NSMutableArray *items = [jsonDictionary objectForKey:#"items"];
if ([items isKindOfClass: [NSArray class]] && items != nil) // Changed to NSArray {
for (NSMutableDictionary *item in items)
{
// Rest of Code
}
}
From your comments, it seems that you actually have an NSArray, not an NSMutableArray, so isKindOfClass is working correctly. AFN will give immutable containers unless you specify otherwise, and this shouldn't be any different on iOS 10, so I am not sure why it was working previously.
Rather than testing for a mutable array, it is probably simpler to create a mutable copy of whatever is there, this way you don't have to try and handle the "failure" condition gracefully:
NSArray *items = [jsonDictionary objectForKey:#"items"];
if (items != nil) {
NSMutableArray *mutableItems = [items mutableCopy];
for (NSMutableDictionary *item in mutableItems)
{
// Rest of Code
}
}
Beware, unless you have specified the option to AFN to provide mutable containers, the dictionaries inside your items array will be NSDictionary not NSMutableDictionary, so you may need to make mutable copies of them.
Of course, if you aren't mutating the array or the dictionary, then you can just u NSArray and NSDictionary regardless of whether you have a mutable or immutable object.
Related
I have a plist that looks like this with a count of 81 "dictionary" items:
I have this code which reads pList into newArray
NSArray *newArray = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"DukeCruiseControlTable" ofType:#"plist"]];
When I look at newArray in the debugger I get:
newArray has the right number of elements, so it is reading the right file. But instead of containing the content of each element it is showing just the index of the element (e.g. [3]).
What am I doing wrong?
Being new to iOS I thought perhaps the debugger just showed me the indices of an Array, but when I use the next code to read the array into another array of objects I get an error that indicates that the newArray element is "[3]" or whatever the index is.
for (dukeperfPerfChartLine *object in newArray)
{
[self.perfTable addObject:object];
}
I dont see any problem in reading the file, in debugger it will show only the indices, you can try printing the newArray just after reading from the file as:
NSLog(#"%#",newArray);
For reading the dictionaries from the newArray,I think you should try this:
EDITED:
for (NSDictionary *dict in newArray)
{
NSArray *allKeys = [dict allKeys];
for (NSString *key in allKeys)
{
NSLog(#"%#=%#",key,[dict objectForKey:key]);
}
}
Hope it will help.
A comment to the answer by #Rajeev but as an answer just for the formatting.
Two other methods using different enumeration methods:
Using fast enumeration:
for (NSDictionary *dict in newArray) {
for (NSString *key in dict) {
NSLog(#"%#=%#",key,[dict objectForKey:key]);
}
}
Using an enumeration block:
for (NSDictionary *dict in newArray) {
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSLog(#"%#=%#",key, obj);
}];
}
These produce the same results as the answer by #Rajeev.
While trying to set a single key/value pair in NSMutableDictionary of NSMutableArray like:
[[self.items objectAtIndex:i] setValue:#"value" forKey:#"key"];
self.items is NSMutableArray and it have a list of NSMutableDictionaries
Instead of setting to that single object, it set it to all dictionaries in the list.
I have used this method before. But I don't know what is happening in this case.
I know NSArray have setValue:#"value" forKey:#"key method, but in this case I am using NSMutableArray
Here is a bit more block of code to help clarify my situation:
-(void)setItem:(id)sender
{
for (CellView *cell in self.CollectionView.visibleCells)
{
NSIndexPath *indexPath = [self.CollectionView indexPathForCell:cell];
int i = (indexPath.section * (mainItems.count)/3+ indexPath.row);
if (((UIButton *)sender).tag == i)
{
[[self.items objectAtIndex:i] setValue:#"value" forKey:#"key"];
}
}
}
Call setObject:forKey:, not setValue:forKey:. There is a difference.
Note that NSMutableArray extends NSArray so NSMutableArray has all of the methods of NSArray.
I also recommend you split your line up as well as use modern syntax:
NSMutableDictionary *dict = self.items[i];
dict[#"key"] = #"value";
NSMutableArray is a subclass of NSArray so all the NSArray methods are still there in NSMutatbleArray. You could try pulling it out and putting it back in to figure things out then reassemble your code after...
NSMutableDictionary *d = [self.items objectAtIndex:i];
[d setValue:#"value" forKey:#"key"];
[self.items setObject: d atIndexedSubscript: i];
This is a little more explicit which will allow you to debug it easier (not getting unexpected nils back, etc.).
Ok I got the issue.
I am working on a large pre-existing code. And I come to notice that The MutableDictionary was defined globally and the same object was being added to the MutableArray. So basically all the pointers in the MUtableArray where pointing to a single object.
I have an array of recommendedcar IDs, and another array of allcar IDs. From this, I have to take the recommendedcar images. First, I check whether the recommended carid is in my allcar id; if it is, I select the corresponding car images, and store them into NSArray.
This is the code I am using.
for (int i=0;i<[listOfCarId count];i++) {
for (int j=0;j<[_allCarID count];j++) {
tempAllCarId=[_allCarID objectAtIndex:j];
tempRecommendedCarId=[listOfCarId objectAtIndex:i];
if ([tempRecommendedCarId isEqualToString:tempAllCarId]) {
_recommendedCarImage=[_allCarImages objectAtIndex:j];
NSLog(#"finalImage%#",_recommendedCarImage);
}
}
}
_recommendedcarImage is NSMUtableArray; I want a NSArray. How can I convert it to a NSArray?
How can i replace the "_recommendedCarImage " with an NSArray?? Currently _recommendedCarImage is a mutable array.
Polymorphism. Since NSMutableArray is a subclass of NSArray, you can use it anywhere an NSArray is expected. You don't have to do anything.
Now its working,What i did is , I just copy the contents of Mutable array to NSarray
recommendedArray=[_recommendedCarImage copy];
An NSMutableArray is an NSArray already (as it's a subclass of NSArray), still you can do:
NSArray *array = [NSArray arrayWithArray:mutableArray];
Here is the situation:
I have a request on AFNetworking that retrieves me a JSON with an NSArray.
My goal is to mutate the NSDictionaries inside it. I already made a mutableCopy of the array, but I want to know if I can easily mutate all the content. Will I have to iterate through the array manually?
NSJSONSerialization has options to allow you to control the mutability of the resulting data structure. Just pass the appropriate ones (probably NSJSONReadingMutableContainers) and there you go.
You cannot mutate NSDictionary, just because only NSMutableDictionary has method setObject:forKey:
So you should create mutableCopy of each dictionary and empty mutable array. Then with a forloop fill that array. Your code should be so:
- (NSMutableArray *)mutatedArrayFromArray:(NSArray *)array
{
NSMutableArray *resultArray = [NSMutableArray new];
if([array count] > 0)
{
for(int i = 0; i < count; i++)
{
NSMutableDictionary *mutatedItem = [[array objectAtIndex:i] mutableCopy];
[resultArray addObject:mutatedItem];
[mutatedItem release]; // only with ARC disabled
}
}
return [result autorelease]; // if ARC enabled : return result;
}
How can I remove an object from a reversed NSArray.
Currently I have a NSMutableArray, then I reverse it with
NSArray* reversedCalEvents = [[calEvents reverseObjectEnumerator] allObjects];
now I need to remove at item from reversedCalEvents or calEvents and automatically refresh the table the array is displayed in based on conditions.
i.e.
if(someInt == someOtherInt){
remove object at index 0
}
How can I do this? I cannot get it to work.
Here's a more functional approach using Key-Value Coding:
#implementation NSArray (Additions)
- (instancetype)arrayByRemovingObject:(id)object {
return [self filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF != %#", object]];
}
#end
You will need a mutable array in order to remove an object. Try creating reversedCalEvents with mutableCopy.
NSMutableArray *reversedCalEvents = [[calEvents reverseObjectEnumerator] allObjects] mutableCopy];
if (someInt == someOtherInt)
{
[reversedCalEvents removeObject:object];
}
NSArray is not editable, so that you cannot modify it. You can copy that array to NSMutableArray and remove objects from it. And finally reassign the values of the NSMutableArray to your NSArray.
From here you will get a better idea...
NSArray + remove item from array
First you should read up on the NSMutableArray class itself to familiarize yourself with it.
Second, this question should show you an easy way to remove the objects from your NSMutableArray instance.
Third, you can cause the UITableView to refresh by sending it the reloadData message.
you can try this:-
NSMutableArray* reversedCalEvents = [[[calEvents reverseObjectEnumerator] allObjects] mutableCopy];
[reversedCalEvents removeLastObject];