Trying to retrieve only NSStrings excluding whitespace from UITextField in iOS - ios

I am working on an iOS application where a user is required to enter their first and last name into a UITextField. Now, I want my UITextField to be able to check to see that the user has entered:
(1) two names and (2) each name is a minimum of two characters.
My problem is that when I retrieve the name(s) from the text field, I am unable to distinguish between an empty NSString (i.e. " "), and an NSString that is composed of characters. Because of this, when I check to see what the length of the shortest word that has been entered is, the empty spaces are always counted as being valid strings, which I don't want. So in other words, if a user enters:
" larry bird "
I need the string count to be two, and the length of the shortest word to be 4 (thus passing both tests). So I need the leading, trailing whitespaces as well as the whitespaces in between to be removed, but keep the NSString objects that are valid to be distinct.
Here is the code that I have thus far:
NSString *name = [textField text];
NSArray *trimmedArray = [name componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSMutableArray *trimmedNames = [NSMutableArray array];
for (NSString *cleanString in trimmedArray) {
NSString *trimmedString = [cleanString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSLog(#"The trimmed name is: %#", trimmedString);
[trimmedNames addObject:trimmedString];
}
self.alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Please Enter Full First and Last Name" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
if(trimmedNames.count > 1) {
NSNumber *lengthOfShortestWord = [trimmedNames valueForKeyPath:#"#min.length"];//here is where I am counting the characters in the smallest string entered the textfield
if (lengthOfShortestWord.intValue > 1) {
[textField resignFirstResponder];
}
else if (lengthOfShortestWord.intValue <= 1) {
[self.alert show];
}
}
else if (trimmedNames.count < 2) {
[self.alert show];
}
Does anyone see what it is that I am doing wrong?

Trim the white space from the initial string from the text field.
NSString *name = [[textField text] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
Now you don't need to trim each individual string.

Related

how to reveal all string padding from txt file in Xcode?

I making a word game so Ive set all the word in a .txt file, and i've added a show 1st letter button:
Code:
if ([buttonTitle isEqualToString:#"reveal"]) {
UIAlertView *alertuser;
NSString *prla = [NSString stringWithFormat:#"%#", [lst_word objectAtIndex:nCurrentWord]];
NSString *finished = [[prla substringToIndex:1] stringByPaddingToLength:prla.length withString: #"_" startingAtIndex:0];
alertuser = [[UIAlertView alloc]initWithTitle:#"This is the first letter:" message:finish delegate:self cancelButtonTitle:#"Thanks" otherButtonTitles:nil, nil];
[alerta show];
How would I make it show and reveal all the letters from the word in the .txt file?
NSString *finishText = [[prlt substringToIndex:1] stringByPaddingToLength:prlt.length withString: #"_" startingAtIndex:0];
alerta = [[UIAlertView alloc]initWithTitle:#"First Letter is:" message:finishText delegate:self cancelButtonTitle:#"Thanks" otherButtonTitles:nil, nil];
[alerta show];
I need this reversed to allow the full answer from the txt file!
substringWithRange: may be the function you are looking for.
The sample code below will print word by word of a string
NSString *sampleString = #"abcedefgh";
for(int i = 0; i < [sampleString length]; i++)
{
NSLog(#"word = %#", [sampleString substringWithRange:NSMakeRange(i, 1)])
}
EDIT:
In place of
NSString *finishedText = [[prlt substringToIndex:1] stringByPaddingToLength:prlt.length withString: #"_" startingAtIndex:0];
use below code, this will solve your issue
NSString *finishedText= [prlt substringWithRange:NSMakeRange(0, prla.length)];

Pull first name and last initial from string

I have an NSString that contains a users full name. Some names are in the standard first and last formation (Kyle Begeman) and others are just a single name (TechCrunch).
How would I grab the first name as is and then the first initial of the last name, and if there is only one name, just grab the whole name?
Basically I want the above to be turned into Kyle B. or just TechCrunch depending on the name.
NSString *username = #"Kyle Begeman"
NSString *otherUserName = #"TechCrunch"
converted to
#"Kyle B"
// No conversion because it is a single word name
#"TechCrunch"
Using substringToIndex is how I can grab the first letter in the whole string, and I know there is a way to separate the string by #" " whitespace into an array but I can figure out how to easily produce the result the way it needs to be.
Any help would be great!
(NSString*)firstNameWithInitial:(NSString*)userName {
NSArray *array = [userName componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
array = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF != ''"]];
NSString *firstName = [array objectAtIndex:0];
NSString finalNameString;
if ([array count] > 1) {
NSString *lastNameInitial = [[array objectAtIndex:1] substringToIndex:1];
finalNameString = [firstName stringByAppendingString:[NSString stringWithFormat:#" %#", lastNameInitial]];
else {
finalNameString = firstName;
}
return finalNameString;
}
This function should return what you need. Note that you can modify this to work with people who have more than 2 names, by checking the number of objects in the array.
Find a position pos of the first space in the string. If there is no space, or if the space is the last character of the string, then return the entire string; otherwise, return substring in the range from zero to pos+1, inclusive:
NSRange range = [str rangeOfString:#" "];
if (range.location == NSNotFound || range.location == str.length-1) {
return str;
} else {
return [str substringToIndex:range.location+1];
}
You could use NSScanner to find substrings.
NSString *name = #"Some name";
NSString *firstName;
NSString *lastName;
NSScanner *scanner = [NSScanner scannerWithString:name];
[scanner scanUpToString:#" " intoString:&firstName]; // Scan all characters up to the first space
[scanner scanUpToString:#"" intoString:&lastName]; // Scan remaining characters
if (lastName != nil) {
// It was no space and lastName is empty
} else {
// There was at least one space and lastName contains a string
}

NSString : String extraction from a comma Separated NSString

Below are two examples of strings separated by comma that I get back as results:
NSString *placeResult = #"111 Main Street, Cupertino, CA"
or sometimes the result contains the name of a place:
NSString *placeResult = #"Starbucks, 222 Main Street, Cupertino, CA"
What's the best way to check the strings above to see if it starts with a name or or a street address?
If it does start with a name (i.e. Starbucks in the 2nd example above"), I'd like to extract the name and store it into another variable. Thus after extraction the string will be:
NSLog (#"%s", placeResult);
The log will print:
"222 Main Street, Cupertino, CA"
Another string will now store the #"Starbucks" in it:
NSLog (#"%s", placeName);
The log will print:
"Starbucks"
Important: I can't lose the comma separations after extraction.
Thank you!
Make use of NSDataDetector and NSTextCheckingResult:
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeAddress error:nil];
NSString *str = #"Starbucks, 222 Main Street, Cupertino, CA";
NSArray *matches = [detector matchesInString:str options:0 range:NSMakeRange(0, str.length)];
for (NSTextCheckingResult *match in matches) {
if (match.resultType == NSTextCheckingTypeAddress) {
NSDictionary *data = [match addressComponents];
NSLog(#"address = %#, range: %#", data, NSStringFromRange(match.range));
NSString *name = data[NSTextCheckingNameKey];
if (!name && match.range.location > 0) {
name = [str substringToIndex:match.range.location - 1];
// "name" may now include a trailing comma and space - strip these as needed
}
}
}
This outputs:
address = {
City = Cupertino;
State = CA;
Street = "222 Main Street";
}, range: {11, 30}
The odd thing is that the resulting dictionary of results does not contain a reference to the "Starbucks" portion. What you can do is check to see of the addressComponents contains a value for the NSTextCheckingNameKey. If not, check the range of the match. If the match's range isn't the start of the string, then you can use that value to extract the name from the beginning of the string.
To get an array of the things between commas, you could use:
NSArray *components = [placeResult componentsSeparatedByString:#","];
Possibly with a follow-up of:
NSMutableArray *trimmedComponents =
[NSMutableArray arrayWithCapacity:[components count]];
NSCharacterSet *whitespaceCharacterSet = [NSCharacterSet whitespaceCharacterSet];
for(NSString *component in components)
[trimmedComponents addObject:
[component stringByTrimmingCharactersInSet:whitespaceCharacterSet]];
To remove any leading or trailing spaces from each individual component. You would reverse the transformation using e.g.
NSString *fullAddress = [trimmedComponents componentsJoinedByString:#", "];
So then the question is, given NSString *firstComponent = [trimmedComponents objectAtIndex:0];, how do you guess whether it is a name or a street address? If it's as simple as checking whether there's a number at the front that isn't zero then you can just do:
if([firstComponent integerValue])
{
/* ... started with a non-zero number ... */
NSString *trimmedAddress = [[trimmedComponents subArrayWithRange:
NSMakeRange(1, [trimmedComponents count]-1)] componentsJoinedByString:", "];
NSLog(#"trimmed address is: %#");
}
Though that conditional test would also have worked with placeResult, and you'll probably want to add validity checks to make sure you have at least two components before you start assuming you can make an array from the 2nd one onwards.

How to pad strings to a fixed width with NSMutableString?

I'm trying to write a string to a text file. That text file will then be read by another program. That second program is expecting the different "fields" in the text file to be a fixed width. Therefore, when I write the text file with my app, I will need to add spaces between my actual data to get everything to line up correctly. How do I get these spaces added?
So far, I've tried writing a function that takes a source string and a target length as input. If the target is longer than the source, it just appends " ". Code for this routine is below:
- (NSString *) makeStringFrom:(NSString *)source withLength:(NSInteger)length
{
// Method to add spaces to the end of a string to get it to a certain length
if ([source length] > length)
{
// String is too long - throw warning and send it back
NSLog(#"Warning - string is already longer than length supplied. Returning source string");
return source;
}
else if ([source length] == length)
{
// String is already correct length, so just send it back
return source;
}
else
{
// String is too short, need to add spaces
NSMutableString *newString = [[NSMutableString alloc] initWithString:source];
NSLog(#"newString initial length = %d",[newString length]);
for (int current = [source length]; current < length; current ++)
{
[newString stringByAppendingString:#" "];
NSLog(#"hit");
}
NSLog(#"target length = %d. newString length = %d",length,[newString length]);
return newString;
}
}
This apparently doesn't work. The length of the string I'm getting back in the return isn't changing any from the length of the supplied string, even when the NSLog(#"hit"); runs multiple times.
There's a stringByPaddingToLength:withString:startingAtIndex: method on NSString that does just this.
You did a silly mistake here
[newString stringByAppendingString:#" "];
This returns a new string, and it doesnot effect the caller object. You need to store it
newString=[newString stringByAppendingString:#" "];
or simply
[newString appendString:#" "];
You want to change:
[newString stringByAppendingString:#" "];
into:
newString = [newString stringByAppendingString:#" "];

How to read seperate fields in a csv file and compare with user input?

I am building an app where use can upload a csv file that contains First Name, Last Name and email in 3 seperate columns. User interface will have 3 text fields and a button. When user enters the first name or last name or email, and click search button, the whole documenent must be searched and display an alert saying that the record was found in the file. This is the function that I am using, but it only reads the first row and first column. Please help
- (void) SearchStudent
{
NSArray *DocumentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *DocumentDirectory = [DocumentPath objectAtIndex:0];
NSString *FullPath = [DocumentDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"example.csv"]];
NSString * pstrCSVFile= [NSString stringWithContentsOfFile:FullPath encoding:NSASCIIStringEncoding error:NULL];
NSArray * paRowsOfCSVFile= [pstrCSVFile componentsSeparatedByString:#"\n"];
NSArray *paColumnsOfRow;
NSString *pstrFirstColumn;
for(NSString * pstrRow in paRowsOfCSVFile)
{
paColumnsOfRow= [pstrRow componentsSeparatedByString:#","];
pstrFirstColumn= [paColumnsOfRow objectAtIndex:0];
if([pstrFirstColumn localizedCaseInsensitiveCompare:GWIDText.text] == NSOrderedSame)
{
UIAlertView *alertingFileName = [[UIAlertView alloc]initWithTitle:#"Error" message:#"Found" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertingFileName show];
break;
}
else
{
UIAlertView *alertingFileName1 = [[UIAlertView alloc]initWithTitle:#"Error" message:#"Not Found" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertingFileName1 show];
break;
}
}
}
It looks like your else statement is breaking out of the for loop if the first name doesn't match. You'll want to remove that and perhaps add a variable to track if you've found a match. Only set it if you match the name. After your for loop, check the variable to see if there was a match. If not, then show your UIAlertView for "Not Found".
Couple of hints:
You are checking for one column only.
if([pstrFirstColumn localizedCaseInsensitiveCompare:GWIDText.text] == NSOrderedSame)
Do the same with the other two columns. Then you will solve your first problem of only checking one column.
Looks like the line terminator is not correct. Depending on which platform the csv file was created, it might have different line terminator. I would suggest taking a text editor like notepad++ for instance and viewing hidden code to find out your line terminator. Then use the terminator to split rows. Make sure you are getting more than 1 row (just output the rows variable].

Resources