NSString Memory Bug/Crash - iphone

I have UITextField of username and password, once the user hit the submit button I do
NSString* user_name;
NSString* pass_word;
UITextField * username;
UITextField * password;
NSString * url;
user_name=username.text;
pass_word=password.text;
url = [[NSString stringWithFormat:#"devices.json?user=%#&pswd=%#", user_name,pass_word];
However, when I try that, sometimes I got EXEC_BAD_ACCESS issue with url, I used the Zombie tool and nailed it %# is the one causing issue with url string. %# expecting a NSString of user_name, pass_word but somehow in the process, the user_name and pass_word got mutated and got some junk values, not NSString anymore.
I try to use [user_name retain]; [pass_word retain]; [url retain]; but didn't help. It keep having EXEC_BAD_ACCESS issue with %# parameter of the url.
secondly I able to output the user_name, pass_word, it sometimes got some values that doesn't make sense. I don't where they got those values. I didn't put those values in. I am making a http call. somehow the http returned values sneaked inside the pass_word, and user_name, I have no idea why it's doing that.

secondly I able to output the user_name, pass_word, it sometimes got some values that doesn't make sense.
this usually means that you assign not initialized variables... and it explains the crashes if you try to nslog the values. but it's not possible to find out what's wrong from the part of the code you have included in your answer.
try to log the contents of username and password. (the uitextfields) .. you should use better variable names.

From a comment:
I declare NSString *user_name, *pass_word in common.h file which many
files need to access that one.
Unless you've got a singleton class, every time you alloc/init a new Common object it's going to have trash values. Objective-C best practices recommend against this sort of design. For most data, it's fine to store in a plist or in NSUserDefaults, but for the username and password string, you should store it in the keychain. Even better, you should store your password as a hash if the server will accept it.
Then use a category on NSString (call it something like NSString+Authentication) that has methods to pull the data from the keychain as well as insert it into the keychain.

Try using the allocation as well and see if it helps:
url = [[NSString alloc] initWithFormat:#"devices.json?user=%#&pswd=%#", user_name,pass_word];

Related

Object is deallocated - why? where?

Ok, I spent the last 8 hours fighting with it - it just seems beyond me. Here's my complete (relevant) code:
- (void)updateUserDefaults
{
NSMutableDictionary *viewControllerDetails = [[NSMutableDictionary alloc] initWithCapacity:4];
[viewControllerDetails setObject:[NSNumber numberWithInt:OOVenueClassControllerType] forKey:#"classType"];
[viewControllerDetails setObject:self.searchTerm forKey:#"searchTerm"];
[viewControllerDetails setObject:self.searchLocation forKey:#"searchLocation"];
//----- the next two lines cause the problem
NSString *res = [[NSString stringWithFormat:#"%#",[searchResults xmlString]] retain];
[viewControllerDetails setObject:res forKey:#"searchresults"];
//-----
NSMutableArray *viewControllersList = [NSMutableArray array] ;
[viewControllersList addObject:viewControllerDetails];
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
//the following line causes the error
[defs setObject:viewControllersList forKey:kViewControllersKey];
[defs synchronize];
[res release];
}
Note the block with the next two lines cause the problem. At first I didn't create another string, but added it later while trying to solve the problem.
If I comment out those two lines, everything works fine. If I put them back in, I get
- [CFString class]: message sent to deallocated instance 0xa1a9000
Is something is wrong with the string that I'm trying to put into the userdefaults? That string is rather large (about 200,000 characters), but I had stored even longer strings in user defaults in the past.
It's also worth noting that if I uninstall the app, then everything works fine. But on subsequent runs the problem exhibits itself.
So, how and why and where is the string getting deallocated? I have explicitly added retain - but that still doesn't help. What am I missing?
Edit: just realised I forgot to say that the error is thrown on line
[defs setObject:viewControllersList forKey:kViewControllersKey];
Also, for general information, method - (NSString *)xmlString on searchResults does exactly what the name means: creates an XML string with the information from that object.
Edit 2: I tried doing something else with that string - convert it to NSData, compress using zlib - but regardless of data type, that particular object gets deallocated. Does it have to do something with the size of the string?
NSString *res = [[NSString stringWithFormat:#"%#",[searchResults xmlString]] retain];
Is auto released. You don't need to release it at the end of your method. You are over-releasing it.
Further, you don't need to retain the [searchResults xmlString]. The stringWithFormat method already does it for you.
Good Luck!
Ok, not sure what exactly the problem was, but it was somewhere in the searchResults and/or xmlString method. searchResults object is originally created from XML received from the server (XML is parsed into the object structure). When xmlString was called, for some reason the string I was getting back was different from the original XML (I'm not talking about formatting, of course) - of 200,000 char-long string, within the first 500 chars or so there were some differences. I haven't been able to figure out why. So, instead of recreating the xml from object structure, I instead stored the original XML in a field in that object and, when xmlString was called, simply returned the original string. Now everything worked fine.
Thank you all for your support through this painful process.

iPhone: Reading a string from a file is returning the wrong results

What I'm doing:
I am reading some data off a file several times while my app runs. I use the following code to do so:
NSString *dataPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"data.txt"];
NSString *data = [NSString stringWithContentsOfFile:dataPath encoding:NSStringEncodingConversionExternalRepresentation error:NULL];
NSArray *components = [data componentsSeparatedByString:#"|||||"];
The first time this is called, it works as expected - I get an array of length 5, each section containing a relevant string.
What goes wrong:
This file is never modified. Yet, when I call the same procedure a second time (or third, fourth etc) I don't get the same result. Instead, an array of length 1 is returned, containing only part of the necessary data.
Why? I can't see any reason for this to go wrong... any help is much appreciated!
Since the file is in you AppBundle this means that you can't modify this file at all.
Are you sure that, where ever this code is called, the autorelease object are retained correctly?
If you call this block of code every time you want this data, it might be an idea to save the results of the first time and use that every time. This will speed things up a bit.
Turns out that the code works fine. The problem was elsewhere in my code, where I was (accidentally) accessing protected directories. As a result, iOS blocked my app from accessing any files at all :o

Why am I seeing the error "Format is not a string literal and no format arguments"?

i am creating a music application in iphone where i am integrating twitter in my iphone so that a user can listen to a particular song click on the twitter tab ,log in to twitter and post his comment in to twitter.and i need that his username and password should be saved when he click on save username and password button so that he remain logged in when he is in the application.
I have done the code of saving username and password but i get an error indicating that ""FORMAT IS NOT A STRING LITERAL AND NO FORMAT ARGUMENTS""
Here is my code:
-(IBAction)SaveAll:(id)sender{
UsernameString =[[NSString alloc]initWithFormat:text1.text]; "FORMAT IS NOT A STRING LITERAL AND NO FORMAT ARGUMENTS"
[text1 setText:UsernameString];
NSUserDefaults *UsernameDefault =[NSUserDefaults standardUserDefaults];
[UsernameDefault setObject:UsernameString forKey:#"Stringkey"];
PasswordString =[[NSString alloc]initWithFormat:text2.text]; "FORMAT IS NOT A STRING LITERAL AND NO FORMAT ARGUMENTS"
[text2 setText:PasswordString];
NSUserDefaults *PasswordDefault =[NSUserDefaults standardUserDefaults];
[PasswordDefault setObject:PasswordString forKey:#"Stringkey2"];
}
Please help me in solving this problem so that when i click on the username and password button my username and password should be saved.
Use InitWithFormat if you want to create a String that is composed by several components, like a string and an integer for example then you would do something like this
NSString *myString = [NSString stringWithFormat:#"%# costs %i"itemName, itemprice];
itemName would be an NSString Object, itemprice would be an integer.
in your case, try doing it the following way:
UsernameString =[[NSString alloc]initWithString:text1.text];
or even easier
UsernameString = text1.text;
note:
I would NOT recommend to store Passwords or any other sensitive information into userdefaults
a better (more safe/secure way) to store passwords is to use the devices keychain, where stored information is heavily encrypted and access happens in a safe way.
also it's easy to use:
Simple iPhone Tutorial: Password Management using the keychain by using SFHFKeychainUtils
Hope that helps.

iPhone: Reading Text From File and UISegmentedControl

First off, I'm a complete beginner.
That said, I thought an ambitious longer-term project/learning experience would be to create an app that displayed daily quotes, like those cheesy day-by-day calendars our grandmothers have in their bathrooms. I want it to have two per day, each one represented by a tab in a UISegmentedControl. That's the long term. Right now I'd be happy with getting a single day's worth of quotes functioning.
Onto the questions:
How can I get text saved in a .txt or .rtf file to be displayed in a UITextView? Preferably without using 'stringWithContentsOfFile,' since Xcode is telling me that's deprecated.
How can I get content from a different file (or maybe a different portion of the same file...?) to be displayed when the user taps the second segment?
If I can get it running so that those two conditions are met and I understand what's going on, I'll consider the day a success. Thanks!
1.
NSError *error = nil;
NSStringEncoding stringEncoding;
NSString *fileText = [NSString stringWithContentsOfFile:#"/path" usedEncoding:&stringEncoding error:&error];
myTextView.text = fileText;
The error and encoding are optional, and you can pass in nil for both. But if you care about the error, or what encoding the file was in they will have useful info in them after the string is created.
2.
Set the valueChanged outlet in Interface Builder to an IBAction on your controller, such as setSegmentValue:. Then, assuming you have an array of quote strings:
- (IBAction)setSegmentValue:(id)sender {
UISegmentedControl *control = (UISegmentedControl*)sender;
NSString *quote = [quotes objectAtIndex:control.selectedSegmentIndex];
myTextView.text = quote;
}
Even though stringWithContentsOfFile: is deprecated, stringWithContentsOfFile:usedEncoding:error: is not. That is the standard method to use for reading from files.
As for the second question, you simply test the state of the segmented control and perform as action based on it. Admittedly this is a high level answer but should get you going.

"Invalid" iphone string

I'm converting data (from a web page) to a string). The basic code works (but there's been some subtle change somewhere - maybe on server).
NSLog shows the expected string (maybe 1000 chars long). However, when I float over responseString, it shows "Invalid". Worse, parsing with componentsSeparatedByCharactersInSet does not work.
Ideas?
NSString *responseString;
responseString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSLog([NSString stringWithFormat:#"responsestring ='%#'",responseString]);
if ([responseString compare:#""] != NSOrderedSame) {
lines = [responseString componentsSeparatedByCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:#";"]];
This may happen when the configuration is set to "Release" rather than "Debug" I think.
Do not trust what the debugger says, it is not accurate, this has happened to me and took me a while to realise that the xcode debugger is not always right and should not be trusted, so i no longer trust the debugger and i use nslog statements whenever it tries to tell me something is invalid. So dont worry about it it happens, and when it happened to me I was also parsing responses from some webservice.
Just to be clear -- my experience with seeing "Invalid" in the debugger means that the reference is to an already-released object.
Your question and the comments below seem to suggest that you are thinking "Invalid" is an actual string value -- but are you sure you don't just have a memory management probably?