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
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:
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:)
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):
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
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
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
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"
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