Objective-C
String Manipulation
Programming
Coding Tips
Software Development

How do I check if a string contains another string in Objective-C?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Checking whether one NSString contains another is a very common Objective-C task, and the correct approach depends mostly on deployment target and matching rules. For modern code the shortest answer is often containsString:, but rangeOfString: remains the more flexible tool and is still the best fallback for older platforms.

Use rangeOfString: As The Compatible Baseline

The classic Objective-C solution is rangeOfString:. It searches for the first occurrence of a substring and returns an NSRange. If the substring is missing, the range location is NSNotFound.

objective-c
1NSString *mainString = @"Hello, World!";
2NSString *searchString = @"World";
3
4NSRange range = [mainString rangeOfString:searchString];
5
6if (range.location != NSNotFound) {
7    NSLog(@"Found substring");
8} else {
9    NSLog(@"Substring not found");
10}

This works on older iOS and macOS targets, which is why it is still the safest general answer in Objective-C codebases that care about compatibility.

Use containsString: For Simpler Modern Code

If your deployment target includes iOS 8 or later, containsString: is more direct:

objective-c
1NSString *mainString = @"Hello, World!";
2NSString *searchString = @"World";
3
4BOOL contains = [mainString containsString:searchString];
5NSLog(@"%@", contains ? @"YES" : @"NO");

This returns a BOOL, which is exactly what you want when the only question is containment. It is more readable than checking NSNotFound, but it does not replace rangeOfString: when you need more control.

Handle Case-Insensitive Searches Explicitly

Both of the basic examples above are case-sensitive. If the match should ignore case, use rangeOfString:options:.

objective-c
1NSString *mainString = @"HELLO, WORLD!";
2NSString *searchString = @"world";
3
4NSRange range = [mainString rangeOfString:searchString
5                                  options:NSCaseInsensitiveSearch];
6
7if (range.location != NSNotFound) {
8    NSLog(@"Found case-insensitive match");
9}

This is usually better than lowercasing both strings manually because it keeps the search behavior in one place and works naturally with the NSString APIs.

If locale rules matter, use the longer variant with an explicit locale. That is more advanced, but it matters when the application handles natural-language text rather than simple identifiers.

Search Only Part Of The String When Needed

Sometimes the requirement is not "does the whole string contain this substring?" but "does this substring appear after a certain point?" or "inside a particular range only?" In that case, use the range-limited search API.

objective-c
1NSString *text = @"prefix:important-value:suffix";
2NSRange searchRange = NSMakeRange(7, text.length - 7);
3
4NSRange result = [text rangeOfString:@"important"
5                             options:0
6                               range:searchRange];
7
8if (result.location != NSNotFound) {
9    NSLog(@"Found it inside the requested range");
10}

This is one reason rangeOfString: remains the more powerful building block even in modern code.

Know What Kind Of Match You Really Need

A containment check is different from checking prefixes, suffixes, or exact equality. If the real question is "does the string start with" or "does the string end with", use hasPrefix: or hasSuffix: instead of a general substring search.

That makes the code easier to read and communicates the real intent immediately.

Common Pitfalls

  • Using containsString: on projects that still target older iOS versions where it is unavailable.
  • Forgetting that default substring searches are case-sensitive.
  • Lowercasing both strings manually when rangeOfString:options: would express the intent more clearly.
  • Treating a containment check as equivalent to a prefix or suffix check.
  • Forgetting to handle nil values before sending messages to the strings involved.

Summary

  • 'rangeOfString: is the classic Objective-C way to test substring containment and works across older targets.'
  • 'containsString: is cleaner when you only need a BOOL and your deployment target supports it.'
  • Use NSCaseInsensitiveSearch when matching should ignore case.
  • Reach for prefix, suffix, or range-limited APIs when those better match the real requirement.

Course illustration
Course illustration

All Rights Reserved.