If logic behind checking two textfields - ios

I'm attempting to check two input textfields that the user type in to see if they put in either AM or PM (going for non-case sensitive). If they did, post the event otherwise display an alert.
I tried this, it works in some occasions, but when I type in PM and AM in the second it sometimes tells me it's not valid and returning my alert. Any idea where I got the logic wrong?
if(!([self.eventStartTimeSuffix.text isEqualToString:#"AM"] || [self.eventStartTimeSuffix.text isEqualToString:#"PM"]) && !([self.eventEndTimeSuffix.text isEqualToString:#"AM"] || [self.eventEndTimeSuffix.text isEqualToString:#"PM"]))
{
NSLog(#"Invalid Event / Start Time Suffix, AM or PM required");
}
else
{
//post event
}

In trying to test for not AM/PM you are testing for both being invalid, your test is: NOT(StartTimeSuffix is AM/PM) AND NOT(EndTimeSuffix is AM/PM). So first either use OR to join the separate conditions or test them independently so you can present a more specific error.
You are also not ignoring case as you say you wish to, and if the user enters some whitespace it might be worth ignoring that as well. You can do both of these with code such as:
NSSString *startSuffix = [[self.eventStartTimeSuffix.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] lowercaseString];
and then comparing startSuffix to #"am" and #"pm", likewise for eventEndTimeSuffix.
BTW You might be even better off if you use the international facilities of OS X and compare for the localised versions of AM & PM - but that is another topic!

Add parentheses to make your grouping clear:
Pseudocode (this is not real code!):
if (
(startText == "AM" || startText == "PM")
&&
(endText == "AM" || endText "PM")
)
{
//Both fields contain either "AM" or PM"
}
Note that if you want case insensitive comparison, you should use
if ([string caseInsensitiveCompare: #"otherString"] == NSOrderedSame)
{
//strings match, ignoring case
}
else
{
//strings don't match
}

You also may as well factor out a method to make it more readable:
- (BOOL)hasValidTimeSuffix:(NSString *)timeText {
return [[timeText lowercaseString] hasSuffix:#"am"] || [[timeText lowercaseString] hasSuffix:#"pm"]
}
and then
if ([self hasValidTimeSuffix:self.eventStartTimeSuffix.text] && [self hasValidTimeSuffix:self.eventEndTimeSuffix.text])
{
//post event
}
else
{
NSLog(#"Invalid Event / Start Time Suffix, AM or PM required");
}
Notice the use of NSString's lowercaseString and hasSuffix: methods. These help a lot.

Why would you bother checking for the input of textfields? Won't it be wiser to use a NSPopUpButton? Check the selected tag 0:AM or 1:PM. It's just an idea, but it screams for a NSPopUpButton. Cheers!
if
([sender selectedTag] == AM)
{
NSLog(#"it's AM");
}
else if([sender selectedTag] == PM)
{
NSLog(#"it's PM");
}
//Sender is one of the two NSPopUpButtons
//I made a Typedef Enum to make it more readable
/*In the .h file:
typedef enum {
AM,
PM
} TimeNotation;
*/

Related

Can one define NSFound macro?

This may sound like a silly question but Apple provides us with NSNotFound but why didn't they provide one called NSFound? Is there a way one can define a NSFound macro on their own?
The reason I am asking all this is that in order for me to check if a string "contains" a certain character I have to do double negative i.e.
if ([XML rangeOfString:#"error" options:NSCaseInsensitiveSearch].location != NSNotFound)
{
//server is down
}
else
{
//server is up
}
At least for me this would have been so much easier to read if I could simply do this instead
if ([XML rangeOfString:#"error" options:NSCaseInsensitiveSearch].location == NSFound)
{
//server is down
}
else
{
//server is up
}
If I want to define NSFound or SAMFound, how would I go about doing that?
Your issue is really with the design pattern methods like rangeOfString follow - using a single return value for both valid results, of which there are many, and failure indications, of which there is one. You can test for a single failure value with a comparison to a constant, NSNotFound in this case, but you cannot likewise test for many possible values with a simple comparison - instead you use the "double negative" you don't like.
If you find it too ugly change it... Maybe:
#interface NSString (SamExtras)
- (BOOL) SAMcontainsString:(NSString *)string options:(NSStringCompareOptions)options;
#end
#implementation NSString (SamExtras)
- (BOOL) SAMcontainsString:(NSString *)string options:(NSStringCompareOptions)options
{
return [self rangeOfString:string options:options].location != NSNotFound;
}
#end
Which would allow you to use:
if ([XML SAMcontainsString:#"error" options:NSCaseInsensitiveSearch])
{
//server is down
}
else
{
//server is up
}
with no double negative. You can write the category once and use it in all your projects.
HTH
Double Negative doesn't have the consequences in code as it does in grammar.
The reason they provide a not found, as opposed to a found version, is simply the not found value is a single (supposedly invalid) value and everything else is valid. It's therefore simpler to define this single, invalid value.
Also it makes more sense (more efficient, avoiding a double-search and less code) to store the NSRange in a local variable in order to firstly test for validity and then to use the value:
NSRange range = [XML rangeOfString:#"error" options:NSCaseInsensitiveSearch];
if (range.location != NSNotFound) {
// Do thing with range
} else {
// Complain
}
There is nothing whatever wrong with your original test:
if ([XML rangeOfString:#"error" options:NSCaseInsensitiveSearch].location != NSNotFound) {
If all you need to know is whether XML contains the string #"error", that test answers the question and is a perfectly legitimate and idiomatic way to ask it. Observe that even the documentation tells you that containsString: is nothing but a front for calling rangeOfString:options:!
If you really want to know what the positive version would be, it would be to test the length of the returned range and see if it is the same as the length of #"error". The length of a not-found range is 0.

else if condition concept

I need to check in two of string, if those string contains any particular string or not
NSString *startLocationAddress = #"Any address for start location";
NSString *endLocationAddress = #"Any address for end location";
if ([startLocationAddress rangeOfString:#"Australia"].location == NSNotFound)
{
NSLog(#"string does not contain Australia");
startLocationAddress = [startLocationAddress stringByAppendingString:#",Australia"];
}
else if ([endLocationAddress rangeOfString:#"Australia"].location == NSNotFound)
{
NSLog(#"string does not contain Australia");
endLocationAddress =[endLocationAddress stringByAppendingString:#",Australia"];
}
else {
NSLog(#"string contain Australia");
}
As my both of strings does not contains "Australia". So the first condition will be checked first and if the first condition valid then it exit out of the conditions, if the first condition is not valid then only it check the else if condition. In this way the if else if conditional works.
As my both of strings does not contains "Australia". First if condition is working fine and it append "Australia" to the string but second else if condition is not working
How on earth can an else if block execute when it's corresponding if was executed? Expectation is not logical.
If you want your else if block to also check then separate it from your main if and start a new if condition, not an else if
You better reconstruct it like:
if ([startLocationAddress rangeOfString:#"Australia"].location == NSNotFound)
{
//codes..
}
else
{
NSLog(#"startLocationAddress contain Australia");
}
if ([endLocationAddress rangeOfString:#"Australia"].location == NSNotFound)
{
//codes..
}
else
{
NSLog(#"endLocationAddress contain Australia");
}
and review how if-else if-else statement works.. See: #
Hanky 웃 Panky answer for that, since confusion is very prone to us..
if (ifcondition)
{ .. }
else if (elseifcondition)
{ .. }
else
{ .. }
/*
if `ifcondition` == true, dont expect anything from `else-if` or `else`,
compiler won't care about them anymore. that goes with `else-if` and `else` as well..
*/
In if-else if-else condition if any of one is gets satisfied it will ignore the rest of the condition.
This means if First if gets satisfied, then it will ignore the "else if - else". Hence your second condition is not executing.
You are required to read the basic if else logic of execution.
Here is the example
int x=70;
string Grade;
IF (x > 90) THEN
Grade = "O"
ELSE IF (x > 80) THEN
Grade = "A"
ELSE IF (x > 70) THEN
Grade = "B"
ELSE IF (x > 60) THEN
Grade = "C"
ELSE
Grade = "F"
Here the value for variable Grade will be only one per execution.

format uiTextField for phoneNumber and date

I'm using parse to store my data. I have a bunch of UITextField for user registration inside a view controller.
Now, in my phone text field, how do I format the text field to show the following depending on the total length.
+55 (21) 99999-9999 = 13 numbers
+55 (21) 9999-9999 = 12 numbers
I want to accept both 12 and 13 numbers and show the formatted phone in the textfield.
Now, for saving it to parse, I would like to save the formatted number with characters +, (, ), -.
I would also like to format my date text field to dd/mm/yyyy. Can anyone help me?
Thanks.
UPDATE
Ok, so I did the following:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (_telefoneTextField.text.length == 0)
_telefoneTextField.text = [NSString stringWithFormat:#"(%#",_telefoneTextField.text];
if (_telefoneTextField.text.length == 3)
_telefoneTextField.text = [NSString stringWithFormat:#"%#) ",_telefoneTextField.text];
if (_telefoneTextField.text.length == 9)
_telefoneTextField.text = [NSString stringWithFormat:#"%#-",_telefoneTextField.text];
return YES;
}
and
else if (textField == self.telefoneTextField)
{
if (_telefoneTextField.text.length == 14)
{
NSLog(#"Telefone sem o 9");
[self.nascimentoTextField becomeFirstResponder];
}
if (_telefoneTextField.text.length == 15)
{
NSLog(#"Telefone COM o 9");
NSMutableString *telefone = [[NSMutableString alloc] initWithString:_telefoneTextField.text];
[telefone deleteCharactersInRange:NSMakeRange(9,1)];
[telefone insertString:#"-" atIndex:10];
NSLog(#"%#", telefone);
_telefoneTextField.text = telefone;
[self.nascimentoTextField becomeFirstResponder];
}
else
{
NSLog(#"Telefone NAO esta no formato");
}
}
now, it works like I wanted. It changes the format in real time when the user is typing and when finish editing it checks to see how many chars, in case of 15, it changes the format again.
Now, one thing I couldn't do: How can I delete the phone number using the keyboard, I mean, it does't delete the numbers before the "-"character.
Thanks.
The best way to implement this by using regular expressions. See the following discussion
Regex not working correctly on iOS

Check if Text Field NEARLY Matches Set Text? iOS

Does anyone now how I can check if a text field NEARLY matches a set text?
I know how to check if it exactly matches, but i want it to know if its even close to the set text
So if they type HELLO WORD it indicates its close but not exact match?
if (([textfield.text isEqual:#"HELLO WORLD"]))
{
NSLog(#"Correct");
} else {
NSLog(#"Incorrect");
}
This library may be of use to you. And since it's open source, you can check the source to see how it's done. :)
Use this
For Case Insensitive :
if( [textfield.text caseInsensitiveCompare:#"My Case sensitiVE"] == NSOrderedSame ) {
// strings are equal except for possibly case
}
For Case Sensitive :
if([textfield.text isEqualToString:#"My Case sensitiVE"]) {
// Case sensitive Compare
}
You can compare each index of two string and see how many difference is there. And you should define your "nearly match", it may be difference in single character or in multiple character. And decide if you should accept it or reject it.
If you like algorithm Longest Common Subsequence is a key to your goal.. :)
use
NSString caseInsensitiveCompare:
or
- (NSComparisonResult)compare:(NSString *)aString
options:(NSStringCompareOptions)mask`
NSString *string = #"HELLO WORLD I AM JACK";
if ([string rangeOfString:#"HELLO WORLD"].location == NSNotFound) {
NSLog(#"string does not contain HELLO WORLD");
} else {
NSLog(#"string contains HELLO WORLD!");
}

Compare 2 Objects in Objective-C

In my application, I want to compare 2 core data instances of the entity "Workout". I want to check if the 2 objects have identical attribute values for all of their attributes. Essentially if the two objects are the same minus the relationship, whosWorkout. Is there any way to do this without manually checking every single attribute? I know I could do:
if(object1.intAttr == object2.intAttr){
NSLog(#"This attribute is the same");
}
else{
return;
}
repeat with different attributes...
Is there any core data method to make this a bit less tedious?
First I would create an isEqual method in the Workout subclass like this...
-(BOOL)isEqualToWorkout:(Workout*)otherWorkout
{
return [self.attribute1 isEqual:otherWorkout.attribute1]
&& [self.attribute2 isEqual:otherWorkout.attribute2]
&& [self.attribute3 isEqual:otherWorkout.attribute3]
&& [self.attribute4 isEqual:otherWorkout.attribute4]
...;
}
Then whenever you want to compare to Workout objects just use...
BOOL equal = [workout1 isEqualToWorkout:workout2];
You can iterate through the attributes by name.
for (NSString *attribute in object.entity.attributesByName) {
if ([[object valueForKey:attribute] intValue] !=
[[object2 valueForKey:attribute] intValue]) {
return NO;
}
}
return YES;
This assumes all integer attributes. You could do a switch statement to check for the class with the class method and deal with different data types as well.
If you need to compare whether one object represents a greater or lesser value than another object, you can’t use the standard C comparison operators > and <. Instead, the basic Foundation types, like NSNumber, NSString and NSDate, provide a compare: method:
if ([someDate compare:anotherDate] == NSOrderedAscending) {
// someDate is earlier than anotherDate
}
I ended up doing the following:
-(BOOL)areEqual:(Workout *)firstWorkout secondWorkout:(Workout *)secondWorkout{
NSArray *allAttributeKeys = [[[firstWorkout entity] attributesByName] allKeys];
if([[firstWorkout entity] isEqual:[secondWorkout entity]]
&& [[firstWorkout committedValuesForKeys:allAttributeKeys] isEqual:[secondWorkout committedValuesForKeys:allAttributeKeys]]) {
return YES;
}
else{
return NO;
}
}

Resources