Error when adding NSString object to my NSMutableArray - ios

I am getting this error when trying to add the NSString object named object to my array :
erminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI addObject:]: unrecognized selector sent to instance 0x7fc48ae52ba0'
Not sure why this is so. I was originally using NSArray to changed it to NSMutableArray but I am still having problems with it. Code is below:
-(NSMutableArray *)getReplyArrayForMessage: (NSString *)message {
//get the array
NSMutableArray *replies = [self.messageDictionary objectForKey:message];
NSLog(#"%#",replies);
//if no replies we init the base set
if([replies count]==0) {
//get the base array
//this also works if a key just isn't in the dictonary
return replies=[self getBaseArray];
}
else {
//add the other message
NSString *object = #"Send a different message";
[replies addObject:object];
return replies;
}
}
If anyone could give me a pointer to why this is happening I would appreciate it. Noob here.

The array is immutable (NSArray), not mutable (NSMutableArray). You can create a mutable array from an immutable array using mutableCopy:
NSMutableArray *replies = [[self.messageDictionary objectForKey:message] mutableCopy];
I know this from the exception text:
-[__NSArrayI addObject:]: unrecognized selector sent to instance ...
^^^^^^^^^^
EDIT I've missed off some important information from my original answer.
Having used mutableCopy you now have a copy of the array and the original array (from self.messageDictionary objectForKey:message) will remain unchanged after you add your element. This is almost certainly not what you intended.
As I've mentioned in the comments below, you probably want to create a custom object to hold these details (or an array of custom objects) that should be created from the message dictionary as soon as you receive it. The effort required to create a custom object will pay for itself tenfold in the long term.

You are trying to add an NSString to an NSArray (which looks like an NSMutableArray) since you initialized it as one. This means that the object that you store in your messageDictionary is actually of type NSArray, and not NSMutabelArray. So, assigning it to an object of type NSMutableArray won't actually change its type and make it mutable.
It's an easy fix:
NSMutableArray *replies = [[NSMutableArray alloc] initWithArray:(NSArray *) [self.messageDictionary objectForKey:message]];
Or you can go with mutableCopy (as suggested by #trojanfoe) which is a shortcut but will lead to the same result.
I can tell because the error message says -[__NSArrayI addObject:]: unrecognized selector sent to instance 0x7fc48ae52ba0'. Notice the I at the end of __NSArrayI, this means that this array is actually immutable, so you can't add objects to it.

Related

Accessing an instance throws exception - NSDictionary NSArray

I am a beginner in Objective-C and do struggle a bit with dictionaries and arrays.
My goal is to create a table view where every cell contains a picture from a server. The url for the pic comes from a JSON call. I downloaded the example from Apple called "lazy table view" and tried to merge it with the one I found inside a Standford iOS Class. So far everything works, besides the picture. Xcode throws the following exception, once I try to access the icon:
-[__NSCFDictionary Icon]: unrecognized selector sent to instance 0x10b845ff0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary Icon]: unrecognized selector sent to instance 0x10b845ff0'
The code in question looks like this:
#interface FlickrPhotosTVC : UITableViewController
#property (nonatomic, strong) NSArray *photos;
#end
#interface ClRecord : NSObject
#property (nonatomic, strong) UIImage *Icon;
#define FLICKR_PHOTO_TITLE #"title"
ClRecord *clRecord = self.photos[indexPath.row];
cell.textLabel.text = [clRecord valueForKeyPath:FLICKR_PHOTO_TITLE]; // works
if (clRecord.Icon) NSLog(#"test"); // throws exeption
Somehow this seems to be releated with the types. Trying to access an array, while accesing a dictionory or similar. I found some releated posts on stack, but could not solve it so far.
Thank you for any help!
The objects stored in self.photos seems to be dictionaries objects and not ClRecord objects. The error you get say that you are calling Icon method on a dictionary object.
Check where you fill your photos array to make sure you put ClRecord objects in it and not dictionaries objects.
You could do NSLog(#"My photos array is ---%#",self.photos);
This will give you what exactly you have in your array.
Case 1: If you have a dictionary objects then :- You should do NSDictionary *dict = self.photos[indexPath.row]; ClRecord *clRecord = [dict objectForKey:#"YourKeyForImage"];
Case2: If you have images as you expect, then make sure you import ClRecord header file, you have non nil object at your specified [indexPath.row] index and other necessary initializations.
Hope this helps. Link1

How XCode knows about name of function at compile time?

I have written simple code to practice selector in Objective C, which is working fine
NSMutableArray *array = [NSMutableArray arrayWithObjects:#"A",#"B", nil];
NSLog(#"Before adding %#",array);
SEL message = #selector(addObject:); //I will change this line
if([array respondsToSelector:message])
{
[array performSelector:message withObject:#"C"];
}
NSLog(#"After adding %#",array);
But as soon as I change selector line to,
SEL message = #selector(addobject:);// Just changed name of selector
XCode starts giving warning :
Undeclared selector 'addobject:'
Now, question is how XCode knows at compile time about name of method is correct or not. Is there always list of selector generates internally for whatever object I am creating? In this case for NSMutableArray
All Xcode knows is that there is no class, either in the system code or in your program, that declares a selector called addobject. You can prove this by creating a custom class that declares an addobject method, and the warning should go away, but of course the program will crash with a unrecognized selector sent to object error message.

removeAllObjects crashes app

I want to clear my array, what i did is,
I have tableview view in my app, first i am fetching data from server and loading it in tableView.
-(void)viewDidLoad{
//fetching data from server using background thread and storing it in array called (msg_array)
[table reloadData];
}
when last row comes on screen i want to fetch new data from server and i want to display it,
-(void)LoadMoreData{ //this method gets fire when last cell is on screen
if ([msg_array count]>0)
{
[msg_array removeAllObjects]; //crashes here
}
}
This gives the error:
Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[__NSArrayI removeAllObjects]: unrecognized selector sent to instance
Why does it cause a crash:
The array is allocated like this:
msg_array = [dictShow copy];
dictshow contains the data and copying it to msg_array and dictshow is mutabledictionary
(Taken from comments)
'-[__NSArrayI removeAllObjects]: unrecognized selector sent to instance
This means that the array doens't have the method you're trying to call. That's because it is an immutable array (NSArray), not mutable (NSMutableArray).
Either make it mutable if you want to mutate it. Or, replace:
[msg_array removeAllObjects];
with:
msg_array = #[];
Based on your comment, the array should be mutable. That means that you have a mutable property / instance variable, but that you're creating an immutable instance to store into it. Find that location and update it (to create / return a mutableCopy at least).
Its because you are trying to modify a immutable array, you have two options here:
msg_array = #[];
OR
NSMutableArray *mutableMessageArray = [msg_array mutableCopy];
[mutableMessageArray removeAllObjects];
msg_array = [mutableMessageArray copy];
I prefer the first option as its neater, but if you need to do any other modifications of the array the latter option might be best for you.
NB:
Check how you declare msg_array, can you post that code?
msg_array could be immutable thats why it is crashing. removeAllObjects is only for NSMutableArray
__NSArrayI, looking carefully at this bit, we can see it's suffixed with an i. This i means the array is immutable and can't be changed.
You possibly want to use an NSMutableArray
msg_array = [dictShow copy]; dictshow contains the data and copying it to msg_array and dictshow is mutabledictionary
This is very strange! I expect that calling copy on a dictionary would always return a dictionary. Unless you are mistaken there, I can only imagine that either the dictionary's keys or its values are being returned.
I think you might have meant mutable array; assuming you did, the call to copy returns an immutable object, try [dictShow mutableCopy] instead
msg_array = [NSMutableArray arrayWithArray:_MoodsArray].mutableCopy;

unrecognized selector "length" when attempting to log entire managed object with overridden getter/setter

I use core data to store some arrays as strings. The strings are prefixed with STRINGFROMARRAY and delimited by &,&.
I thought it would be neat to override the setters and getters so I wouldn't have to provide code to convert them every time I needed access. I have created a managed object subclass called TestEntity with only one attribute, "memberIds" (string). I have verified that my custom setter and getter seem to work fine:
TestEntity.h:
#interface TestEntity (CoreDataGeneratedAccessors)
- (NSArray*)memberIds;
- (void)setMemberIds:(NSArray *)memberIds;
#end
TestEntity.m:
#implementation TestEntity
#dynamic memberIds;
- (NSArray *)memberIds
{
[self willAccessValueForKey:#"memberIds"];
NSArray *memberIdsArray = [NSArray arrayWithArray:[[[self primitiveValueForKey:#"memberIds"] substringFromIndex:15] componentsSeparatedByString:#"&,&"]];
[self didAccessValueForKey:#"memberIds"];
return memberIdsArray;
}
- (void)setMemberIds:(NSArray *)memberIds
{
NSString *stringFromArray = [#"STRINGFROMARRAY" stringByAppendingString:[memberIds componentsJoinedByString:#"&,&"]];
[self willChangeValueForKey:#"memberIds"];
[self setPrimitiveValue:stringFromArray forKey:#"memberIds"];
[self didChangeValueForKey:#"memberIds"];
}
#end
I can set an array value and it properly stores as a string. I can also use valueForKey to log the value after it's set, and it properly prints as an array.
However, when I attempt to log the entire managed object (without valueForKey:), I get a [NSArray length] unrecognized selector error.
Here's the code I'm using to test this:
NSManagedObject *test = [NSEntityDescription insertNewObjectForEntityForName:#"TestEntity" inManagedObjectContext:[SyncEngine sharedEngine].managedObjectContext];
[test setValue:[NSArray arrayWithObjects:#"1", #"2", #"3", nil] forKey:#"memberIds"];
NSLog(#"%#", [test valueForKey:#"memberIds"]);
NSLog(#"%#", test);
And here's the output:
2013-08-24 13:59:27.820 0.1[1440:19d03] (
1,
2,
3
)
2013-08-24 13:59:27.820 0.1[1440:19d03] -[__NSArrayI length]: unrecognized selector sent to instance 0xa533800
Why is the length message getting sent to my array? And how can I prevent this crash? Thanks!
I think the problem is that you have overriden memberIds methods.
In your model, memberIds should return a string, and you've overriden it to return an NSArray.
So, when your managedobjet is trying to generate its description, it is assuming that memberIds is a string.
I think the best way to do that it to name your custom getter / setter differently than your model attribute.

alloc init release [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
index 0 beyond bounds for empty array error
I am a hobbyist in iOS programming. And I always have the same problem while programming.
I think that I don't understand the memory management issue.
This is my actual project:
h-File:
a NSMutableArray containing NSStrings
NSMutableArray *pictureStrings;
#property (nonatomic,retain) NSMutableArray *pictureStrings;
in the m-File:
#synthesize pictureStrings;
and in the viewDidLoad Method
pictureStrings = [[NSMutableArray alloc] init];
in the dealloc Method
[pictureStrings release];
okay. I am working with an asynchronous URL Request which gets a number of strings and in the connectionDidFinishLoading Delegate Method the values get stored to pictureStrings
[pictureStrings addObject:aString];
BUT
when I read values in the cellForRowAtIndexPath Method like
if (pictureStrings != nil) {
cell.textLabel.text = [NSString stringWithFormat:#"%#", [pictureStrings objectAtIndex:indexPath.row]];
}
my App crashes with the message:
* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[NSMutableArray objectAtIndex:]: index 0 beyond bounds for empty array'
Where is my fault?
Please help me!
Yours, Raphael.
Greetings from Austria
Your crash is not a memory management issue. Your crash is that you're reading past the end of an array. We know that pictureStrings is non-nil at that point, because if it was nil then the objectAtIndex: method would have silently just returned nil (because messaging nil returns nil [1]). Oh and not to mention you have the if around the call to objectAtIndex: anyway - but you can safely remove that really as you shouldn't need it.
So, the only thing that can really be happening here is that your [pictureStrings addObject:aString] are not being called before the table view is reloaded. However, that would be quite odd because I assume you are doing something like return pictureStrings.count in the table view's tableView:numberOfRowsInSection: data source method. If there really were zero elements in the array then the table view wouldn't be asking for any rows and you wouldn't get this crash.
I think your problem is likely to be that you're not adding the strings to the array. You could check by breakpointing that code and seeing what is happening.
Also, consider changing your code to set the cell's text to this:
cell.textLabel.text = [pictureStrings objectAtIndex:indexPath.row];
You said they are already strings so why bother going through a stringWithFormat: call?
[1] Caveat: Doesn't always return nil - read up about it for more information.

Resources