-[__NSArrayI isEqualToString:]: message sent to deallocated instance - iphone

I have passed an NSArray value back to a parent view using a delegate.
it is received in the parent view like so
- (void) setManufactureSearchFields:(NSArray *)arrayValues withIndexPath:(NSIndexPath *)myIndexPath
{
manufactureSearchObjectString = [arrayValues valueForKey:#"MANUFACTURER"];
NSLog(#"%#",[arrayValues valueForKey:#"MANUFACTURER"]);
manufactureResultIndexPath = myIndexPath;
[self.tableView reloadData]; //reloads the tabels so you can see the value in the tableViewCell.
}
If i was to execute this code and select the tablecell of the childview it obviously executes the delegate but then freezes up and fires this error to the Log
2011-10-31 14:06:16.670 code[12610:207] (
"Alfa Romeo"
)
2011-10-31 14:06:16.673 code[12610:207] *** -[__NSArrayI isEqualToString:]: message sent to deallocated instance 0x6859280
However if I comment out the following line in my delegate method
- (void) setManufactureSearchFields:(NSArray *)arrayValues withIndexPath:(NSIndexPath *)myIndexPath
{
//manufactureSearchObjectString = [arrayValues valueForKey:#"MANUFACTURER"];
NSLog(#"%#",[arrayValues valueForKey:#"MANUFACTURER"]);
manufactureResultIndexPath = myIndexPath;
[self.tableView reloadData]; //reloads the tabels so you can see the value in the tableViewCell.
}
it dose not crash and I end up with the NSLog with the correct details in my log like so.
2011-10-31 14:09:28.200 code[12737:207] (
Sony
)
I am hoping someone has experianced such a problem before, this is what my array object looks like, its a dictionary of values.
ISELECT = F;
ISALIVE = T;
MANUFACTURER = Sony;
MANUFACTURERID = 3;

valueForKey: returns an autoreleased instance. Unless you retain it, you can expect it will be deallocated sometime after you return from the current method. It looks like you are assigning it to an instance variable. If you do that, you need to retain it.
manufactureSearchObjectString = [arrayValues valueForKey:#"MANUFACTURER"];
[manufactureSearchObjectString retain];
But it looks like you have another problem.
[arrayValues valueForKey:#"MANUFACTURER"];
That returns an array.
manufactureSearchObjectString = [arrayValues valueForKey:#"MANUFACTURER"];
By the name of your variable, it looks as though you're assigning it to a string variable. So if you fix the retain issue, then you will have another error. You will get an unrecognized selector when you try to call isEqualToString on it.
You need to assign a string value to manufactureSearchObjectString. You need to figure out what string value you want that to be. In this case you only have one string in your array, so I guess you want that one. In that case
manufactureSearchObjectString = [[arrayValues valueForKey:#"MANUFACTURER"] objectAtIndex:0];
[manufactureSearchObjectString retain];
But in general you need to check if there is more than one value in the array, and decide which one you want, and also check if there are no values in the array, and do something correct to handle that.

Try changing your code into this:
- (void) setManufactureSearchFields:(NSDictionary *)arrayValues withIndexPath:(NSIndexPath *)myIndexPath
{
manufactureSearchObjectString = [[arrayValues valueForKey:#"MANUFACTURER"] copy];
NSLog(#"%#",[arrayValues valueForKey:#"MANUFACTURER"]);
manufactureResultIndexPath = myIndexPath;
[self.tableView reloadData]; //reloads the tabels so you can see the value in the tableViewCell.
}
Please note that I've also changed the variable type of arrayValues to NSDictionary. Let me know if that works for you.

please convert it to NSString.
NSString *manufact=[NSString stringWithFormat:#"%#",[arrayValues valueForKey:#"MANUFACTURER"];
It will not get crash.

Related

objective c perform selector in background and autoreleasepool

I am developing an iphone application which has some data stored in a sqllite database. When my view loads i would like to load the data from the database on a background thread. The problem is the application keeps crashing and i dont know why.
The code:
-(id) init
{
if((self=[super init]))
{
[self performSelectorInBackground:#selector(loadList) withObject:nil];
}
}
-(void) loadList
{
#autoreleasepool
{
Loader * loader = [[Loader alloc] init];
NSMutableArray * array = [loader getItemList];
[array retain];
NSLog(#"Got %d items",[array count]);
[self performSelectorOnMainThread:#selector(createList:) withObject:array waitUntilDone:false];
[loader release];
}
}
-(void) createList: (NSMutableArray*) array
{
items = array;
int i;
Item * it;
for(i = 0; i < [items count]; i++)
{
it = [items objectAtIndex: i];
[it getName]; // crashes
// populate the list
}
}
Loader returns a NSMutableArray with Item objects. The application crashes when i call the item getName (which returns a NSString*). From what i understand it crashes because the item name properties is being released. What am i doing wrong?
Thanks!
It's likely to be a problem with whatever type of object you're using to populate array.
I'm unable to find finger-on-paper proof but I'm confident that performSelectorOnMainThread:withObject:waitUntilDone: retains its object. However if each of the items in array keeps a reference to loader then they need to take responsibility for retaining that object. It looks like you're attempting to keep it alive manually but — as Chuck alludes to — your call to performSelector... will return instantly and not wait for the call you've made to complete.
This particular bug appears to be that you're passing waitUntilDone:NO, so the array is being released immediately and consequently so are its items.
But in general, UIKit is not thread-safe, so this is just a touchy design. I would probably put the loading of this stuff in another class that handles the task for you instead of right in the view.
I'd put a breakpoint on the line:
it = [items objectAtIndex: i];
Then type
po it
in the debugger, and see what's in the name field. As a guess, I'd say one of two things: 1) the field that getName returns isn't initialized with an object (i.e. isn't a real NSString *) or that you're getting a C string from SQLite (which is what it usually returns) and you're trying to treat it as an NSString *. If it's the latter you can use [myCString stringWithUTF8String] to convert the C string into an NSString *

App crash in button

I have face strange problem on UIButton.
When i tap button the app is crash .
I wrote below code for that...
-(IBAction)renameTest:(id)sender
{
NSLog(#"Tapped");
// UIButton *button = (UIButton *)sender;
NSUInteger row = 1;//button.tag;
NSString * titlename = [titleArray objectAtIndex:row];
RenameTest *renameVC = [[RenameTest alloc]initWithNibName:#"RenameTest" bundle:nil];
renameVC.titlespell = titlename;
NSLog(#"titlespell = %#",renameVC.titlespell);
NSLog(#"title = %#",titlename);
// [button release];
[self.navigationController pushViewController:renameVC animated:YES]; //here APP is cresh
[renameVC release];
}
I check also my .Xib file name .It is ok and files are there.
error msg is below :
2012-07-11 14:28:29.079 TestApp[238:207] -[__NSCFDictionary _isNaturallyRTL]: unrecognized selector sent to instance 0x73d8a80
Thanks in Advance.
[button release] is causing the problem. Remove it and check.
_isNaturallyRTL is an NSString method (private), and it looks like you are passing a dictionary instead of a string somewhere.
Breaking on the exception and showing us the call stack at that point would help tremendously.
If u have created the button in xib file then u cannot release it because you have not allocated it and claimed ownership.. U should call release only on objects you have allocated by calling alloc..
Remove the [button release] statement .. that should fix the crash!
You have a crash which is related to a dictionary and your titlename string is set equal to, titleArray objectAtIndex:row. I believe, without seeing the declaration of your variables, that titleArray is a dictionary, or is a NSMutableArray importing from a plist of dictionaries, either way you need to use objectForKey, when using dictionaries, like this:
[[titleArray objectAtIndex:(NSUInteger *)] objectForKey:(NSString *)]
Obviously replace (NSUInteger *) with your integer row and (NSString *) with the name of your key. This may not be the answer but from your crash report and visible code, this is what I assume.

NSNumber causing a SIGABRT

I have a strange problem (strange if you ask me). Im using a NSNumber object to store a number (doh). When I try to "modify" it it crashes my application. The code I'm using looks like this:
if ([frequency intValue] > 19999)
return;
frequency = [NSNumber numberWithInt:([frequency intValue] + 1)]; //I think this line is causing me the problem
[freqLabel setText:[NSString stringWithFormat:#"%i Hz", [frequency intValue]]];
Where is frequency the NSNumber and freqLabel my label to which I write the value every time this gets called.
Why is this incorrect? It works when I call it for the first time. Is it that NSNumber numberWithInt always returns a new object which I'm trying to assign to frequency?
How do I fix this? Whats the correct way to change a NSNumber's value?
Sorry for my bad english (if there are any mistakes).
EDIT:
The error log looks like this:
[__NSCFType intValue]: unrecognized selector sent to instance 0x73430e0
2012-05-09 16:39:28.064 MyApp[31939:10703] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType intValue]: unrecognized selector sent to instance 0x73430e0'
*** First throw call stack:
(0x17a6022 0x28afcd6 0x17a7cbd 0x170ced0 0x170ccb2 0x4821 0x17a7e99 0x49d14e 0x49d0e6 0x543ade 0x543fa7 0x543266 0x4c23c0 0x4c25e6 0x4a8dc4 0x49c634 0x2e49ef5 0x177a195 0x16deff2 0x16dd8da 0x16dcd84 0x16dcc9b 0x2e487d8 0x2e4888a 0x49a626 0x1cca 0x1c15)
terminate called throwing an exception
But it doesn't always show this error. Sometimes it causes an EXC_BAD_ACCESS. Should I store my variable in a temporary NSNumber?
You can't just alloc/init something once and then you have a lifelong reference to that type. When you assign frequency to numberWithInt, then you are overwriting the previous alloc/init value with an autorelease value (which will be released later and cause the exact behavior you are describing). The reason it works with self.frequency is because your property is set as a retain property, so it automatically retains the autorelease value. Add a retain to your numberWithInt line and it will be fine (or do what you are doing now with self.frequency).
I would try doing this instead
int myNumber = ([frequency intValue] + 1);
frequency = [NSNumber numberWithInt:myNumber];
Yes, numberWithInt: does indeed return a new object. You're probably not retaining this object. Just properly retain frequency when assigning it a new NSNumber. Without context, I'm not sure the best way to accomplish this, but one way is to make frequency a property of your object and using the accessor method.
It would seem that you've already initialized and assigned some value prior to NSNumber, like you have it inside an array for example.
Basically NSNumber objects are immutable, so changing their value is not possible anyway.
You can do it this workaround if you use it inside an array:
NSMutableArray *myOldArray = [[NSMutableArray alloc] init];
myOldInt = 3;
myOldArray[4] = [NSNumber numberWithInt:myOldInt]; // for example
NSMutableArray *myNewArray = [[NSMutableArray alloc] init];
myInt = myOldInt+2;
NSMutableArray *row = [NSMutableArray arrayWithObjects:myOldArray[1],myOldArray[2],myOldArray[3],[NSNumber numberWithInt:myInt],[NSNumber numberWithInt:myInt2],nil];
[myNewArray addObject:row];

instance variables not accessible

Serious Problem here... i'm getting ECX_BAD_ACCESS if i try to NSLog an instance variable of my custom object. Following Function is called in my ViewController, payload holds String Data which is pulled from a url.
- (void) initVcardWithData:(NSString *)payload {
NSLog(#"1. initVcardWithData");
aVCard = [[vcardItem alloc] initWithPayload:payload];
VCardViewController *aVCardViewController = [[VCardViewController alloc] initWithVCard:aVCard];
[self presentModalViewController:aVCardViewController animated:YES];
[aVCard release];
}
So far so good. The initWithWithVCard function is as follows, theVCard and theVCardN are defined in #implementation and also set as a #property (nonatomic, retain) in (.h).:
-(id)initWithVCard:(vcardItem *)aVCard {
if(self = [super init]) {
theVCard = [aVCard retain];
theVCardN = [theVCard.PersonName retain];
}
NSLog(#"---- vCardViewController :: initWithVcard :: FirstName: %#", theVCard.PersonName.FirstName);
return self;
}
If i access the theVCardN object in my ViewController aVCardViewController within ViewDidLoad everything works like a charm. I set some labels with data from that object.
If i then try to access the instance variables from theVCardN within a function which is called from an IBAction which is connected to a button in View, i get an EXC_BAD_ACCESS error at the debugger console. The Function which tries to pull data from the instance variables is as follows:
-(IBAction)addressbookButtonTapped {
NSLog(#"RETAIN COUNT FOR theVCard: %i", [theVCard retainCount]);
NSLog(#"RETAIN COUNT FOR theVCardN: %i", [theVCardN retainCount]);
NSLog(#"Save to Adressbook: %#", theVCardN.FirstName);
//[self dismissModalViewControllerAnimated:YES];
}
The RetainCounter for theVCardN right before calling NSLog outputs "1". The NSLog Line then returns EXC_BAD_ACCESS in Debugger Console.
Any idea ?
Do not call -retainCount. Absolute retain counts are useless.
retainCount returns the absolute retain count of an object. The actual value will be an implementation detail that is very often completely out of your control as the system frameworks may do any number of things internally to cause the retain count to be modified in ways you don't expect.
It is useless for debugging and their are a wealth of tools that are specifically focused on tracking down these kinds of issues.
First, if there is a crash, there is a backtrace. Post it. Probably not that interesting in this case, but, still, always look to the backtrace to at least confirm that it is crashing where/how you think it is.
From the evidence posted, it sounds like theVCardN.FirstName is either set to garbage or the underlying string has been over-released. Turn on zombie detection mode and see if that is the case. Since it is crashing on FirstName, then show the code related to creating/storing the FirstName.
Also, instance variables and methods should always start with a lowercase letter; PersonName should be personName & FirstName should be firstName.
Maybe i'm reading the code wrong or misunderstanding your class structure, but it looks like you logging:
NSLog(#"Save to Adressbook: %#", theVCardN.FirstName);
Above, where you say it is still working, you are logging:
theVCard.PersonName.FirstName
Are you missing the "PersonName"? Meaning you should be logging:
NSLog(#"Save to Adressbook: %#", theVCardN.PersonName.FirstName);

Accessing a UITextField from an array in Objective-C

I have 4 UITextFields that I'm dynamically creating, in the viewDidLoad, which works good. I want to reference those objects when the UISlider value changes. Right now I'm storing those objects in a NSMutableArray and accessing them like so from the sliderChanged method:
NSInteger labelIndex = [newText intValue];
labelIndex--;
NSUInteger firstValue = (int)0;
NSMutableArray *holeArray = [pointsArray objectAtIndex:labelIndex];
UITextField *textField = [textFieldArray objectAtIndex:firstValue];
NSString *newLabel1Text = [[NSString alloc] initWithString:[[holeArray objectAtIndex:firstValue] stringValue]];
[textField setText: newLabel1Text];
[newLabel1Text release];
Everything is working good, but the program crashes on the setText: method. The last message I get from the program is: [UILabel drawTextInRect:] and then I get a EXC_BAD_ACCESS failure.
I want to be able to acces that dynamically created UITextField, but I must be going about it the wrong way.
Thanks!
Uh, yea, you create a text field, but you aren't displaying the field itself, just creating it.
If you want to do what I think you want to do, I would just do if statements.
ex.
if (firstValue == 1)
{
fieldone.text = #"whatever";
}
else if (firstValue == 2)
{
fieldtwo.text = #"whatever";
}