iPhone application error. NSString with whitespace - objective-c

I am having a major problem with my iPhone app. My problem seems basic but I cannot find out the reason for the error. I have a NSString saveDescription that is set by user's input.
savede = civilsJobDescTb.text;
I then call in a NSLog to check the string has been set, and it is. So I have no problem there.
Later in the program I create a PDF file with several details. Everything works ok except the NSString that I have set earlier. It seem as if the string no longer exists. I get an error from it. EXC_BAD_ACCESS or something like that.
Now for the weird thing. This only happens when I have a whitespace in the text box. Eg: I enter "ok" and it will work without problem. But if I enter "Everything is ok" then I get errors.
I can't see where the problem is. Any ideas?

You didn't specify if your "savede" is an ivar (instance variable) but assuming that it is,
and if you are using ARC, set a strong property to it:
#property (nonatomic, strong) NSString * savede;
self.savede = civilsJobDescTb.text;
If you are not using ARC, then make sure to retain your "savede" string after setting it. Something like:
savede = civilsJobDescTb.text;
[savede retain];
(making sure to release it when you are truly finished with it).
You can also make a copy of the string (in case the label that it's coming from disappears, or is cleared, or somehow disappears).
[savede setString: civilsJobDescTb.text];
[savde retain];

Related

NSString isEqual strange bug

I have a web server which I used to fetch some data in my iOS application. The data include a field as the itemId let say '48501' (with no quotation). I read item JSON data into my itemObject in which itemId is defined as a NSString and not a NSInteger.
Everything works until this point but I have problems where I want to compare itemObject.itemId using isEqual: function with another NSString filled with 48501.
In other words both string are exactly the same and include 48501 when I print them. No space and hidden things is there. All isEqual: and isEqualToString: and == report false on comparison.
On the hand when I convert NSStrings to NSIntegers and compare them it works but not always! sometime TRUE sometime CRASH with no error to catch and just pointing to the line! I see them printed exactly the same but the if statement does not go through.
I showed the code to someone with far more experience than me and he was like this could be a bug! Anyone has ever exposed to this?
If your itemId is 48501 without any quotation in the JSON, then it's deserialized as NSNumber. Probably that's the problem in the first place. Try logging the type of your itemId and use appropriately -isEqualToString: for NSString and -isEqualToNumber: for NSNumber.

Changing value of a NSString

I am having problems changing the value of an NSString.
It is declared in my class like this:
#property (strong, nonatomic)NSMutableString *votes;
When the object is created, it is set like this:
song.votes = [dict objectForKey:#"Votes"];
And finally is where the trouble occurs. Later in my code I try to modify the value like this:
song.votes =[responseArr valueForKey:#"CNT"];
This line is leading to this crash:
'NSInvalidArgumentException', reason: '-[__NSCFString setVotes]:
unrecognized selector sent to instance 0x14f84430'
I'm think my problems is caused by one of these:
1. Incorrectly setting the properties above. I've tried setting it as (copy, nonatomic) as well but it does the same thing.
2. i need to use an NSMutableString for this. I tried changing it to NSMutableString but it still crashes when it changes (admittedly I am initializing and changing it the way way when using NSMutableString, am not entirely sure how to change things when its Mutable.
I think the problem is in the way you're allocating / setting your song object. Somewhere between setting the first and the second value, you're probably deallocating song and then trying to set it's properties, or you're modifying it in such a way that it's not the same class type anymore.
unrecognized selector sent to instance 0x14f84430' pretty much sums it up for you. The second time you try to set the votes property, it tries to access the synthesized setter (setVotes) from song which is no longer the class you think it is.
From the error it looks like you may be re-allocating song as a NSString object. That's why it's trying to access a setVotes method on NSString and such a method does not exist, so it bails out and crashes.
Are you sure you're not doing something like song = [someString retain]; ?
Use -mutableCopy if you need a mutable copy of your NSString.
song.votes = [[dict objectForKey:#"Votes"] mutableCopy];
Assuming responseArr is an array, [responseArr valueForKey:#"CNT"] returns an array with the return value of each of the instances in responseArr. Your property is for a NSMutableString, but you set it to a NSArray.
(Also, do provide the actual error that you get when you crash instead of just saying 'it crashes'.)

Xcode: #dynamic class variable not working

I have a class which declares a User and includes these variables:
(User.h file):
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSString * unid;
(User.m file):
#dynamic name;
#dynamic unid;
I have an array of values by parsing a string.
I then want to set the values accordingly:
(ViewController.m file):
[user setName:[returned objectAtIndex:1]];
[user setUnid:[returned objectAtIndex:2]];
When this is run the compiler gives me the following error:
unrecognized selector sent to instance
*** WebKit discarded an uncaught exception in the webView:shouldInsertText:replacingDOMRange:givenAction: delegate: <NSInvalidArgumentException> -[User setName:]: unrecognized selector sent to instance
When I comment out the setName line it works fine.
I then looked at the classes of the two objects from the returned array and they were both: __NSCFString
I then tried this piece of code:
(ViewController.m file):
[user setName:[returned objectAtIndex:2]];
Again the same error.
Why would the same input fail in one case and succeed in another if they are both expecting the same input?
Thanks.
EDIT:
This error is weird as this part of the app does not interact with any webviews. This returned array is parsed from a string gather from a webpage:
(ViewController.m file):
NSString *string = [NSString stringWithContentsOfURL:[NSURL URLWithString:#"http://url_goes_here.com" encoding:NSUTF8StringEncoding error:&error];
NSArray *returned = [returned componentsSeparatedByString:#"#"];
However the unid is also parsed from this array without any problem.
The #dynmaic keyword means that you'll be providing the accessors yourself. If you want the compiler to create accessors for you, simply delete the #dynamic name declaration. (Because #synthesize is now the default, you don't have to use it explicitly.) Otherwise, you'll need to create the -name, -setName:, -unid, and -setUnid: methods yourself.
it is actually a set up class by xcode using the NSManagedObject subclass for core data
This is an important detail. In the case of managed objects, Core Data will provide the accessors for you and you just need the #dynamic property declaration to let the compiler know that it shouldn't generate accessors itself.
I'm a little confused as to why this error is coming from a web view delegate method. It might help if you could explain a little more about how your Core Data classes are interacting with a web view.
why would this work for the unid, but not the name
The error you're getting is an run time error -- an exception is being thrown. It's likely that the name accessor is simply the first one to be used; the same thing might happen for unid if that property were to be set first.
This error is weird as this part of the app does not interact with any webviews.
Another important clue. At this point, it sounds very much like you've got a bad pointer. You're sending -setName: to an object that's not what you think it is, and in this case it turns out to be a web view delegate. Try turning on NSZombies to help you track this down.

NSString category method not called after creating NSSavePanel

I have a simple Cocoa application (39 KB zipped) that consists of an application delegate (AppDelegate) and an NSString category (and a default window that does nothing).
In its init method, the AppDelegate creates an NSSavePanel. Before and after it does this, it logs the length of a string trimmed of whitespace and newlines by an NSString category method: stringByTrimmingWhitespace.
The string consists of whitespace and newline characters. My category method should trim all of these characters, resulting in a 0-length string.
Before the NSSavePanel is created, my stringByTrimmingWhitespace method is called and returns a 0-length string, as expected. After the NSSavePanel is created, my stringByTrimmingWhitespace method does not appear to be called, and whatever method is called does not trim newlines. However, a different NSString category method that does exactly the same thing—stringByTrimmingWhitespaceAndNewlines—is called and works as expected.
I have absolutely no idea what is causing my stringByTrimmingWhitespace to not be called or how to fix it (besides renaming it, which is what I’ve done). I’m also concerned that other category methods on other classes may be getting trashed. Does anyone know what’s happening here?
It seems as though NSSavePanel is loading a category on NSString for its own use, with a method whose name conflicts with your -[NSString(TurnerAdditions) stringByTrimmingWhitespace] method. You can verify with this code:
NSString *foo = #"!";
NSLog(#"Responds to '-stringByTrimmingWhitespace': %#", [foo respondsToSelector:#selector(stringByTrimmingWhitespace)] ? #"YES" : #"NO");
NSSavePanel *panel = [NSSavePanel savePanel];
NSLog(#"Responds to '-stringByTrimmingWhitespace': %#", [foo respondsToSelector:#selector(stringByTrimmingWhitespace)] ? #"YES" : #"NO");
Why it doesn't behave the same as yours is somewhat strange (edit: no it's not, see #rdelmar's comment).
You should always be prefixing the method names in your categories, specifically for instances like this. Cocoa naming conventions are fairly explicit, which makes it very likely to have name conflicts. Because of the way categories are handled (e.g. they can be loaded in the middle of an app's execution without your knowledge) it's difficult/impossible for the compiler to provide conflict errors.

NSString unexpectedly becomes __NSCFDictionary

I have this very strange problem, I'm new to objective-c and it probably comes from depths which I don't comprehend yet.
So, in my header file I declare the variable
NSString *curTitle;
then in .m file I synthesize it:
curTitle = [[NSString alloc] init];
after that in other method I assign it:
curTitle = string; // string is an instance of NSString
and at the end of the day when I'm trying to assign
slide.title = curTitle; //slide is a managed object (CoreData)
I'm getting this error: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "title"; desired type = NSString; given type = __NSCFDictionary; value = {
}.'
Interesting fact that in iphone SDK 3.2 it worked, but after I installed SDK 4 I have this error
Another interesting fact that if make my curTitle property of my class (with #property and #synthesize) it also works
Any ideas?
Thanks
When an object seems to change class, it's almost always because it has been deallocated, and another object is now residing on the same memory location. All object variables are actually pointers to memory locations (that's what the * means), and unlike in many other languages you have to always remember that you're working with memory locations. (Well, not always, once you get the hang of it. But definitely when you're debugging.)
To debug these problems, it can be very useful to use NSZombie. Just search SO or the web for info.
then in .m file I synthesize it:
curTitle = [[NSString alloc] init];
This is not synthesizing. What you are doing here is merely assigning a value to the variable. More precisely, you create an object somewhere in memory (alloc) and initialize it (init) and then you set the value of curTitle to point to that memory location.
There is no need for you to have this line in your code at all.
curTitle = string;
Here you are overwriting the old value of curTitle with a pointer to another string. Your problem is most likely that that other string later gets deallocated, and the memory location gets reused to hold another object (a dictionary in this case). (If you don't know about the retain/release mechanisms, you need to read up on those to understand what happens.)
slide.title = curTitle;
Since curTitle is pointing to a memory location that has been re-used to hold a random object (or even worse: garbage) this line will fail. In fact, you're lucky that it fails, because if it didn't (if the location hadn't been reused yet) it would be even harder to detect the bug.
What you should do is to declare a property, then synthesize it and access the variable through the property:
self.curTitle = aString;
This will make sure that you actually copy and take ownership of the string so that even if the original string is released, you will still have a valid copy.