Objective-C String Function: Contains String - objective-c

How can I check if an NSString contains another substring, at which point it will return a Boolean Value.
This is what I'm thinking of:
If myString.contains("string") then
{
//Stuff Happens
}
But, from the research I've done, it seems as if Obj-C has no function for this. This Wikipedia article gives numerous string functions, their differences, and all in different languages, but I see no Obj-C support for any Contain Function.
Does anyone know of a simple-to-use function like the once above (which is similar to the C# and VB.NET function)?
Would a "Find" Function work? If so, how?
If this is not supported in Obj-C, is there a workaround I can use?
Any help is very appreciated.

if ([myString rangeOfString:#"string"].location != NSNotFound)
{
// Stuff happens
}

NSString *someString = #"Time for an egg hunt";
if ( [someString rangeOfString:#"egg" options:NSCaseInsensitiveSearch].location != NSNotFound ) {
NSLog( #"Found it!" );
}

If you want to be case insensitive.
NSRange range = [string rangeOfString:#"string" options:NSCaseInsensitiveSearch];
if (range.location != NSNotFound)
{
return range.location;
}
else
{
return nil;
}
Documentation

Create a NSString category, and put that in...
Code :
- (BOOL)contains:(NSString *)str
{
NSRange aRange = [self rangeOfString:str];
return (aRange.location!=NSNotFound);
}
Usage :
NSString* testStr = #"This is my string";
if ([testStr contains:#"is"])
{
// do something
}

if([string rangeOfString:substring].length > 0)
...

Related

Checking to see if ObjectForKey exists [duplicate]

Most of the examples I found on the net write this:
if(x != nil)
// ...
Is there any problems with this?
if(x)
// ...
I tried both in a simple program and couldn't found any difference.
In Objective-C, nil is defined as a value called __DARWIN_NULL, which essentially evaluates to 0 or false in if-statements. Therefore, writing
if (x == nil) is the same as writing if (!x) and writing if (x != nil) is equal to if (x) (since comparing to false creates a negation, and comparing to true keeps the condition the same).
You can write your code either way, and it really depends on which you think is more readable. I find if (x) to make more sense, but it depends on your style.
It's like comparing if (someCondition == true) versus if (someCondition).
It all depends on you, and who's going to be reading the code.
Edit: As Yuji correctly mentions, since Objective-C is a superset of C, any condition that evaluates to a value other than 0 is considered to be true, and therefore, if someCondition in the example above were to evaluate to an integer value of, say, -1, comparing it to true would result in false, and the if-statement would not be evaluated. Something to be aware of.
Both
if (x != nil)
and
if ( x )
are equivalent, so pick the variant that in your opinion makes your code more readable for you (and others who will read and support your code)
Both are the same and this is a style question and it boils down to whether you prefer:
if (something) { ... }
versus
if (something != nothing) { ... }
I have always found #1 more clear but #2 is used extensively in documentation and hence the field so it is better to both know both forms and adapt to what a project uses and be stylistically consistent.
The best and safe way to check nil is
Make a common method, and add all these null :
+ (NSString *)trimWhiteSpaceAndNewLine:(NSString *)string {
NSString *stringSource = [NSString stringWithFormat:#"%#",string];
if ([stringSource isEqualToString:#"(null)"]) {
stringSource = #"";
return stringSource;
}
if ([stringSource isEqualToString:#"<null>"]) {
stringSource = #"";
return stringSource;
}
if ([stringSource isEqualToString:#"<nil>"]) {
stringSource = #"";
return stringSource;
}
if ([stringSource isKindOfClass:[NSNull class]]) {
stringSource = #"";
return stringSource;
}
if ([stringSource isEqualToString:#""]) {
stringSource = #"";
return stringSource;
}
if (stringSource == nil) {
stringSource = #"";
return stringSource;
}
NSString *stringFinal = [stringSource stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
return stringFinal;
}
And check
NSString *strUuid = [Common trimWhiteSpaceAndNewLine:[dict valueForKeyPath:#"detail.uuid"]];
if (![strUuid isEqualToString:#""]) {
// do your stuff
}

Matching strings, consider some characters are the same

please help me with this problem.
I want to check if the targetString match the keyword or not. Consider some character may different, but should still return true.
Example:
targetString = #"#ß<"
keyword = #"abc", #"∂B(", #"#Aß<"
result: all must return true.
(Matched.targetString and all keyword are the same.)
Consider me have an array, contains list of character set that can be the same:
NSArray *variants = [NSArray arrayWithObjects:#"aA#∂", #"bBß", #"c©C<(", nil]
So that when matching, with this rule, it can match as the example above.
Here is what i've done so far (using recursion):
- (BOOL) test:(NSString*)aString include:(NSString*) keyWord doTrim:(BOOL)doTrim {
// break recursion.
if([aString length] < [keyWord length]) return false;
// First, loop through each keyword's character
for (NSUInteger i = 0; i < [keyWord length]; i++) {
// Get #"aA#∂", #"bBß", #"c©C<(" or only the character itself.
// like, if the keyword's character is A, return the string #"aA#∂".
// If the character is not in the variants set, eg. P, return #"P"
char c = [keyWord characterAtIndex:i];
NSString *rs = [self variantsWithChar:c];
// Check if rs (#"aA#∂" or #"P") contains aString[i] character
if([rs rangeOfString:[NSString stringWithCharacters:[aString characterAtIndex:i] length:1]].location == NSNotFound) {
// If not the same char, remove first char in targetString (aString), recursion to match again.
return [self test:[aString substringFromIndex:1] include:keyWord doTrim:NO];
}
}
// If all match with keyword, return true.
return true;
}
- (NSString *) variantsWithChar:(char) c {
for (NSString *s in self.variants) {
if ([s rangeOfString:[NSString stringWithFormat:#"%c",c]].location != NSNotFound) {
return s;
}
}
return [NSString stringWithFormat:#"%c", c];
}
The main problem is, variantsWithChar: doesn't return the correct string. I don't know which datatype and which function should I use here. Please help.
For thou who know ruby, here's the example in ruby. It work super fine!
require 'test/unit/assertions'
include Test::Unit::Assertions
class String
def matching?(keyword)
length >= keyword.length && (keyword.chars.zip(chars).all? { |cs| variants(cs[0]).include?(cs[1]) } || slice(1, length - 1).matching?(keyword))
end
private
VARIANTS = ["aA#∂", "bBß", "c©C<("]
def variants(c)
VARIANTS.find { |cs| cs.include?(c) } || c
end
end
assert "abc".matching?("#ß<")
PS: The fact is, it's containt a japanese character set that sounds the same (like あア, いイ... for thou who know japanese)
PS 2: Please feel free to edit this Question, since my engrish is sooo bad. I may not tell all my thought.
PS 3: And, maybe some may comment about the performance. Like, search about 10,000 target words, with nearly 100 variants, each variant have at most 4 more same characters.
So first off, ignore comments about ASCII and stop using char. NSString and CFString use unichar
If what you really want to do is transpose hiragana and katakana you can do that with CFStringTransform()
It wraps the ICU libraries included in OS X and iOS.
It makes it very simple.
Search for that function and you will find examples of how to use it.
After a while (a day) working on the code above, I finally get it through. But don't know about the performance. Someone comment and help me improve about performance, please. Thanks.
- (BOOL) test:(NSString*)aString include:(NSString*) keyWord doTrim:(BOOL)doTrim {
// break recursion.
if([aString length] < [keyWord length]) return false;
// First, loop through each keyword's character
for (NSUInteger i = 0; i < [keyWord length]; i++) {
// Get #"aA#∂", #"bBß", #"c©C<(" or only the character itself.
// like, if the keyword's character is A, return the string #"aA#∂".
// If the character is not in the variants set, eg. P, return #"P"
NSString* c = [NSString stringWithFormat:#"%C", [keyWord characterAtIndex:i]];
NSString *rs = [self variantsWithChar:c];
NSString *theTargetChar = [NSString stringWithFormat:#"%C", [aString characterAtIndex:i]];
// Check if rs (#"aA#∂" or #"P") contains aString[i] character
if([rs rangeOfString:theTargetChar].location == NSNotFound) {
// If not the same char, remove first char in targetString (aString), recursion to match again.
return [self test:[aString substringFromIndex:1] include:keyWord doTrim:NO];
}
}
// If all match with keyword, return true.
return true;
}
If you remove all comment, it'll be pretty short...
////////////////////////////////////////
- (NSString *) variantsWithChar:(NSString *) c{
for (NSString *s in self.variants) {
if ([s rangeOfString:c].location != NSNotFound) {
return s;
}
}
return c;
}
You could try comparing ascii values of the japanese characters in the variants's each character's ascii value. These japanese characters aren't treated like usual characters or string. Hence, string functions like rangeOfString won't work on them.
to be more precise: have a look at the following code.
it will search for "∂" in the string "aA#∂"
NSString *string = #"aA#∂";
NSMutableSet *listOfAsciiValuesOfString = [self getListOfAsciiValuesForString:string]; //method definition given below
NSString *charToSearch = #"∂";
NSNumber *ascii = [NSNumber numberWithInt:[charToSearch characterAtIndex:0]];
int countBeforeAdding = [listOfAsciiValuesOfString count],countAfterAdding = 0;
[listOfAsciiValuesOfString addObject:ascii];
countAfterAdding = [listOfAsciiValuesOfString count];
if(countAfterAdding == countBeforeAdding){ //element found
NSLog(#"element exists"); //return string
}else{
NSLog(#"Doesnt exists"); //return char
}
===================================
-(NSMutableSet*)getListOfAsciiValuesForString:(NSString*)string{
NSMutableSet *set = [[NSMutableSet alloc] init];
for(int i=0;i<[string length];i++){
NSNumber *ascii = [NSNumber numberWithInt:[string characterAtIndex:i]];
[set addObject:ascii];
}
return set;
}

NSString "nil or empty" check -- is this complete?

I was writing a small Category on NSString, and I wanted to know if this method is accurately handles all potential use cases:
Update: to clarify -- I wanted to make sure I'm not missing some oddball case involving character encodings, etc..
#implementation NSString (Helpers)
+(BOOL)stringIsNilOrEmpty:(NSString*)aString {
if (!aString)
return YES;
return [aString isEqualToString:#""];
}
#end
Sample usage:
-(void) sampleUsage {
NSString *emptyString = #"";
NSString *nilString = nil;
NSAssert([NSString stringIsNilOrEmpty:nilString] == YES, #"String is nil/empty");
NSAssert([NSString stringIsNilOrEmpty:emptyString] == YES, #"String is nil/empty");
}
#end
I only use the next conditional and do not even need a category:
if (!aString.length)
{
...
}
Using Objective-C theory, a message to NIL will return nil or zero, so basically you do not have to test for nil.
You can simplify the code by removing conditional:
+(BOOL)stringIsNilOrEmpty:(NSString*)aString {
return !(aString && aString.length);
}
#dasblinkenlight's answer is fine, but a much more readable conditional check I would use is:
NSString *string = ...; // define the string
if ([string length] == 0) {
// Do stuff with the string
} else {
// The string is empty or nil here
}
Very concise and does not require a separate convenience function definition. It's easy enough to remember.
EDIT: #Michael G. Emmons posted this as the last comment to that answer... credit to him but I'm listing this as an answer in its own right.
Some examples of this sort of "is not empty or blank" tests as a category on NSString.
// Please note that in general I advocate using a prefix on category methods
// to avoid category collisions. I've not done this here for clarity.
// The #interface is also excluded from this example for brevity.
#implementation NSString (MyAdditions)
- (BOOL)isNotEmpty
{
return [self length] != 0;
}
- (BOOL)isNotBlank
{
if ([self isNotEmpty])
{
NSCharacterSet *nonWhitespaceSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] invertedSet];
NSRange range = [self rangeOfCharactersFromSet:nonWhitespaceSet];
return range.location != NSNotFound;
}
return NO;
}
#end
Simply Check your string length
> if (!yourString.length){
> //your code } a
message to NIL will return nil or 0, so no need to test for nil :).
Happy coding ...
Make sure to check for spaces, trim white spaces before calculating length.
+(BOOL)stringIsNilOrEmpty:(NSString*)aString {
return !aString || [[aString stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceCharacterSet]] length] == 0;
}

Trying to work with NSString but I'm having problems comparing two strings

I have a simple program that I'm testing a printer class in.
-(void) setInkType {
NSMutableString *theInkType;
InkType typeOfInk;
char inkFromInput[50];
NSLog(#"What type of ink are you using?");
NSLog(#"Options are photoInk, lazerJet, regularInk");
fgets(inkFromInput,50,stdin);
theInkType = [[NSMutableString alloc] initWithUTF8String:inkFromInput];
NSLog(#"%#",theInkType);
if([theInkType compare: #"photoInk"]==true) {
typeOfInk.photoInk = 564;
NSLog(#"Your using a photo ink of type %d",typeOfInk.photoInk);
inkType.photoInk = typeOfInk.photoInk;
}
else { if ([theInkType compare: #"lazerJet"] == true) {
typeOfInk.lazerJet = 94;
NSLog(#"Your using a lazer toner of type %d",typeOfInk.lazerJet);
inkType.lazerJet = typeOfInk.lazerJet;
}
else { if ([theInkType compare: #"regularInk"] == true) {
typeOfInk.regularInk = 910;
NSLog(#"Your using a regular ink of type %d",typeOfInk.regularInk);
inkType.regularInk = typeOfInk.regularInk;
}
}
}
}
When I run this I can enter in "photoInk" and "lazerInk" and I get a proper output. Why is it when I type "regularInk" I get a bad output?
I'm thinking it could be my {}'s but I'm not quite sure. I've been scratching my head for a few hours at this.
If there is anymore Cocoa flavoring I can do to make this look smoother let me know too please.
-compare: doesn't return a boolean true/false value, it returns an NSComparisonResult, which is either NSOrderedAscending, NSOrderedSame, or NSOrderedDescending.
So you could do this:
if ([theInkType compare: #"photoInk"] == NSOrderedSame)
But really, the -isEqual: method is closer to your true intention.
if ([theInkType isEqual: #"photoInk"])
Also: you're doing your else clauses wrong. Not this:
if (x) {
...
}
else { if (y) {
...
} }
But this:
if (x) {
...
} else if (y) {
...
}
I think this should work for you. This is my answer which I have taken from the link:
Comparing text in UITextView?
SOLUTION-1: I have modified it here a bit to make it more easier for your case:
Let us assume String1 is one NSString.
//Though this is a case sensitive comparison of string
BOOL boolVal = [String1 isEqualToString:#"My Default Text"];
//Here is how you can do case insensitive comparison of string:
NSComparisonResult boolVal = [String1 compare:#"My Default Text" options:NSCaseInsensitiveSearch];
if(boolVal == NSOrderedSame)
{
NSLog(#"Strings are same");
}
else
{
NSLog(#"Strings are Different");
}
Here if boolVal is NSOrderedSame then you can say that strings are same else they are different.
SOLUTION-2: Also you don't find this easy, you can refer to Macmade's answer under the same link.
Hope this helps you.
Hope this helps you.

If else statment not work in my app

I´m making a dictionary (this is my test app)
here is my code which not work:
- (IBAction) btnClickMe_Clicked:(id)sender {
NSString *kw = s.text;
NSString *encodedkw = [kw stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *mms = [NSString stringWithFormat: #"%#", encodedkw];
if (mms=NULL){
iMessageLabel.text=#"put text";
} else if (mms=#"a"){
iMessageLabel.text=#"this is a";
} else if (mms=#"b"){
iMessageLabel.text=#"this is b";
}
}
anybody have some idea with this ?
thanks
ALex
You cannot use == on NSString objects. Try doing this:
if (encodedkw == nil){
iMessageLabel.text=#"put text";
} else if ([encodedkw isEqualToString:#"a"]){
iMessageLabel.text=#"this is a";
} else if ([encodedkw isEqualToString:#"b"]){
iMessageLabel.text=#"this is b";
}
mms should be equal to encodedkw so I switched to using that. Also I'm using isEqualToString for string comparison. Finally, I've changed the null check to check against nil instead of NULL.
You've used = rather than ==
May it happen, that you need to call some kind of string manipulation routine like compare to compare strings, not just comparing the pointers?
Besides mms=NIL means assignment NIL to mms not comparison desired.
Upd.: NIL does not mean empty string. You should write [mms length] == 0 instead to see if the string is empty.