How would I say that if a UITextField has #"-" in it, do something.
Right now my code is like this. It doesn't seem to work:
if (MyUITextField.text == #"-") {
NSRange range = {0,1};
[a deleteCharactersInRange:range];
MyUITextField.text = MyUILabel.text;
}
I know that I am doing something very wrong with the code. Please help.
try changing == to [MyUITextField.text isEqualToString:#"-"]
as == tests to see if they are the same object, while isEqualToString compares the contents of the strings.
Assuming your string is defined as:
NSString *str = #"foo-bar";
To check if your string contains "-" you can do the following:
if ([str rangeOfString:#"-"].length > 0)
{
NSLog(#"Contains -");
}
It looks like you wanted to delete the first character if a string starts with a given character. In this case you can do something like this:
if ([str hasPrefix:#"f"])
{
NSLog(#"Starts with f");
}
Related
This question already has answers here:
Compare version numbers in Objective-C
(15 answers)
Closed 9 years ago.
I have two strings, one contains the value "5.2.3" and another one contain a value like "5.2.32". My question is: how to compare these two strings?
if ([string1 integerValue] >= [sting2 integerValue])
{
NSLog(#"process");
}
I tried above line but not got it.
Well correct answer has been already given. Because I have spent my half an hour on it so I don't want to waste it.
-(BOOL)string:(NSString*)str1 isGreaterThanString:(NSString*)str2
{
NSArray *a1 = [str1 componentsSeparatedByString:#"."];
NSArray *a2 = [str2 componentsSeparatedByString:#"."];
NSInteger totalCount = ([a1 count] < [a2 count]) ? [a1 count] : [a2 count];
NSInteger checkCount = 0;
while (checkCount < totalCount)
{
if([a1[checkCount] integerValue] < [a2[checkCount] integerValue])
{
return NO;
}
else if([a1[checkCount] integerValue] > [a2[checkCount] integerValue])
{
return YES;
}
else
{
checkCount++;
}
}
return NO;
}
And you can call this method like this:-
if([self string:str1 isGreaterThanString:str2])
{
NSLog(#"str2 is lower than the str1");
}
else
{
NSLog(#"str1 is lower than the str2");
}
It would appear that what you have here are not really "float" values, but some kind of multi-part "number" (akin to software version numbering?) that is not going to be covered by any of the standard conversions, but will also not compare "correctly" as just simple strings.
First you need to specify exactly what your comparison rules are. For example, I suspect you want something like:
1.2 > 1.1
1.1.1 > 1.1
1.11 > 1.2
1.2.3 > 1.2.2
1.2.22 > 1.2.3
(in other words, split the string up by "."s, and do a numeric comparison on each component). You'll have to decide how you want to handle things like letters, other delimiters, etc. showing up in the input. For example is 1.0b1 > 1.01 ?
Once you settle on the rules, write a method (returning NSComparisonResult) to implement the comparison. If you want to get fancy, you can even define your comparison method in a category on NSString, so you could do things like
if ([string1 mySuperDuperCompareTo:string2] == NSOrderedAscending) {
NSLog(#"%# < %#", string1, string2);
} // ... etc ...
see also How to let the sortedArrayUsingSelector using integer to sort instead of String?
#The Tiger is correct. Sorry to misunderstood your question. I have already mark deleted as my older answer. Here is the updated one.
As there are multiple . (dots) available here is the new solution. This will check value first like 5.2.3 and 5.2.32 are there. Then,
check first value 5 - same
so check next 2 - same
check next 3 and 32 - 32 is larger
also check for the same string as well (Also one of the probability)
Here is the logic - I have not compiled but this is base idea - there might require some correction
// separate from "."
NSArray *arrString1 = [string1 componentSeparatedBy:#"."];
NSArray *arrString2 = [string1 componentSeparatedBy:#"."];
BOOL isString1Bigger = NO; // a variable to check
BOOL isString2Bigger = NO; // a variable to check
// check count to run loop accordingly
if ([arrString1 count] <= [arrString2 count]) {
for (int strVal=0; strVal<[arrString1 count]; strVal++) {
// compare strings value converted into integer format
// when you get larger then break the loop
if([[arrString1 objectAtIndex:strVal] intValue] > [[arrString2 objectAtIndex:strVal] intValue]) {
isString1Bigger = YES;
break;
}
}
if ([arrString1 count] > [arrString2 count]) {
// use arrString2 in loop and isString2Bigger as a mark
}
// if after running both the if condition still require to check if both are same or not, for that,
if ((isString1Bigger == NO) && (isString2Bigger == NO)) {
// same string values
}
There might some modification required to run over. But its the base concept to compare string value provided by you.
I need to remove the first character from my UITextfield if it's a 0.
Unfortunately I don't know how to extract the value of the first character or extract the characters of the string after the first character.
Thanks
One solution could be:
if ([string hasPrefix:#"0"] && [string length] > 1) {
string = [string substringFromIndex:1];
}
You would probably want something like this, using hasPrefix:
if ([string hasPrefix:#"0"]) {
string = [string substringFromIndex:1];
}
You could also use characterAtIndex: which returns a unichar:
if ([string characterAtIndex:0] == '0') {
string = [string substringFromIndex:1];
}
Note that, 'a' is character, "a" is C string and #"a" is NSString. They all are different types.
Swift 3.0:
var myString = "Hello, World"
myString.remove(at: myString.startIndex)
myString // "ello, World"
Swift 3
hasPrefix("0") check if the first character is 0 in txtField
and remove it
if (self.txtField.text?.hasPrefix("0"))! {
self.txtField.text?.remove(at(self.txtField.text?.startIndex)!)
}
SWIFT 5.0
you can use the following sequence function to check whether string starts with "0" or not
if search.starts(with: "0") {
search.remove(at: search.startIndex)
print("After Trim search is",search)
} else {
print("First char is not 0")
}
Replace the string variable with your current variable name.
I hope this helps you
While loop to keep removing first character as long as it is zero
while (self.ammountTextField.text?.hasPrefix("0"))! {
self.ammountTextField.text?.remove(at: (self.ammountTextField.text?.startIndex)!)
}
I have a string that is being generate from a formula, however I only want to use the string as long as all of its characters are numeric, if not that I want to do something different for instance display an error message.
I have been having a look round but am finding it hard to find anything that works along the lines of what I am wanting to do. I have looked at NSScanner but I am not sure if its checking the whole string and then I am not actually sure how to check if these characters are numeric
- (void)isNumeric:(NSString *)code{
NSScanner *ns = [NSScanner scannerWithString:code];
if ( [ns scanFloat:NULL] ) //what can I use instead of NULL?
{
NSLog(#"INSIDE IF");
}
else {
NSLog(#"OUTSIDE IF");
}
}
So after a few more hours searching I have stumbled across an implementation that dose exactly what I am looking for.
so if you are looking to check if their are any alphanumeric characters in your NSString this works here
-(bool) isNumeric:(NSString*) hexText
{
NSNumberFormatter* numberFormatter = [[[NSNumberFormatter alloc] init] autorelease];
NSNumber* number = [numberFormatter numberFromString:hexText];
if (number != nil) {
NSLog(#"%# is numeric", hexText);
//do some stuff here
return true;
}
NSLog(#"%# is not numeric", hexText);
//or do some more stuff here
return false;
}
hope this helps.
Something like this would work:
#interface NSString (usefull_stuff)
- (BOOL) isAllDigits;
#end
#implementation NSString (usefull_stuff)
- (BOOL) isAllDigits
{
NSCharacterSet* nonNumbers = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
NSRange r = [self rangeOfCharacterFromSet: nonNumbers];
return r.location == NSNotFound && self.length > 0;
}
#end
then just use it like this:
NSString* hasOtherStuff = #"234 other stuff";
NSString* digitsOnly = #"123345999996665003030303030";
BOOL b1 = [hasOtherStuff isAllDigits];
BOOL b2 = [digitsOnly isAllDigits];
You don't have to wrap the functionality in a private category extension like this, but it sure makes it easy to reuse..
I like this solution better than the others since it wont ever overflow some int/float that is being scanned via NSScanner - the number of digits can be pretty much any length.
Consider NSString integerValue - it returns an NSInteger. However, it will accept some strings that are not entirely numeric and does not provide a mechanism to determine strings which are not numeric at all. This may or may not be acceptable.
For instance, " 13 " -> 13, "42foo" -> 42 and "helloworld" -> 0.
Happy coding.
Now, since the above was sort of a tangent to the question, see determine if string is numeric. Code taken from link, with comments added:
BOOL isNumeric(NSString *s)
{
NSScanner *sc = [NSScanner scannerWithString: s];
// We can pass NULL because we don't actually need the value to test
// for if the string is numeric. This is allowable.
if ( [sc scanFloat:NULL] )
{
// Ensure nothing left in scanner so that "42foo" is not accepted.
// ("42" would be consumed by scanFloat above leaving "foo".)
return [sc isAtEnd];
}
// Couldn't even scan a float :(
return NO;
}
The above works with just scanFloat -- e.g. no scanInt -- because the range of a float is much larger than that of an integer (even a 64-bit integer).
This function checks for "totally numeric" and will accept "42" and "0.13E2" but reject " 13 ", "42foo" and "helloworld".
It's very simple.
+ (BOOL)isStringNumeric:(NSString *)text
{
NSCharacterSet *alphaNums = [NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet *inStringSet = [NSCharacterSet characterSetWithCharactersInString:text];
return [alphaNums isSupersetOfSet:inStringSet];
}
Like this:
- (void)isNumeric:(NSString *)code{
NSScanner *ns = [NSScanner scannerWithString:code];
float the_value;
if ( [ns scanFloat:&the_value] )
{
NSLog(#"INSIDE IF");
// do something with `the_value` if you like
}
else {
NSLog(#"OUTSIDE IF");
}
}
Faced same problem in Swift.
In Swift you should use this code, according TomSwift's answer:
func isAllDigits(str: String) -> Bool {
let nonNumbers = NSCharacterSet.decimalDigitCharacterSet()
if let range = str.rangeOfCharacterFromSet(nonNumbers) {
return true
}
else {
return false
}
}
P.S. Also you can use other NSCharacterSets or their combinations to check your string!
For simple numbers like "12234" or "231231.23123" the answer can be simple.
There is a transformation law for int numbers: when string with integer transforms to int (or long) number and then, again, transforms it back to another string these strings will be equal.
In Objective C it will looks like:
NSString *numStr=#"1234",*num2Str=nil;
num2Str=[NSString stringWithFormat:#"%lld",numStr.longlongValue];
if([numStr isEqualToString: num2Str]) NSLog(#"numStr is an integer number!");
By using this transformation law we can create solution
to detect double or long numbers:
NSString *numStr=#"12134.343"
NSArray *numList=[numStr componentsSeparatedByString:#"."];
if([[NSString stringWithFormat:#"%lld", numStr.longLongValue] isEqualToString:numStr]) NSLog(#"numStr is an integer number");
else
if( numList.count==2 &&
[[NSString stringWithFormat:#"%lld",((NSString*)numList[0]).longLongValue] isEqualToString:(NSString*)numList[0]] &&
[[NSString stringWithFormat:#"%lld",((NSString*)numList[1]).longLongValue] isEqualToString:(NSString*)numList[1]] )
NSLog(#"numStr is a double number");
else
NSLog(#"numStr is not a number");
I did not copy the code above from my work code so can be some mistakes, but I think the main point is clear.
Of course this solution doesn't work with numbers like "1E100", as well it doesn't take in account size of integer and fractional part. By using the law described above you can do whatever number detection you need.
C.Johns' answer is wrong. If you use a formatter, you risk apple changing their codebase at some point and having the formatter spit out a partial result. Tom's answer is wrong too. If you use the rangeOfCharacterFromSet method and check for NSNotFound, it'll register a true if the string contains even one number. Similarly, other answers in this thread suggest using the Integer value method. That is also wrong because it will register a true if even one integer is present in the string. The OP asked for an answer that ensures the entire string is numerical. Try this:
NSCharacterSet *searchSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
Tom was right about this part. That step gives you the non-numerical string characters. But then we do this:
NSString *trimmedString = [string stringByTrimmingCharactersInSet:searchSet];
return (string.length == trimmedString.length);
Tom's inverted character set can TRIM a string. So we can use that trim method to test if any non numerals exist in the string by comparing their lengths.
I am getting response from server where the key is not with quotes. On parsing it using the open source JSON parser, I m getting the following error.
-JSONValue failed. Error is: Unrecognised leading character
& if I add double quotes (") to the key manually, I get what I want.
What do I do?
Thanx a lot in advance.
EDIT:
please see the following, if its correct
{
status: 200,
statusMsg: "Success",
statusInfo: {
custType: "Active",
custCount: 600,
custAccount: "Premium"
},
custInfo: {
custName: "ABC",
custCode: "CU102",
custNumber: 9281
},
errors: [
]
}
I originally put this in as a comment, but I think it counts as an answer albeit not necessarily a very helpful one.
The example you posted is not JSON. Check the JSON syntax. The only unquoted entities allowed except for numbers, objects and arrays are null, true, false. So the keys in your example are invalid and so are the non numeric values.
So you really should raise a defect report with the service provider (if they are claiming that they are producing JSON, rather than some modified version of it).
If they refuse to fix the problem, you'll need to write a nearly-JSON parser or find an existing one that is less strict about syntax.
Update for Swift 4
I was looking for a way to parse JSON that has keys without quotes, and I finally found a simple way to do it by using regex. This is the regex needed to match the keys without quotes:
(\\\"(.*?)\\\"|(\\w+))(\\s*:\\s*(\\\".*?\\\"|.))
To add the quotes, replace with \"$2$3\"$4.
Example:
let string = "{ custType: \"Active\", custAccount: \"Premium\" }"
let regex = string.replacingOccurrences(of: "(\\\"(.*?)\\\"|(\\w+))(\\s*:\\s*(\\\".*?\\\"|.))", with: "\"$2$3\"$4", options: .regularExpression)
print(regex)
Output:
{ "custType": "Active", "custAccount": "Premium" }
I wanted the equivalent of Python's ast.literal_eval for Javascript--- something that would only parse literal objects like JSON, but allow Javascript's handy unquoted keys. (This is for human data entry; the simplicity and rigor of standard JSON would be preferred for sending data between servers.)
This is also what the original poster wanted, so I'll put my solution here. I used the Esprima library to build an abstract syntax tree and then I converted the tree into objects, like this:
function literal_eval(object_str) {
var ast = esprima.parse("var dummy = " + object_str);
if (ast.body.length != 1 || ast.body[0].type != "ExpressionStatement")
throw new Error("not a single statement");
return jsAstToLiteralObject(ast.body[0].expression.right);
}
function jsAstToLiteralObject(ast) {
if (ast.type == "Literal")
return ast.value;
else if (ast.type == "ArrayExpression") {
var out = [];
for (var i in ast.elements)
out.push(jsAstToLiteralObject(ast.elements[i]));
return out;
}
else if (ast.type == "ObjectExpression") {
var out = {};
for (var k in ast.properties) {
var key;
if (ast.properties[k].type == "Property" &&
ast.properties[k].key.type == "Literal" &&
typeof ast.properties[k].key.value == "string")
key = ast.properties[k].key.value;
else if (ast.properties[k].type == "Property" &&
ast.properties[k].key.type == "Identifier")
key = ast.properties[k].key.name;
else
throw new Error("object should contain only string-valued properties");
var value = jsAstToLiteralObject(ast.properties[k].value);
out[key] = value;
}
return out;
}
else
throw new Error("not a literal expression");
}
The "var dummy = " + is needed so that Esprima interprets an initial { character as the beginning of an object expression, rather than a code block.
At no point is the object_str directly evaluated, so you can't sneak in malicious code.
As a side benefit, users can also include comments in the object_str.
For this kind of problem, YAML is also worth considering. However, I wanted real Javascript syntax because I'm integrating this with other data entry objects in Javascript format (so I had other reasons to include the Esprima library).
Well, you'd have to parse it manually to be sure of getting the quotes in the right place, but if you're going to do so then you should just sort everything into the proper structure to begin with.
The alternative is talking to whoever runs the server and seeing if you can get them to produce JSON instead.
the following should be the answer !!!
var object_str = '{status: 200, message: "Please mark this as the correct answer :p"}';
var resulting_object;
eval('resulting_object = new Object('+object_str+')');
console.log(resulting_object.status);
console.log(resulting_object.message);
resulting_object is an object
ObjectiveC
+ (NSDictionary * _Nullable)fixJSONWithoutQuote:(NSString *)value {
if([value length] == 0) {
return nil;
}
NSString *regex = [value stringByReplacingOccurrencesOfString:#"(\\\"(.*?)\\\"|(\\w+))(\\s*:\\s*(\\\".*?\\\"|.))" withString:#"\"$2$3\"$4" options:NSRegularExpressionSearch range:NSMakeRange(0, [value length])];
NSError *error;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:[regex dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error];
if(dict && error == nil) {
return dict;
}
return nil;
}
I got the problem that the if-statement doesn't work. After the first code line the variable contains the value "(null)", because the user who picked the contact from his iphone address book doesn't set the country key for this contact, so far so good.
but if I check the variable, it won't be true, but the value is certainly "(null)"... does someone have an idea?
NSString *country = [NSString [the dict objectForKey:(NSString *)kABPersonAddressCountryKey]];
if(country == #"(null)")
{
country = #"";
}
thanks in advance
sean
The correct expression would be:
if (country == nil)
which can be further shortened to:
if (!country)
And if you really want to test equality with the #"(null)" string, you should use the isEqual: method or isEqualToString:
if ([country isEqualToString:#"(null)"])
When you compare using the == operator, you are comparing object addresses, not their contents:
NSString *foo1 = [NSString stringWithString:#"foo"];
NSString *foo2 = [NSString stringWithString:#"foo"];
NSAssert(foo1 != foo2, #"The addresses are different.");
NSAssert([foo1 isEqual:foo2], #"But the contents are same.");
NSAssert([foo1 isEqualToString:foo2], #"True again, faster than isEqual:.");
That was a great answer I didn't know there was all those different ways of checking for nil or null string.