EXC_BAD_ACCESS when using stringWithFormat? - ios

While deploying my application, I got the error message: "Thread 1:Program received signal: "EXC_BAD_ACCESS".
My code is below:
-(NSDictionary *)syncWithList:(NSInteger)listID
{
NSString *urlit = [NSString stringWithFormat:#"http://0.0.0.0:3000/lists/%#/syncList.json?auth_token=%#",#"xxxxxxxxxxx",listID];
// **Here I got the error message: "Thread 1:Program received signal: "EXC_BAD_ACCESS"**
NSLog(#"url: %#",urlit);
NSURL *freequestionurl = [NSURL URLWithString:urlit];
ASIHTTPRequest *back = [ASIHTTPRequest requestWithURL:freequestionurl];
[back startSynchronous];
self.listData = [[back responseString] objectFromJSONString];
NSLog(#"%#",listData);
NSDictionary *dicPost = [listData objectAtIndex:0];
return dicPost;
}
Thanks a lot!!!!

You must not format NSInteger (which is just a typedef'd int on current iOS versions) with the %# specifier. Writing %# in a string format basically means "call description on the object and use the result".
But NSInteger is not an object, it's a primitive type.
You get a memory exception because when listID is 42 you access an object at memory address 42. This is definitely not what you want.
-(NSDictionary *)syncWithList:(NSInteger)listID
^^^^^^^^^
NSString *urlit = [NSString stringWithFormat:#"http://0.0.0.0:3000/lists/%#/syncList.json?auth_token=%#",#"xxxxxxxxxxx",listID];
^^
just use the %i format specifier instead of %# for listID.
NSString *urlit = [NSString stringWithFormat:#"http://0.0.0.0:3000/lists/%#/syncList.json?auth_token=%i",#"xxxxxxxxxxx",listID];

EDIT: So used to getting errors from Xcode without it giving me any clues I neglected to notice that the troubled line was already know. I'll leave this here in the hope it helps someone in future.
Try creating an exception breakpoint, it may point to straight to the line where your code is falling over which should help you figure out the problem.
Switch to the breakpoint 'tab' in the left hand navigator.
Click the little '+' at the bottom.
Create a breakpoint as shown in the image:
Run your code and see where it pops.

You used wrong data type to print out.
NSLog(#"%#",listData);

You made very popularar mistake in this line
NSString *urlit = [NSString stringWithFormat:#"http://0.0.0.0:3000/lists/%#/syncList.json?auth_token=%#",#"xxxxxxxxxxx",listID];
Second argument is of type NSInteger, but in format you use %#, this is object only, and compiler thinks that your listID is address of object.
Correct format is %li:
NSString *urlit = [NSString stringWithFormat:#"http://0.0.0.0:3000/lists/%#/syncList.json?auth_token=%li",#"xxxxxxxxxxx",listID];

Related

Unusual stringWithFormat: argument

I apologize if this is a noob question.
I have been following this tutorial about mapkit and I stumbled on this line of code
NSString *json = [NSString stringWithFormat:formatString,
centerLocation.latitude,
centerLocation.longitude,
0.5 * METERS_PER_MILE];
The reason this is unusual at least to me is that it is missing the nsstring that has the %# flags in it. The tutorial claims that we are adding the latitude and longitude information into the json.
But when I print out formatString and json, the output is identical.
I have never seen nsstrings used in this way before. Is there a hidden variable that is getting set?
Can someone explain to me how this nsstring object (named json) contains those 4 arguments?
Someplace else in the code, formatString must be defined something like this:
NSString *formatString = #"latitude=%f, longitude=%f, %f = half the number of meters in a mile";
Make sure your test looks like this:
NSLog(#"the format is %# and the json is %#", formatString, json);
They shouldn't look the same. The only way they would look the same is if format string doesn't refer to any format specifiers, like this:
NSString *formatString = #"I'm a silly format with no percent format specifiers";
Here's a good intro on the topic from Apple.
That formatString actually contains the %#'s. It might be like this:
NSString *formatString = #"lat: %f | lon: %f | half-meters-per-mile: %f";
NSString *json = [NSString stringWithFormat:formatString,
centerLocation.latitude,
centerLocation.longitude,
0.5 * METERS_PER_MILE];
(note that the substitutions (%f) might not be correct, I'm guessing)
As for how it contains those four arguments, everything after the first one are values that you want added into the string. The first one is a string that says where to put those values.
If you check the tutorial, following line of code is written above what you have posted-
NSString *jsonFile = [[NSBundle mainBundle] pathForResource:#"command" ofType:#"json"];
NSString *formatString = [NSString stringWithContentsOfFile:jsonFile encoding:NSUTF8StringEncoding error:nil];
From here the format string is created, this file will be available in the resources folder of your tutorial.

simple calculator app, presents SIGABRT error when I add new button

I'm new to Objective-C programminga nd X-Code so please bear with me. I copied code from a book about objective C to make a calculator class and it's working wonders. Then it asked me as part of the exercises to add a convert button to convert a fraction to a double and print it. The thing is that when I press the convert button, the app stops and I get a message saying that the program received a SIGABRT signal.
Here is the button code:
-(IBAction)clickConvert //convert method
{
if ( [myCalculator accumulator] != 0 ){
displayString = [NSString stringWithFormat: #"%e", [myCalculator convertResult]];
display.text = displayString;
[displayString setString:#""];
}}
The convertResult code:
-(double) convertResult
{
double convertedFraction;
convertedFraction = [accumulator convertToNum];
return convertedFraction;
}
(accumulator is a Fraction object that contains the value of the mathematical operation done on the 2 operands)
and the ConverToNum function:
-(double) convertToNum
{
if (denominator != 0)
return (double) numerator/denominator;
else
return NAN;
}
everything else in teh app works fine, so it must be a problem with what I've done......can anyone help? I've been searching online all day, but I read completely different stuff about this SIGABRT error. Thank you for your help
If displayString is an NSString, then there is no setString setter. Just assign the string to displayString.
Instead of
[displayString setString:#""]
do:
displayString = #"";
Edit:
You say that displayString is an NSMutableString. In that case, your first assignment to displayString:
displayString = [NSString stringWithFormat: #"%e", [myCalculator convertResult]];
assigns an immutable object to the displayString pointer. I don't know why the compiler isn't complaining about that. Then when you try to call setString on displayString, the actual type of the object is NSString even though you have declared the pointer to be an NSMutableString. To fix this, try:
displayString = [[NSString stringWithFormat: #"%e", [myCalculator convertResult]] mutableCopy];
or:
[displayString setString:[NSString stringWithFormat: #"%e", [myCalculator convertResult]]];
or:
displayString = [NSMutableString stringWithFormat: #"%e", [myCalculator convertResult]];

Output to UITextField

I have a NSDictionary with some parameters i want to display in a UITextField.
but
firstname.text = [userdata objectForKey:#"firstname"];
throws an exeption.
If i use NSLog on [userdata objectForKey:#"firstname"]; it shows the right value. What seems to be the problem here?
Just use the following code:
firstname.text = [NSString stringWithFormat:#"%#",
  [userdata objectForKey:#"firstname"]];
go on .. :)
When you NSLog something it uses [object description] to convert the object to a string for output. If the object stored in your dictionary is not an NSString and you try to assign to firstname.text you will get an exception.
Another problem you may be facing is your firstname object may not be pointing at what you think it is. This may occur, for example, if you are not using ARC and you forgot to retain it or you already released it.
The exact exception you are seeing will determine which of these you are encountering.
Tried to do something like
[NSString stringWithFormat:#"%#",[userdata objectForKey:#"firstname"]];
firstname.text = nameString;
?

Over-release an object and the app does not crash

#property (retain) NSString *testString;
self.testString = [[NSString alloc] initWithString:#"aaa"];
[self.testString retain];
self.testString = [NSString stringWithString:#"a"];
[self.testString release];
[self.testString release];
Let's go line by line:
Line 2: retain count of testString = 2
Line 3: retain count of testString = 3
Line 4: retain count of testString = 1
Line 5: retain count of testString = 0
Line 6: it should crash
Even if there's other stuff holding to testString in CoreFoundation, it eventually will go away. But the app never crash due to this.
Anyone could explain this? Thanks!
see this code and its log:
NSString *string1 = [NSString stringWithString:#"a"];
NSString *string2= #"a";
NSLog(#"String1: %p", string1);
NSLog(#"String2: %p", string2);
2012-03-22 13:21:49.433 TableDemo[37385:f803] String1: 0x5860
2012-03-22 13:21:49.434 TableDemo[37385:f803] String2: 0x5860
as you see [NSString stringWithString:#"a"]; doesn't create a new string, it uses the string literal #"a". And string literals can't be deallocated.
Try your code with NSMutableString and you will see a crash.
I am not an expert about this, so please take this with a grain of salt. I guess that [NSString stringWithString:#"a"] will probably just return the literal string #"a", i.e. it just returns its argument. As #"a" is a literal, it probably resides in constant memory and can't be deallocated (so it should be initialized with a very high retain count).
[NSString stringWithString:#"a"] returns an autoreleased object. That means "the true" retain count is 2 not 1 in line 4. In line 6 you are overreleasing your variable but the crash will happen later - on the autorelease pool drain.

Fast Enumeration error?

Getting a warning saying that:
Collection expression type 'NSString *' may not respond to 'countByEnumeratingWithState:objects:count'
when trying to run the following code:
NSString *proper = [NSString stringWithContentsOfFile:#"usr/share/dict/propernames" encoding:NSUTF8StringEncoding error:NULL];
for (NSString *i in proper){
NSLog(#"Item>%#", i);
}
When I run the program I don't get any output from the NSLog statement. Anyone run into this?
The compiler warning is trying to tell you that you cannot iterate over an NSString using a for ... in ... loop. It is further trying to say than the reason for this is that an NSString is not a valid "Collection" type. Your valid "Collection" types are things like NSArray, NSSet, and NSDictionary.
So if your file is supposed to contain structured data, you should parse it into something more useful than a flat NSString. Something like this may give a better result:
NSString* temp = [NSString stringWithContentsOfFile:#"usr/share/dict/propernames" encoding:NSUTF8StringEncoding error:NULL];
NSArray* proper = [temp componentsSeparatedByString:#"\n"];
for (NSString* i in proper){
NSLog(#"Item>%#", i);
}
That will print each line in the file. This assumes, of course, that your input file has one entry per line. If it is structured some other way, then you will have to parse it differently.
After you load the file, split it into lines with componentsSeparatedByString: .
NSArray *lines = [proper componentsSeparatedByString:#"\n"]; // Use the correct line ending character here
for (NSString *i in lines) {
NSLog(#"item> %#", i);
}
This is a clear mistake u have here.
NSString* is a string object and is not a collection of characters as the string object known in C++ which is a character array.
for-in Loop need a collection to iterate within. like NSArray or NSSet.

Resources