NSString
string manipulation
iOS development
Swift programming
text parsing

Split an NSString to access one particular piece

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

To split an NSString (Objective-C) or String (Swift) and access a specific piece, use componentsSeparatedByString: in Objective-C or .components(separatedBy:) in Swift. These methods split the string at every occurrence of the delimiter and return an array of substrings. Access the desired piece by index. For more complex splitting (multiple delimiters, regex patterns), use componentsSeparatedByCharactersInSet: or NSRegularExpression. This article covers both Objective-C and Swift approaches with practical examples.

Objective-C: componentsSeparatedByString

objectivec
1NSString *path = @"Users/alice/Documents/report.pdf";
2NSArray *components = [path componentsSeparatedByString:@"/"];
3
4NSLog(@"%@", components);
5// ("Users", "alice", "Documents", "report.pdf")
6
7// Access specific piece
8NSString *filename = [components lastObject];    // "report.pdf"
9NSString *user = components[1];                  // "alice"
10NSString *first = [components firstObject];      // "Users"
11
12// Split CSV data
13NSString *csv = @"Alice,30,NYC,Engineer";
14NSArray *fields = [csv componentsSeparatedByString:@","];
15NSString *name = fields[0];  // "Alice"
16NSString *age = fields[1];   // "30"
17NSString *city = fields[2];  // "NYC"
18NSString *role = fields[3];  // "Engineer"

Objective-C: componentsSeparatedByCharactersInSet

Split on multiple delimiters at once:

objectivec
1// Split on spaces, commas, and semicolons
2NSString *text = @"Alice, Bob; Charlie Dave";
3NSCharacterSet *delimiters = [NSCharacterSet characterSetWithCharactersInString:@",; "];
4NSArray *names = [text componentsSeparatedByCharactersInSet:delimiters];
5// ("Alice", "", "Bob", "", "Charlie", "Dave")
6
7// Filter empty strings
8NSPredicate *notEmpty = [NSPredicate predicateWithFormat:@"length > 0"];
9NSArray *filtered = [names filteredArrayUsingPredicate:notEmpty];
10// ("Alice", "Bob", "Charlie", "Dave")
11
12// Split on whitespace and newlines
13NSString *multiLine = @"Hello  World\nFoo\tBar";
14NSArray *words = [multiLine componentsSeparatedByCharactersInSet:
15    [NSCharacterSet whitespaceAndNewlineCharacterSet]];
16NSArray *filteredWords = [words filteredArrayUsingPredicate:notEmpty];
17// ("Hello", "World", "Foo", "Bar")

Swift: components(separatedBy:)

swift
1let path = "Users/alice/Documents/report.pdf"
2let components = path.components(separatedBy: "/")
3
4print(components)  // ["Users", "alice", "Documents", "report.pdf"]
5
6let filename = components.last!   // "report.pdf"
7let user = components[1]          // "alice"
8
9// CSV parsing
10let csv = "Alice,30,NYC,Engineer"
11let fields = csv.components(separatedBy: ",")
12let name = fields[0]  // "Alice"
13let age = fields[1]   // "30"
14
15// Split on multiple characters
16let text = "Alice, Bob; Charlie"
17let names = text.components(separatedBy: CharacterSet(charactersIn: ",; "))
18    .map { $0.trimmingCharacters(in: .whitespaces) }
19    .filter { !$0.isEmpty }
20print(names)  // ["Alice", "Bob", "Charlie"]

Swift: split() Method

Swift's split() is more flexible and returns Substring (avoiding copies):

swift
1let sentence = "Hello   World   Swift"
2
3// split removes empty subsequences by default
4let words = sentence.split(separator: " ")
5print(words)  // ["Hello", "World", "Swift"]
6
7// Keep empty subsequences
8let wordsAll = sentence.split(separator: " ", omittingEmptySubsequences: false)
9print(wordsAll)  // ["Hello", "", "", "World", "", "", "Swift"]
10
11// Limit number of splits
12let limited = "a:b:c:d:e".split(separator: ":", maxSplits: 2)
13print(limited)  // ["a", "b", "c:d:e"]
14
15// Split with closure
16let mixed = "abc123def456"
17let parts = mixed.split { $0.isNumber }
18print(parts)  // ["abc", "def"]
19
20// Convert Substring to String
21let stringParts: [String] = sentence.split(separator: " ").map(String.init)

Practical Examples

Parse a URL

swift
1let url = "https://api.example.com:8080/v2/users?page=3"
2
3// Get the host
4let afterProtocol = url.components(separatedBy: "://").last!  // "api.example.com:8080/v2/users?page=3"
5let host = afterProtocol.components(separatedBy: "/").first!  // "api.example.com:8080"
6let hostname = host.components(separatedBy: ":").first!       // "api.example.com"
7
8// Get query parameter
9let query = url.components(separatedBy: "?").last!  // "page=3"
10let value = query.components(separatedBy: "=").last! // "3"

Parse a File Extension

swift
1// Objective-C
2NSString *filename = @"document.final.pdf";
3NSString *ext = [filename pathExtension];  // "pdf"
4NSString *name = [filename stringByDeletingPathExtension];  // "document.final"
5
6// Or with split
7NSArray *parts = [filename componentsSeparatedByString:@"."];
8NSString *extension = [parts lastObject];  // "pdf"
9
10// Swift
11let filename = "document.final.pdf"
12let ext = (filename as NSString).pathExtension  // "pdf"
13
14// Or with Swift URL
15let url = URL(fileURLWithPath: filename)
16print(url.pathExtension)  // "pdf"

Parse Key-Value Pairs

objectivec
1// Objective-C
2NSString *config = @"host=localhost;port=3306;db=myapp;user=root";
3NSArray *pairs = [config componentsSeparatedByString:@";"];
4NSMutableDictionary *dict = [NSMutableDictionary dictionary];
5
6for (NSString *pair in pairs) {
7    NSArray *keyValue = [pair componentsSeparatedByString:@"="];
8    if (keyValue.count == 2) {
9        dict[keyValue[0]] = keyValue[1];
10    }
11}
12NSLog(@"Host: %@", dict[@"host"]);  // "localhost"
13NSLog(@"Port: %@", dict[@"port"]);  // "3306"
swift
1// Swift
2let config = "host=localhost;port=3306;db=myapp;user=root"
3let dict = Dictionary(
4    uniqueKeysWithValues: config.components(separatedBy: ";")
5        .compactMap { pair -> (String, String)? in
6            let parts = pair.components(separatedBy: "=")
7            guard parts.count == 2 else { return nil }
8            return (parts[0], parts[1])
9        }
10)
11print(dict["host"]!)  // "localhost"
12print(dict["port"]!)  // "3306"

Common Pitfalls

  • Accessing an out-of-bounds index after split: If the delimiter is not found, the array contains the original string as a single element. Accessing components[1] when the delimiter does not exist causes an index-out-of-range crash. Always check components.count before accessing by index.
  • Forgetting that componentsSeparatedByString: creates empty strings for consecutive delimiters: Splitting "a,,b" by "," produces ["a", "", "b"]. Filter empty strings with NSPredicate (Objective-C) or .filter { !$0.isEmpty } (Swift).
  • Confusing split() and components(separatedBy:) in Swift: split() returns [Substring] and omits empty subsequences by default. components(separatedBy:) returns [String] and keeps empty strings. Choose based on whether you want empty strings filtered.
  • Using string splitting to parse URLs instead of URLComponents: Splitting URLs by /, ?, or & is fragile. Use URLComponents for reliable URL parsing that handles encoding, edge cases, and optional components correctly.
  • Not trimming whitespace after splitting: Splitting "Alice , Bob , Charlie" by "," produces ["Alice ", " Bob ", " Charlie"] with leading/trailing spaces. Apply .trimmingCharacters(in: .whitespaces) to each component.

Summary

  • Use componentsSeparatedByString: (Objective-C) or .components(separatedBy:) (Swift) to split on a single delimiter
  • Use componentsSeparatedByCharactersInSet: or CharacterSet to split on multiple delimiters
  • Use Swift's .split(separator:) for efficient splitting that omits empty subsequences and returns Substring
  • Always check components.count before accessing by index to avoid out-of-bounds crashes
  • Filter empty strings and trim whitespace after splitting for clean results

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.