macOS String Processing Objective-C Samples

macOS Objective-C string processing examples including NSString, NSMutableString, searching, regex, and encoding

💻 NSString Basics objectivec

🟢 simple ⭐⭐

Create, manipulate, and format NSString objects

⏱️ 20 min 🏷️ objectivec, macos, string, text
Prerequisites: Objective-C basics, Foundation framework
// macOS Objective-C NSString Basics
// Using Foundation framework

#import <Foundation/Foundation.h>

// MARK: - 1. String Creation

@interface StringCreation : NSObject

+ (void)demonstrateCreation {
    NSLog(@"--- String Creation ---");

    // Literal strings
    NSString *literal = @"Hello, World!";
    NSLog(@"Literal: %@", literal);

    // From C string
    const char *cString = "From C string";
    NSString *fromC = [NSString stringWithUTF8String:cString];
    NSLog(@"From C: %@", fromC);

    // With format
    NSString *formatted = [NSString stringWithFormat:@"Age: %d, Name: %@", 30, @"Alice"];
    NSLog(@"Formatted: %@", formatted);

    // Empty string
    NSString *empty = [NSString string];
    NSLog(@"Empty string length: %lu", (unsigned long)empty.length);

    // From numbers
    NSString *fromInt = [NSString stringWithFormat:@"%d", 42];
    NSString *fromFloat = [NSString stringWithFormat:@"%.2f", 3.14159];
    NSLog(@"From int: %@, From float: %@", fromInt, fromFloat);

    // Multiline
    NSString *multiline = @"Line 1\nLine 2\nLine 3";
    NSLog(@"Multiline:\n%@", multiline);

    // Using string constants
    static NSString *const kConstantString = @"Constant";
    NSLog(@"Constant: %@", kConstantString);
}

@end

// MARK: - 2. String Properties

@interface StringProperties : NSObject

+ (void)demonstrateProperties {
    NSLog(@"\n--- String Properties ---");

    NSString *text = @"Hello, World!";

    // Length
    NSLog(@"Length: %lu", (unsigned long)text.length);

    // Empty check
    NSLog(@"Is empty: %@", text.length == 0 ? @"YES" : @"NO");

    // Character access
    unichar firstChar = [text characterAtIndex:0];
    NSLog(@"First char: %C", firstChar);

    // Get characters
    NSInteger length = text.length;
    unichar *buffer = malloc(sizeof(unichar) * length);

    [text getCharacters:buffer range:NSMakeRange(0, length)];

    NSLog(@"All characters:");
    for (NSInteger i = 0; i < length; i++) {
        NSLog(@"  %ld: %C", (long)i, buffer[i]);
    }

    free(buffer);

    // UTF-8 representation
    const char *utf8 = [text UTF8String];
    NSLog(@"UTF-8: %s", utf8);

    // Hash
    NSUInteger hash = [text hash];
    NSLog(@"Hash: %lu", (unsigned long)hash);
}

@end

// MARK: - 3. String Comparison

@interface StringComparison : NSObject

+ (void)demonstrateComparison {
    NSLog(@"\n--- String Comparison ---");

    NSString *str1 = @"Apple";
    NSString *str2 = @"apple";
    NSString *str3 = @"Apple";

    // Equality
    BOOL isEqual = [str1 isEqualToString:str3];
    NSLog(@"%@ == %@: %@", str1, str3, isEqual ? @"YES" : @"NO");

    BOOL isEqual2 = [str1 isEqualToString:str2];
    NSLog(@"%@ == %@: %@", str1, str2, isEqual2 ? @"YES" : @"NO");

    // Case insensitive compare
    NSComparisonResult result = [str1 caseInsensitiveCompare:str2];
    NSLog(@"Case insensitive compare: %ld", (long)result);

    // Compare
    result = [str1 compare:str2];
    if (result == NSOrderedAscending) {
        NSLog(@"%@ < %@", str1, str2);
    } else if (result == NSOrderedDescending) {
        NSLog(@"%@ > %@", str1, str2);
    } else {
        NSLog(@"%@ == %@", str1, str2);
    }

    // Has prefix/suffix
    NSString *filename = @"document.txt";

    BOOL hasPrefix = [filename hasPrefix:@"doc"];
    BOOL hasSuffix = [filename hasSuffix:@".txt"];

    NSLog(@"Has prefix 'doc': %@", hasPrefix ? @"YES" : @"NO");
    NSLog(@"Has suffix '.txt': %@", hasSuffix ? @"YES" : @"NO");

    // Common prefix
    NSString *commonPrefix = [str1 commonPrefixWithString:@"Appetizer" options:0];
    NSLog(@"Common prefix: %@", commonPrefix);
}

@end

// MARK: - 4. String Manipulation

@interface StringManipulation : NSObject

+ (void)demonstrateManipulation {
    NSLog(@"\n--- String Manipulation ---");

    // Substring
    NSString *text = @"Hello, World!";

    NSString *substring = [text substringFromIndex:7];
    NSLog(@"From index 7: %@", substring);

    substring = [text substringToIndex:5];
    NSLog(@"To index 5: %@", substring);

    substring = [text substringWithRange:NSMakeRange(7, 5)];
    NSLog(@"Range [7, 5]: %@", substring);

    // Uppercase/Lowercase
    NSLog(@"Uppercase: %@", [text uppercaseString]);
    NSLog(@"Lowercase: %@", [text lowercaseString]);
    NSLog(@"Capitalized: %@", [text capitalizedString]);

    // Trim
    NSString *padded = @"  Hello  ";
    NSLog(@"Original: '%@'", padded);
    NSLog(@"Trimmed: '%@'", [padded stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]);

    // Padding
    NSString *paddedLeft = [NSString stringWithFormat:@"%-10s", "Left"];
    NSString *paddedRight = [NSString stringWithFormat:@"%10s", "Right"];

    NSLog(@"Padded left: '%@'", paddedLeft);
    NSLog(@"Padded right: '%@'", paddedRight);

    // Replacing
    NSString *original = @"Hello, World!";
    NSString *replaced = [original stringByReplacingOccurrencesOfString:@"World"
                                                               withString:@"Objective-C"];
    NSLog(@"Replaced: %@", replaced);

    // Replacing with range
    NSString *rangeReplaced = [original stringByReplacingCharactersInRange:NSMakeRange(0, 5)
                                                             withString:@"Hi"];
    NSLog(@"Range replaced: %@", rangeReplaced);
}

@end

// MARK: - 5. String Searching

@interface StringSearching : NSObject

+ (void)demonstrateSearching {
    NSLog(@"\n--- String Searching ---");

    NSString *text = @"The quick brown fox jumps over the lazy dog";

    // Contains
    BOOL contains = [text containsString:@"fox"];
    NSLog(@"Contains 'fox': %@", contains ? @"YES" : @"NO");

    // Range of string
    NSRange range = [text rangeOfString:@"brown"];
    if (range.location != NSNotFound) {
        NSLog(@"Found 'brown' at: %@", NSStringFromRange(range));
    }

    // Not found
    range = [text rangeOfString:@"cat"];
    if (range.location == NSNotFound) {
        NSLog(@"'cat' not found");
    }

    // Case insensitive search
    range = [text rangeOfString:@"THE"
                           options:NSCaseInsensitiveSearch];
    if (range.location != NSNotFound) {
        NSLog(@"Found 'THE' (case insensitive) at: %@", NSStringFromRange(range));
    }

    // Find all occurrences
    NSString *search = @"o";
    NSRange searchRange = NSMakeRange(0, text.length);
    NSMutableArray *occurrences = [NSMutableArray array];

    while (searchRange.location < text.length) {
        range = [text rangeOfString:search
                            options:0
                              range:searchRange];

        if (range.location == NSNotFound) {
            break;
        }

        [occurrences addObject:[NSNumber numberWithUnsignedInteger:range.location]];
        searchRange.location = range.location + range.length;
        searchRange.length = text.length - searchRange.location;
    }

    NSLog(@"Occurrences of '%@': %@", search, occurrences);

    // Find between
    NSString *startTag = @"<title>";
    NSString *endTag = @"</title>";
    NSString *html = @"<html><title>My Page</title></html>";

    NSRange startRange = [html rangeOfString:startTag];
    NSRange endRange = [html rangeOfString:endTag];

    if (startRange.location != NSNotFound && endRange.location != NSNotFound) {
        NSRange contentRange = NSMakeRange(startRange.location + startTag.length,
                                          endRange.location - startRange.location - startTag.length);
        NSString *content = [html substringWithRange:contentRange];
        NSLog(@"Content between tags: %@", content);
    }
}

@end

// MARK: - 6. String Splitting and Joining

@interface SplitJoin : NSObject

+ (void)demonstrateSplitJoin {
    NSLog(@"\n--- Split and Join ---");

    // Split by components
    NSString *csv = @"Apple,Banana,Cherry,Date";
    NSArray *components = [csv componentsSeparatedByString:@","];
    NSLog(@"CSV split: %@", components);

    // Split by character set
    NSString *sentence = @"Hello World How Are You";
    NSArray *words = [sentence componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    NSLog(@"Words: %@", words);

    // Split by lines
    NSString *multiline = @"Line 1\nLine 2\nLine 3";
    NSArray *lines = [multiline componentsSeparatedByString:@"\n"];
    NSLog(@"Lines: %@", lines);

    // Join
    NSString *joined = [components componentsJoinedByString:@" | "];
    NSLog(@"Joined: %@", joined);

    // Join with paths
    NSArray *pathComponents = @[@"Users", @"alice", @"Documents", @"file.txt"];
    NSString *path = [pathComponents componentsJoinedByString:@"/"];
    NSLog(@"Path: %@", path);

    // Enumerate lines
    NSLog(@"\nEnumerate lines:");
    [multiline enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) {
        NSLog(@"  Line: %@", line);
    }];

    // Enumerate substrings
    NSLog(@"\nEnumerate substrings by comma:");
    [csv enumerateSubstringsInRange:NSMakeRange(0, csv.length)
                           options:NSStringEnumerationByComposedCharacterSequences
                        usingBlock:^(NSString *substring,
                                     NSRange substringRange,
                                     NSRange enclosingRange,
                                     BOOL *stop) {
        if ([substring isEqualToString:@","]) {
            NSLog(@"Found comma at: %@", NSStringFromRange(substringRange));
        }
    }];
}

@end

// MARK: - 7. NSMutableString

@interface MutableString : NSObject

+ (void)demonstrateMutable {
    NSLog(@"\n--- NSMutableString ---");

    // Create
    NSMutableString *mutable = [NSMutableString stringWithString:@"Hello"];
    NSLog(@"Initial: %@", mutable);

    // Append
    [mutable appendString:@", World!"];
    NSLog(@"After append: %@", mutable);

    // Append format
    [mutable appendFormat:@" Number: %d", 42];
    NSLog(@"After append format: %@", mutable);

    // Insert
    [mutable insertString:@"Beautiful " atIndex:7];
    NSLog(@"After insert: %@", mutable);

    // Delete
    NSRange deleteRange = [mutable rangeOfString:@", Number: 42"];
    if (deleteRange.location != NSNotFound) {
        [mutable deleteCharactersInRange:deleteRange];
    }
    NSLog(@"After delete: %@", mutable);

    // Replace
    NSRange replaceRange = NSMakeRange(0, 5);
    [mutable replaceCharactersInRange:replaceRange withString:@"Hi"];
    NSLog(@"After replace: %@", mutable);

    // Set string
    [mutable setString:@"New content"];
    NSLog(@"After set: %@", mutable);

    // Replace all occurrences
    [mutable setString:@"Hello Hello Hello"];
    [mutable replaceOccurrencesOfString:@"Hello"
                             withString:@"Good"
                                options:0
                                  range:NSMakeRange(0, mutable.length)];
    NSLog(@"After replace all: %@", mutable);
}

@end

// MARK: - 8. String Formatting

@interface StringFormatting : NSObject

+ (void)demonstrateFormatting {
    NSLog(@"\n--- String Formatting ---");

    // Number formatting
    int integer = 42;
    float floating = 123.456f;
    double pi = 3.14159265359;

    NSString *intStr = [NSString stringWithFormat:@"%d", integer];
    NSString *floatStr = [NSString stringWithFormat:@"%.2f", floating];
    NSString *piStr = [NSString stringWithFormat:@"%.4f", pi];

    NSLog(@"Integer: %@, Float: %@, Pi: %@", intStr, floatStr, piStr);

    // Padding with zeros
    NSString *padded = [NSString stringWithFormat:@"%05d", 42];
    NSLog(@"Zero-padded: %@", padded);

    // Alignment
    NSString *leftAlign = [NSString stringWithFormat:@"%-10s", "left"];
    NSString *rightAlign = [NSString stringWithFormat:@"%10s", "right"];

    NSLog(@"Left aligned: '%@'", leftAlign);
    NSLog(@"Right aligned: '%@'", rightAlign);

    // Hexadecimal
    int hexValue = 255;
    NSString *hexStr = [NSString stringWithFormat:@"0x%X", hexValue];
    NSLog(@"Hex: %@", hexStr);

    // Scientific notation
    double large = 1234567.89;
    NSString *scientific = [NSString stringWithFormat:@"%e", large];
    NSLog(@"Scientific: %@", scientific);

    // Percent
    double percentValue = 0.7565;
    NSString *percent = [NSString stringWithFormat:@"%.1f%%", percentValue * 100];
    NSLog(@"Percent: %@", percent);

    // Currency
    NSNumberFormatter *currencyFormatter = [[NSNumberFormatter alloc] init];
    currencyFormatter.numberStyle = NSNumberFormatterCurrencyStyle;
    currencyFormatter.currencyCode = @"USD";

    NSNumber *amount = @(1234.56);
    NSString *currency = [currencyFormatter stringFromNumber:amount];
    NSLog(@"Currency: %@", currency);

    // Date formatting
    NSDate *now = [NSDate date];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";

    NSString *dateString = [dateFormatter stringFromDate:now];
    NSLog(@"Date: %@", dateString);

    // Pluralization
    NSInteger count = 5;
    NSString *plural = [NSString stringWithFormat:@"%ld item%@", (long)count, count == 1 ? @"" : @"s"];
    NSLog(@"Plural: %@", plural);
}

@end

// MARK: - Main Demonstration

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"=== macOS Objective-C NSString Examples ===\n");

        // 1. Creation
        [StringCreation demonstrateCreation];

        // 2. Properties
        [StringProperties demonstrateProperties];

        // 3. Comparison
        [StringComparison demonstrateComparison];

        // 4. Manipulation
        [StringManipulation demonstrateManipulation];

        // 5. Searching
        [StringSearching demonstrateSearching];

        // 6. Split and Join
        [SplitJoin demonstrateSplitJoin];

        // 7. Mutable
        [MutableString demonstrateMutable];

        // 8. Formatting
        [StringFormatting demonstrateFormatting];

        NSLog(@"\n=== NSString Examples Completed ===");
    }

    return 0;
}

💻 Regular Expressions objectivec

🟡 intermediate ⭐⭐⭐⭐

Use NSRegularExpression for pattern matching, validation, and text replacement

⏱️ 30 min 🏷️ objectivec, macos, string, regex
Prerequisites: Intermediate Objective-C, NSRegularExpression
// macOS Objective-C Regular Expressions Examples
// Using Foundation framework

#import <Foundation/Foundation.h>

// MARK: - 1. Basic Pattern Matching

@interface RegexBasics : NSObject

+ (void)demonstrateMatching {
    NSLog(@"--- Basic Pattern Matching ---");

    NSString *text = @"Hello World 123";

    // Match digits
    NSError *error = NULL;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\d+"
                                                                               options:0
                                                                                 error:&error];

    if (error) {
        NSLog(@"Regex error: %@", error.localizedDescription);
        return;
    }

    NSTextCheckingResult *match = [regex firstMatchInString:text
                                                    options:0
                                                      range:NSMakeRange(0, text.length)];

    if (match) {
        NSRange matchRange = [match range];
        NSString *matched = [text substringWithRange:matchRange];
        NSLog(@"Found digits: %@ at range: %@", matched, NSStringFromRange(matchRange));
    }

    // Match all occurrences
    NSArray *matches = [regex matchesInString:text
                                        options:0
                                          range:NSMakeRange(0, text.length)];

    NSLog(@"Total matches: %lu", (unsigned long)matches.count);

    for (NSTextCheckingResult *result in matches) {
        NSString *matched = [text substringWithRange:result.range];
        NSLog(@"  Match: %@", matched);
    }
}

@end

// MARK: - 2. Common Patterns

@interface CommonPatterns : NSObject

+ (BOOL)validateEmail:(NSString *)email {
    NSString *pattern = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";

    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
                                                                               options:NSRegularExpressionCaseInsensitive
                                                                                 error:nil];

    NSUInteger matches = [regex numberOfMatchesInString:email
                                                 options:0
                                                   range:NSMakeRange(0, email.length)];

    return matches > 0;
}

+ (BOOL)validatePhone:(NSString *)phone {
    NSString *pattern = @"\\d{3}-\\d{3}-\\d{4}";

    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
                                                                               options:0
                                                                                 error:nil];

    NSUInteger matches = [regex numberOfMatchesInString:phone
                                                 options:0
                                                   range:NSMakeRange(0, phone.length)];

    return matches > 0;
}

+ (BOOL)validateURL:(NSString *)url {
    NSString *pattern = @"https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&\\/=]*)";

    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
                                                                               options:NSRegularExpressionCaseInsensitive
                                                                                 error:nil];

    NSUInteger matches = [regex numberOfMatchesInString:url
                                                 options:0
                                                   range:NSMakeRange(0, url.length)];

    return matches > 0;
}

+ (BOOL)validateHexColor:(NSString *)hex {
    NSString *pattern = @"^#[0-9A-Fa-f]{6}$";

    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
                                                                               options:0
                                                                                 error:nil];

    NSUInteger matches = [regex numberOfMatchesInString:hex
                                                 options:0
                                                   range:NSMakeRange(0, hex.length)];

    return matches > 0;
}

+ (void)demonstrateValidation {
    NSLog(@"\n--- Common Validation Patterns ---");

    // Email
    NSArray *emails = @[@"[email protected]", @"invalid-email", @"[email protected]"];

    for (NSString *email in emails) {
        BOOL valid = [self validateEmail:email];
        NSLog(@"Email '%@': %@", email, valid ? @"Valid" : @"Invalid");
    }

    // Phone
    NSArray *phones = @[@"123-456-7890", @"555-1234", @"12-3456-7890"];

    for (NSString *phone in phones) {
        BOOL valid = [self validatePhone:phone];
        NSLog(@"Phone '%@': %@", phone, valid ? @"Valid" : @"Invalid");
    }

    // URL
    NSArray *urls = @[@"https://www.example.com", @"http://test.org", @"not-a-url"];

    for (NSString *url in urls) {
        BOOL valid = [self validateURL:url];
        NSLog(@"URL '%@': %@", url, valid ? @"Valid" : @"Invalid");
    }

    // Hex color
    NSArray *colors = @[@"#FF0000", @"#00FF00", @"#0000FF", @"#GGG000"];

    for (NSString *color in colors) {
        BOOL valid = [self validateHexColor:color];
        NSLog(@"Color '%@': %@", color, valid ? @"Valid" : @"Invalid");
    }
}

@end

// MARK: - 3. Search and Replace

@interface SearchReplace : NSObject

+ (void)demonstrateSearchReplace {
    NSLog(@"\n--- Search and Replace ---");

    NSString *text = @"The price is $100. Another item costs $50.";

    // Find all prices
    NSRegularExpression *priceRegex = [NSRegularExpression regularExpressionWithPattern:@"\\$\\d+"
                                                                                    options:0
                                                                                      error:nil];

    NSArray *matches = [priceRegex matchesInString:text
                                            options:0
                                              range:NSMakeRange(0, text.length)];

    NSLog(@"Found prices:");
    for (NSTextCheckingResult *match in matches) {
        NSString *price = [text substringWithRange:match.range];
        NSLog(@"  %@", price);
    }

    // Replace prices
    NSString *modified = [priceRegex stringByReplacingMatchesInString:text
                                                          options:0
                                                            range:NSMakeRange(0, text.length)
                                                     withTemplate:@"$$$"];

    NSLog(@"After replacement: %@", modified);

    // Replace with callback
    NSString *result = [priceRegex stringByReplacingMatchesInString:text
                                                           options:0
                                                             range:NSMakeRange(0, text.length)
                                                      usingBlock:^NSString *(NSTextCheckingResult *match, NSString *offset) {
        NSString *price = [text substringWithRange:match.range];
        NSInteger value = [[price substringFromIndex:1] integerValue];

        // Apply 10% discount
        NSInteger discounted = value * 0.9;

        return [NSString stringWithFormat:@"$%ld", (long)discounted];
    }];

    NSLog(@"After discount: %@", result);

    // Multiple patterns
    NSString *html = @"<b>Bold</b> and <i>italic</i>";
    NSRegularExpression *tagRegex = [NSRegularExpression regularExpressionWithPattern:@"<[^>]+>"
                                                                                   options:0
                                                                                     error:nil];

    NSString *plainText = [tagRegex stringByReplacingMatchesInString:html
                                                             options:0
                                                               range:NSMakeRange(0, html.length)
                                                      withTemplate:@""];

    NSLog(@"HTML: %@", html);
    NSLog(@"Plain text: %@", plainText);
}

@end

// MARK: - 4. Extracting Data

@interface DataExtractor : NSObject

+ (NSArray *)extractEmailsFromText:(NSString *)text {
    NSString *pattern = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";

    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
                                                                               options:NSRegularExpressionCaseInsensitive
                                                                                 error:nil];

    NSArray *matches = [regex matchesInString:text
                                        options:0
                                          range:NSMakeRange(0, text.length)];

    NSMutableArray *emails = [NSMutableArray array];

    for (NSTextCheckingResult *match in matches) {
        NSString *email = [text substringWithRange:match.range];
        [emails addObject:email];
    }

    return [emails copy];
}

+ (NSArray *)extractURLsFromText:(NSString *)text {
    NSString *pattern = @"https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&\\/=]*)";

    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
                                                                               options:NSRegularExpressionCaseInsensitive
                                                                                 error:nil];

    NSArray *matches = [regex matchesInString:text
                                        options:0
                                          range:NSMakeRange(0, text.length)];

    NSMutableArray *urls = [NSMutableArray array];

    for (NSTextCheckingResult *match in matches) {
        NSString *url = [text substringWithRange:match.range];
        [urls addObject:url];
    }

    return [urls copy];
}

+ (NSDictionary *)extractKeyValuePairs:(NSString *)text {
    // Pattern: "key=value" or "key: value"
    NSString *pattern = @"([\\w]+)\\s*[=:]\\s*([^\\s]+)";

    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
                                                                               options:0
                                                                                 error:nil];

    NSArray *matches = [regex matchesInString:text
                                        options:0
                                          range:NSMakeRange(0, text.length)];

    NSMutableDictionary *pairs = [NSMutableDictionary dictionary];

    for (NSTextCheckingResult *match in matches) {
        if (match.numberOfRanges >= 3) {
            NSString *key = [text substringWithRange:[match rangeAtIndex:1]];
            NSString *value = [text substringWithRange:[match rangeAtIndex:2]];
            pairs[key] = value;
        }
    }

    return [pairs copy];
}

+ (void)demonstrateExtraction {
    NSLog(@"\n--- Data Extraction ---");

    // Extract emails
    NSString *contactText = @"Contact us at [email protected] or [email protected] for help.";

    NSArray *emails = [self extractEmailsFromText:contactText];
    NSLog(@"Emails found: %@", emails);

    // Extract URLs
    NSString *webText = @"Visit https://www.example.com or http://test.org for more info.";

    NSArray *urls = [self extractURLsFromText:webText];
    NSLog(@"URLs found: %@", urls);

    // Extract key-value pairs
    NSString *configText = @"host=localhost port=8080 debug=true timeout=30";

    NSDictionary *config = [self extractKeyValuePairs:configText];
    NSLog(@"Config pairs: %@", config);
}

@end

// MARK: - 5. Text Processing

@interface TextProcessor : NSObject

+ (NSString *)removeExtraWhitespace:(NSString *)text {
    // Replace multiple spaces with single space
    NSString *pattern = @"\\s+";

    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
                                                                               options:0
                                                                                 error:nil];

    NSString *result = [regex stringByReplacingMatchesInString:text
                                                         options:0
                                                           range:NSMakeRange(0, text.length)
                                                    withTemplate:@" "];

    return [result stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

+ (NSString *)capitalizeSentences:(NSString *)text {
    NSString *pattern = @"([.!?]\\s*)([a-z])";

    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
                                                                               options:0
                                                                                 error:nil];

    NSString *result = [regex stringByReplacingMatchesInString:text
                                                        options:0
                                                          range:NSMakeRange(0, text.length)
                                                   usingBlock:^NSString *(NSTextCheckingResult *match, NSString *offset) {
    NSString *prefix = [text substringWithRange:[match rangeAtIndex:1]];
    NSString *letter = [text substringWithRange:[match rangeAtIndex:2]];
    return [prefix stringByAppendingString:[letter uppercaseString]];
    }];

    // Capitalize first letter
    return [result stringByReplacingCharactersInRange:NSMakeRange(0, 1)
                                           withString:[[result substringToIndex:1] uppercaseString]];
}

+ (NSString *)escapeHTML:(NSString *)html {
    NSDictionary *replacements = @{
        @"&": @"&amp;",
        @"<": @"&lt;",
        @">": @"&gt;",
        @""": @"&quot;",
        @"'": @"&#39;"
    };

    NSString *result = html;

    for (NSString *key in replacements) {
        NSString *value = replacements[key];
        NSString *pattern = [NSRegularExpression escapedPatternForString:key];

        NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
                                                                                   options:0
                                                                                     error:nil];

        result = [regex stringByReplacingMatchesInString:result
                                                    options:0
                                                      range:NSMakeRange(0, result.length)
                                               withTemplate:value];
    }

    return result;
}

+ (void)demonstrateProcessing {
    NSLog(@"\n--- Text Processing ---");

    // Remove extra whitespace
    NSString *messy = @"Hello    world!   This   has   extra   spaces.  ";

    NSString *clean = [self removeExtraWhitespace:messy];
    NSLog(@"Original: '%@'", messy);
    NSLog(@"Clean: '%@'", clean);

    // Capitalize sentences
    NSString *lowercase = @"hello. this is a test. another sentence.";

    NSString *capitalized = [self capitalizeSentences:lowercase];
    NSLog(@"Capitalized: %@", capitalized);

    // Escape HTML
    NSString *html = @"<script>alert("XSS")</script>";
    NSString *escaped = [self escapeHTML:html];

    NSLog(@"HTML: %@", html);
    NSLog(@"Escaped: %@", escaped);
}

@end

// MARK: - Main Demonstration

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"=== macOS Objective-C Regular Expressions Examples ===\n");

        // 1. Basic matching
        [RegexBasics demonstrateMatching];

        // 2. Validation
        [CommonPatterns demonstrateValidation];

        // 3. Search and replace
        [SearchReplace demonstrateSearchReplace];

        // 4. Extraction
        [DataExtractor demonstrateExtraction];

        // 5. Processing
        [TextProcessor demonstrateProcessing];

        NSLog(@"\n=== Regular Expressions Examples Completed ===");
    }

    return 0;
}

💻 String Encoding and Decoding objectivec

🟡 intermediate ⭐⭐⭐

Handle different character encodings, base64, URL encoding, and data conversion

⏱️ 25 min 🏷️ objectivec, macos, string, encoding
Prerequisites: Intermediate Objective-C, Foundation framework
// macOS Objective-C Encoding Examples
// Using Foundation framework

#import <Foundation/Foundation.h>

// MARK: - 1. Character Encoding

@interface CharacterEncoding : NSObject

+ (void)demonstrateEncodings {
    NSLog(@"--- Character Encodings ---");

    NSString *text = @"Hello 世界 🌍";

    // UTF-8
    NSData *utf8Data = [text dataUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"UTF-8 bytes: %lu, data: %@", (unsigned long)utf8Data.length, utf8Data);

    // UTF-16
    NSData *utf16Data = [text dataUsingEncoding:NSUTF16StringEncoding];
    NSLog(@"UTF-16 bytes: %lu", (unsigned long)utf16Data.length);

    // UTF-32
    NSData *utf32Data = [text dataUsingEncoding:NSUTF32StringEncoding];
    NSLog(@"UTF-32 bytes: %lu", (unsigned long)utf32Data.length);

    // ASCII (lossy)
    NSData *asciiData = [text dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    NSString *fromAscii = [[NSString alloc] initWithData:asciiData encoding:NSASCIIStringEncoding];
    NSLog(@"ASCII (lossy): %@", fromAscii);

    // Decode from data
    NSString *decoded = [[NSString alloc] initWithData:utf8Data encoding:NSUTF8StringEncoding];
    NSLog(@"Decoded from UTF-8: %@", decoded);

    // Try different encodings
    NSStringEncoding encodings[] = {
        NSUTF8StringEncoding,
        NSUTF16StringEncoding,
        NSUTF32StringEncoding,
        NSISOLatin1StringEncoding
    };

    for (int i = 0; i < 4; i++) {
        NSData *data = [text dataUsingEncoding:encodings[i]];

        if (data) {
            NSString *decoded = [[NSString alloc] initWithData:data encoding:encodings[i]];

            if (decoded) {
                NSLog(@"Encoding %d: Success (%lu bytes)", i, (unsigned long)data.length);
            }
        }
    }

    // BOM detection
    NSLog(@"\n--- BOM Detection ---");

    NSData *dataWithBOM = [@"\xef\xbb\xbf" dataUsingEncoding:NSUTF8StringEncoding];
    NSString *testString = [[NSString alloc] initWithData:dataWithBOM encoding:NSUTF8StringEncoding];

    if (testString && [testString hasPrefix:@"\ufeff"]) {
        NSLog(@"BOM detected and removed");
    }
}

@end

// MARK: - 2. Base64 Encoding

@interface Base64Encoding : NSObject

+ (NSString *)encodeToBase64:(NSString *)text {
    NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding];
    return [data base64EncodedStringWithOptions:0];
}

+ (NSString *)decodeFromBase64:(NSString *)base64 {
    NSData *data = [[NSData alloc] initWithBase64EncodedString:base64 options:0];
    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}

+ (void)demonstrateBase64 {
    NSLog(@"\n--- Base64 Encoding ---");

    NSString *original = @"Hello, World!";
    NSString *encoded = [self encodeToBase64:original];

    NSLog(@"Original: %@", original);
    NSLog(@"Encoded: %@", encoded);

    NSString *decoded = [self decodeFromBase64:encoded];
    NSLog(@"Decoded: %@", decoded);

    // URL-safe base64
    NSData *data = [original dataUsingEncoding:NSUTF8StringEncoding];
    NSString *urlSafe = [data base64EncodedStringWithOptions:0];

    // Replace + and / with - and _
    urlSafe = [urlSafe stringByReplacingOccurrencesOfString:@"+" withString:@"-"];
    urlSafe = [urlSafe stringByReplacingOccurrencesOfString:@"/" withString:@"_"];

    NSLog(@"URL-safe: %@", urlSafe);

    // Base64 data
    NSLog(@"\nBase64 Data:");

    NSDictionary *json = @{@"name": @"Alice", @"age": @(30)};
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:json options:0 error:nil];

    NSString *jsonBase64 = [jsonData base64EncodedStringWithOptions:0];
    NSLog(@"JSON as Base64: %@", jsonBase64);
}

@end

// MARK: - 3. URL Encoding

@interface URLEncoding : NSObject

+ (NSString *)encodeURL:(NSString *)url {
    NSCharacterSet *allowedChars = [NSCharacterSet characterSetWithCharactersInString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"];

    return [url stringByAddingPercentEncodingWithAllowedCharacters:allowedChars];
}

+ (NSString *)decodeURL:(NSString *)url {
    return [url stringByRemovingPercentEncoding];
}

+ (NSString *)encodeFormParameter:(NSString *)param {
    NSCharacterSet *allowedChars = [NSCharacterSet characterSetWithCharactersInString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._*"];

    return [param stringByAddingPercentEncodingWithAllowedCharacters:allowedChars];
}

+ (NSDictionary *)parseQueryString:(NSString *)query {
    NSMutableDictionary *params = [NSMutableDictionary dictionary];

    NSArray *pairs = [query componentsSeparatedByString:@"&"];

    for (NSString *pair in pairs) {
        NSArray *kv = [pair componentsSeparatedByString:@"="];

        if (kv.count == 2) {
            NSString *key = [self decodeURL:kv[0]];
            NSString *value = [self decodeURL:kv[1]];
            params[key] = value;
        }
    }

    return [params copy];
}

+ (NSString *)buildQueryString:(NSDictionary *)params {
    NSMutableArray *pairs = [NSMutableArray array];

    for (NSString *key in params) {
        NSString *encodedKey = [self encodeFormParameter:key];
        NSString *encodedValue = [self encodeFormParameter:params[key]];
        [pairs addObject:[NSString stringWithFormat:@"%@=%@", encodedKey, encodedValue]];
    }

    return [pairs componentsJoinedByString:@"&"];
}

+ (void)demonstrateURLEncoding {
    NSLog(@"\n--- URL Encoding ---");

    // Encode URL
    NSString *url = @"https://example.com/search?q=hello world&lang=中文";

    NSString *encoded = [self encodeURL:url];
    NSLog(@"Original: %@", url);
    NSLog(@"Encoded: %@", encoded);

    // Decode URL
    NSString *decoded = [self decodeURL:encoded];
    NSLog(@"Decoded: %@", decoded);

    // Query string
    NSString *query = @"name=John%20Doe&age=30&city=New%20York";

    NSDictionary *params = [self parseQueryString:query];
    NSLog(@"Parsed query: %@", params);

    // Build query string
    NSDictionary *newParams = @{
        @"name": @"Alice",
        @"age": @"25",
        @"city": @"San Francisco"
    };

    NSString *newQuery = [self buildQueryString:newParams];
    NSLog(@"Built query: %@", newQuery);
}

@end

// MARK: - 4. HTML Entity Encoding

@interface HTMLEntityEncoding : NSObject

+ (NSString *)encodeHTMLEntities:(NSString *)text {
    NSDictionary *entities = @{
        @"&": @"&amp;",
        @"<": @"&lt;",
        @">": @"&gt;",
        @""": @"&quot;",
        @"'": @"&apos;",
        @"©": @"&copy;",
        @"®": @"&reg;",
        @"™": @"&trade;"
    };

    // Start with ampersand to avoid double-encoding
    NSString *result = [text stringByReplacingOccurrencesOfString:@"&" withString:@"&amp;"];

    for (NSString *key in entities) {
        if (![key isEqualToString:@"&"]) {
            result = [result stringByReplacingOccurrencesOfString:key
                                                     withString:entities[key]];
        }
    }

    return result;
}

+ (NSString *)decodeHTMLEntities:(NSString *)text {
    NSDictionary *entities = @{
        @"&amp;": @"&",
        @"&lt;": @"<",
        @"&gt;": @">",
        @"&quot;": @""",
        @"&apos;": @"'",
        @"&copy;": @"©",
        @"&reg;": @"®",
        @"&trade;": @"™"
    };

    NSString *result = text;

    for (NSString *entity in entities) {
        result = [result stringByReplacingOccurrencesOfString:entity
                                                 withString:entities[entity]];
    }

    // Numeric entities
    NSRegularExpression *numericRegex = [NSRegularExpression regularExpressionWithPattern:@"&#(\\d+);"
                                                                                    options:0
                                                                                      error:nil];

    result = [numericRegex stringByReplacingMatchesInString:result
                                                      options:0
                                                        range:NSMakeRange(0, result.length)
                                                 usingBlock:^NSString *(NSTextCheckingResult *match, NSString *offset) {
        NSString *number = [result substringWithRange:[match rangeAtIndex:1]];
        int code = [number intValue];
        return [NSString stringWithFormat:@"%C", (unichar)code];
    }];

    return result;
}

+ (void)demonstrateHTMLEntities {
    NSLog(@"\n--- HTML Entities ---");

    NSString *html = @"<script>alert("Hello & goodbye")</script> © 2024";

    NSString *encoded = [self encodeHTMLEntities:html];
    NSLog(@"Encoded: %@", encoded);

    NSString *decoded = [self decodeHTMLEntities:encoded];
    NSLog(@"Decoded: %@", decoded);
}

@end

// MARK: - 5. Hex Encoding

@interface HexEncoding : NSObject

+ (NSString *)encodeToHex:(NSData *)data {
    NSString *hex = [data description];
    return [hex stringByReplacingOccurrencesOfString:@"<" withString:@""]
                         stringByReplacingOccurrencesOfString:@">" withString:@""]
                         stringByReplacingOccurrencesOfString:@" " withString:@""];
}

+ (NSData *)decodeFromHex:(NSString *)hex {
    NSMutableData *data = [NSMutableData data];

    unsigned char wholeByte;
    char byteChars[3] = {'\0', '\0', '\0'};
    NSInteger i = 0;

    while (i < hex.length) {
        char c = [hex characterAtIndex:i];

        if (c == ' ' || c == '\n' || c == '\r') {
            i++;
            continue;
        }

        byteChars[0] = c;
        byteChars[1] = [hex characterAtIndex:++i];

        wholeByte = strtol(byteChars, NULL, 16);
        [data appendBytes:&wholeByte length:1];

        i++;
    }

    return [data copy];
}

+ (NSString *)stringToHex:(NSString *)text {
    NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding];
    return [self encodeToHex:data];
}

+ (NSString *)hexToString:(NSString *)hex {
    NSData *data = [self decodeFromHex:hex];
    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}

+ (void)demonstrateHexEncoding {
    NSLog(@"\n--- Hex Encoding ---");

    NSString *text = @"Hello";

    NSString *hex = [self stringToHex:text];
    NSLog(@"'%@' to hex: %@", text, hex);

    NSString *decoded = [self hexToString:hex];
    NSLog(@"Hex to string: %@", decoded);

    // Hex data
    NSData *data = [NSData dataWithBytes:(unsigned char[]){0xDE, 0xAD, 0xBE, 0xEF} length:4];
    NSString *dataHex = [self encodeToHex:data];
    NSLog(@"Data as hex: %@", dataHex);
}

@end

// MARK: - 6. Punycode (IDN)

@interface PunycodeEncoder : NSObject

+ (NSString *)encodePunycode:(NSString *)domain {
    // Simplified placeholder - actual implementation requires ICU library
    NSLog(@"Punycode encoding (placeholder): %@", domain);

    // For IDN, use NSString's IDN support via CFStringTransform or external library
    return domain;
}

@end

// MARK: - Main Demonstration

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"=== macOS Objective-C Encoding Examples ===\n");

        // 1. Character encoding
        [CharacterEncoding demonstrateEncodings];

        // 2. Base64
        [Base64Encoding demonstrateBase64];

        // 3. URL encoding
        [URLEncoding demonstrateURLEncoding];

        // 4. HTML entities
        [HTMLEntityEncoding demonstrateHTMLEntities];

        // 5. Hex encoding
        [HexEncoding demonstrateHexEncoding];

        NSLog(@"\n=== Encoding Examples Completed ===");
    }

    return 0;
}