message sent to deallocated instance ,,, [__NSArrayI respondsToSelector:] - objective-c

I have this implementation file with aNSArray object userIDs
NSArray *userIDs;
NSInteger friendID;
#implementation TableViewController
-(void)reciveFriendsIDs:(NSArray *)array
{
userIDs = [NSArray arrayWithArray:array];
}
-(NSString *)getFriendId
{
return [userIDs objectAtIndex:friendID];
}
.
.
.
#end
and the method -(NSString *)getFriendId call it from another class like this :
TableViewController *tableController = [[TableViewController alloc]init];
NSString *fid = [tableController getFriendId];
But I am having an error said "-[__NSArrayI respondsToSelector:]: message sent to deallocated instance 0x20320200" and the compiler indicate the error in this line:
return [userIDs objectAtIndex:friendID];

You are allocating the NSArray with arrayWithArray static method.
In this way it's getting added in the auto release pool and the retain count will be 0.
Either retain it or manually alloc it with [[NSArray alloc] init]

I was getting the same exception on line
if(self.arrTypes != nil)
cause of the following line being used at a different place in code
[self.arrTypes release];
and replacing this code with
self.arrTypes = nil;
resolved the issue.

Related

Why cannot I modify an object inside my method

I am calling an Api asynchronously to get the data. Then I am assigning the data to a shared instance successfully inside a block given below.
RestApiManager *api= [[RestApiManager alloc]init];
[ObjectBuilder sharedManager];
self.obj = [[Object alloc]init];
[api get_data:credential.password finish:^(NSDictionary *data) {
if(data){
self.obj = [ObjectBuilder obj:data];
[[ObjectBuilder sharedManager]setObject:self.obj];
}
This all working as expected except when I try to update some of the values in one of NSMutableDictionary properties of the obj.
- (void)update: (NSInteger) temp {
array3 = [[NSMutableArray alloc]init];
NSNumber *start =[[NSNumber numberWithInteger:var];
[NSNumber numberWithInteger:var2];
NSNumber *temp2 =[NSNumber numberWithInteger:temp];
[array3 addObject:temp2];
[array3 addObject:start];
[array3 addObject:end];
[self.obj.sch setObject:array3 forKey:temp2];
}
[obj.sch setObject:array3 forKey:temp2]; always crashes my app.
Now I have vague idea whats going on, basically I am setting obj inside a block code, whilst in my update function I am trying to change the contents outside block code.
The error I get is
reason: '-[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance
Note this error goes away if i declare line
[[ObjectBuilder sharedManager]setObject:obj];
Outside the finish:^ block
But then I lose all the data obtained from api call.
Object is declared as below #interface Object : NSObject
#property (strong, nonatomic) NSMutableDictionary *sch;

[__NSCFString superview]: unrecognized selector sent to instance

I am trying to copy a NSMutableArray* into NSArray*, but it does not works and it generates a [__NSCFString superview]: unrecognized selector sent to instance error . Here is the code:
//where gc is a NSDictionary*, recentKey is a NSString*, and _objects is a NSArray*
//gc is an singleton is used to save chache data, with NSKeyedUnarchiver class
//_objects is used to reload the UITableView's data
NSArray *savedNews = [[NSArray alloc] initWithArray:[gc objectForKey:recentkey]];
//this not works...why??
_objects = [[NSArray alloc] initWithArray:savedNews];
Resolution:
Yes, as Herman suggests, the error was external. The savedNews Array was using a class with NSEncoding with an error:
- (void)encodeWithCoder:(NSCoder *)encoder {
//...where element was NSString* and not "UIImageView"
// element should be imgView
if (imgView) [encoder encodeObject:element forKey:#"imgView"];
}
Thanks for all guys.
Somewhere in your App is the superview of an NSString object fetched.
I guess that you assigned an NSString object to something where a UIView is expected.
Could be something like:
someButton.textLabel = someString; // wrong - but should generate a compiler warning
instead of
someButton.textLabel.text = someString; // correct
This is not directly related to your array issue.
First, check what the object in the dictionary is for that key.
NSLog(#"GC Object type for recentkey:%#", [[gc objectForKey:recentkey] class]);
You can only pass an NSArray to initWithArray:
So if that object isn't already an NSArray but you want that object to be IN an array. The do this..
id obj = [gc objectForKey:recentkey]; //Because I have no idea what this is
NSArray *savedNews = [NSArray arrayWithObject:obj];

NSMutableArray always empty?

Still have some difficulties to understand Obj-C's gestion of memory and some of its concepts.
So my main class contains a NSMutableArray containing some characters and their list of weapons. It's like this :
In Main class.h
#property (nonatomic, retain) NSMutableArray *players;
In Main class.m's init
for(int i = 0 ; i < 30 ; i++)
{
[players addObject:[[PlayerInGame alloc] init:[self.tabPlayers objectAtIndex:i] :[self.tabWeapons:objectAtIndex:i]]];
}
PlayerInGame.h
#property (nonatomic, retain) NSMutableArray *weaponsList;
PlayerInGame.m
- (id) init : (Player*) player : (Weapon*) weapon
{
[self.weaponsList addObject:weapon];
// Then I try NSLog of weaponsList's count.
}
Here weaponsList is always empty. What is wrong?
The other answers are right. On any other language if you reference a unallocated object you will get a NullPointerException. But in objective C the method sent to nil just returns 0 and it won't crash the app.. If you want further read, read this
That is why
[self.weaponsList addObject:weapon];
didn't crash, while in java if you try to add object to a unallocated array your program will crash.. As other answers pointed out, the statement
self.weaponsList = [[[NSMutableArray alloc] init] autorelease];
alloc memory to store array, and a reference is given back to to variable weaponList. Now weaponList != nil.
You have to alloc your array before add any object in it. you can use following code in viewDidLoad method
NSMutableArray *players = [[NSMutableArray allo]init];
NSMutableArray weaponsList = [[[NSMutableArray alloc] init]
I've not seen weaponList object allocation. Do you initialize it?
self.weaponsList = [[[NSMutableArray alloc] init] autorelease];
PS: Minor advice. Method "- (id) init : (Player*) player : (Weapon*) weapon" signature will look better and being used easier if you change it as
- (id) initWithPlayer:(Player *)player weapon:(Weapon *)weapon
I aslo suggest to change a bit your init syntax and init the array with object:
- (id) initWithPlayer:(Player *)aPlayer weapon:(Weapon *)aWeapon {
self.weaponsList = [NSMutableArray arrayWithObject:aWeapon];
[self.weaponsList retain];
// remember to release inside dealloc, or use autorelease
}

Can't add object to static NSMutableArray

I have a static variable on appDelegate declared like this:
appdelegate.h file:
+(NSMutableArray*)allBanco;
+(void)setAllBanco:(NSMutableArray*)value;
appdelegate.m file:
static NSMutableArray * allBanco;
+(NSMutableArray*)allBanco
{
return allBanco;
}
+(void)setAllBanco:(NSMutableArray*)value
{
if(allBanco != value)
{
[allBanco release];
allBanco = [value copy];
}
}
I tried to acess it on other class
on .m file:
#import "AppDelegate.h"
[[AppDelegate allBanco] addObject:testeObj];
i cant understand why,i can log the
NSLog(#"%i",[[AppDelegate allBanco] count]);
and goes ok.
I tried :
NSMutableArray * temp = [[[NSMutableArray alloc]init]autorelease];
temp = [AppDelegate allBanco];
[temp addObject:testeObj];
[AppDelegate setAllBanco:temp];
and doest work.
Considering you created your array properly, keep in mind that -copy returns an immutable copy, so you may crash later when modifying it.
Now that you added your error, I'm quite sure this is indeed the problem:
-[__NSArrayI addObject:]: unrecognized selector sent to instance
You tried to add an object in a NSArray, not a NSMutableArray. Try using -mutableCopy.
You haven't created an object for allBanco to point to. Change your method so that you can create one if it doesn't exist yet:
+(NSMutableArray*)allBanco
{
if (!allBanco)
allBanco = [[NSMutableArray alloc] init];
return allBanco;
}

"Incorrect decrement" and "Potential leak" messages from Analyzer

When I compile with the analyzer, I get a couple of messages. I have these properties declared:
#property (nonatomic, retain) SyncServicePrimary *syncAndCartOne;
#property (nonatomic, retain) SyncServiceSecondary *syncAndCartTwo;
This method is called from applicationDidBecomeActive and I get "Potential leak of an object allocated".
-(void)makeTheCartObjectsForCountry:(NSString*)country_key{
self.syncAndCartOne = [[SyncServicePrimary alloc] init];
self.syncAndCartTwo = [[SyncServiceSecondary alloc] init];
}
This is called in applicationWillResignActive; here I get "Incorrect decrement of the reference count of an object".
-(void) removeTheCartObjects{
[self.syncAndCartOne release];
self.syncAndCartOne = Nil;
[self.syncAndCartTwo release];
self.syncAndCartTwo = Nil;
}
If I set the objects to autorelease, the error goes away, but I want the objects to be released when the app hides itself.
Is this something I am doing right but that is split too far for the analyzer to see the start and end, or is this something I can do better/properly so it won't complain?
Its more than likely that I am missing a simple concept with regard to release and alloc cycles (I've come from PHP and C#).
Your problem is here:
-(void)makeTheCartObjectsForCountry:(NSString*)country_key{
self.syncAndCartOne = [[SyncServicePrimary alloc] init];
self.syncAndCartTwo = [[SyncServiceSecondary alloc] init];
}
You're creating the objects and then retaining them (because of the property declaration), so they have a reference count of 2, when only one object is referencing them.
You should do it like this:
-(void)makeTheCartObjectsForCountry:(NSString*)country_key{
SyncServicePrimary *primary = [[SyncServicePrimary alloc] init];
self.syncAndCartOne = primary;
[primary release];
SyncServiceSecondary *secondary = [[SyncServiceSecondary alloc] init];
self.syncAndCartTwo = secondary;
[secondary release];
}
You have defined the properties with attribute retain, so the analyzer assumes that the setter method for the property looks like this:
- (void)setSyncAndCartOne:(SyncServicePrimary *)newValue
{
[newValue retain];
[self->_syncAndCartOne release]; // access the instance variable holding the property value
self->_syncAndCartOne = newValue;
}
If you use #synthesize, the setter method will look like that.
So, when makeTheCartObjectsForCountry: returns, the object in syncAndCartOne has a retain count of 2, but should only have a retain count of 1. That's why using autorelease fixes it.
You shouldn't be doing [self.syncAndCartOne release] for the same reason. The setter method will send the old object a release when you assign nil to the property.