
原文:http://rypress.com/tutorials/objective-c/data-types/nsstring
NSString
在本教程的内容可能我们已经看到过很多次了,NSString类是OC应用中文本的基础工具类。除了提供面向对象的字符串外,它也提供了很多强大的方法去操作字符串内容。同时也支持本地的编码支持。
就像NSNumber和NSDecimalNumber,NSString 是不可变类型,所以你不能对他进行修改。在本章最后我们将讨论NSMutableString,这个类是可变字符串。
创建字符串
最最常用的创建方法就是使用@"Some String"语法操作,但是stringWithFormat:方法在提供格式化创建字符串方面很好用:
NSString *make = @"Porsche"; NSString *model = "; ; NSString *message = [NSString stringWithFormat:@"That's a %@ %@ from %d!", make, model, year]; NSLog(@"%@", message);
注意到我们在NSLog()方法中使用@”%@“格式化信息进行输出而不是直接NSLog(message)。这样做才是最佳实践,因为有可能在message中存在着%字符导致问题。想想如果
message = @"The tank is 50% full"
NSString提供了很多内置的编码,也就是说你能在字符串中直接使用UTF-8的字符。例如,你可以使用如下字符串如同其他字符串根本没有任何区别。
NSString *make = @"Côte d'Ivoire";
枚举字符串
NSString两个最主要的基础方法是length和characterAtIndex:方法,分别放回当前字符串的字符数和字符串中指定位置的字符,虽然可能很少使用到他们,但是还是需要了解一下比较好:
NSString *make = @"Porsche"; ; i<[make length]; i++) { unichar letter = [make characterAtIndex:i]; NSLog(@"%d: %hu", i, letter); }
字符串比较
字符串的比较很NSNumber的比较很相像。除了你需要比较指针是否相等外,你还需要使用isEqualToString:方法去做更加详细的内容比较。下面的例子展示了这个原理,在代码中使用了 hasPrefix:
和 hasSuffix:方法
NSString *car = @"Porsche Boxster"; if ([car isEqualToString:@"Porsche Boxster"]) { NSLog(@"That car is a Porsche Boxster"); } if ([car hasPrefix:@"Porsche"]) { NSLog(@"That car is a Porsche of some sort"); } if ([car hasSuffix:@"Carrera"]) { // This won't execute NSLog(@"That car is a Carrera"); }
就像NSNumber,NSString有一个compare:方法,他在让字符串进行字典排序的时候非常有用。
NSString *otherCar = @"Ferrari"; NSComparisonResult result = [car compare:otherCar]; if (result == NSOrderedAscending) { NSLog(@"The letter 'P' comes before 'F'"); } else if (result == NSOrderedSame) { NSLog(@"We're comparing the same string"); } else if (result == NSOrderedDescending) { NSLog(@"The letter 'P' comes after 'F'"); }
上述的方法是大小写敏感的,如果忽略大小写 则需要使用caseInsensitiveCompare:方法,
字符串组合
下面代码展示了两个方法去组合字符串。但是,记住由于NSString本身是不可变的,所以组合后将生成一个新的字符串,而原有字符串不会被改变。
NSString *make = @"Ferrari"; NSString *model = @"458 Spider"; NSString *car = [make stringByAppendingString:model]; NSLog(@"%@", car); // Ferrari458 Spider car = [make stringByAppendingFormat:@" %@", model]; NSLog(@"%@", car); // Ferrari 458 Spider (note the space)
搜索字符串
所有的NSString的搜索方法都将返回NSrange结构体,结构体中定义了location和length变量,location是搜索到的开始位置,length是搜索到的总字符数。如果没有搜索到,location值将为NSNotFound。例如下面的代码片段:
NSString *car = @"Maserati GranCabrio"; NSRange searchResult = [car rangeOfString:@"Cabrio"]; if (searchResult.location == NSNotFound) { NSLog(@"Search string was not found"); } else { NSLog(@"'Cabrio' starts at index %lu and is %lu characters long", searchResult.location, searchResult.length); }
分隔字符串
你可以指定位置的方式来分隔一个字符串,但是记住,由于NSString是不可变,所以分隔后返回的值是一个全新的字符串,远字符串不会被修改。
NSString *car = @"Maserati GranTurismo"; NSLog(]); // Maserati NSLog(]); // GranTurismo NSRange range = NSMakeRange(, ); NSLog(@"%@", [car substringWithRange:range]); // Gran
NSMakeRange()是一个全局方法,用于创建NSRange结构体变量。第一个参数是location值,而第二个是length值。substringWithRange:通过NSRange来切分字符串。
我们也可以将字符串通过componentsSeparatedByString:方法将其切割进数组中,如:
NSString *models = @"Porsche,Ferrari,Maserati"; NSArray *modelsAsArray = [models componentsSeparatedByString:@","]; NSLog(]); // Ferrari
替换字符串
替换字符串的部分内容和切割字符串很像,下面的代码展示了如何做:
NSString *elise = @"Lotus Elise"; NSRange range = NSMakeRange(, ); NSString *exige = [elise stringByReplacingCharactersInRange:range withString:@"Exige"]; NSLog(@"%@", exige); // Lotus Exige NSString *evora = [exige stringByReplacingOccurrencesOfString:@"Exige" withString:@"Evora"]; NSLog(@"%@", evora); // Lotus Evora
大小写转化
NSString类也提供了一些方便的方法去进行字符串的大小写转化处理。
NSString *car = @"lotUs beSpoKE"; NSLog(@"%@", [car lowercaseString]); // lotus bespoke NSLog(@"%@", [car uppercaseString]); // LOTUS BESPOKE NSLog(@"%@", [car capitalizedString]); // Lotus Bespoke
数字转换
NSString定义了几个字符串转换为基本类型的方法。但是如果你需要保证代码的健壮最好还是使用 NSScanner
或者NSNumberFormatter。
NSString *year = "; BOOL asBool = [year boolValue]; int asInt = [year intValue]; NSInteger asInteger = [year integerValue]; long long asLongLong = [year longLongValue]; float asFloat = [year floatValue]; double asDouble = [year doubleValue];
NSMutableString
NSMutableString是NSString的可变版本。不像不可变字符串,可变字符串可以修改原有字符串而不需要重新建立一个新的字符串。
NSMutableString继承自NSString,所以基本上在NSString中可以使用的方法你都可以在NSMutableString中使用。虽然 stringByAppendingString:方法依然返回NSString对象而不是NSMutableString对象。
接下来的小节中展示一些NSMutableString中特有的方法。从中你会发现两者在操作套路上的差别。不像NSString会从新创建新的对象,NSMutableString则直接在原有对象上进行操作。
创建可变字符串
可变字符串可以可以使用stringWithString:方法爱接受一个直接定义的字符串或者一个已经存在的NSString字符串变量来创建。
NSMutableString *car = [NSMutableString stringWithString:@"Porsche 911"];
对象创建完毕后你可以通过setString:方法爱重新给他赋值。
[car setString:@"Porsche Boxster"];
扩展可变字符串
NSMutableString和NSString的最主要区别就是前者直接在原有的内存中操作而后者会新建对象。
NSMutableString *car = [NSMutableString stringWithCapacity:]; NSString *model = @"458 Spider"; [car setString:@"Ferrari"]; [car appendString:model]; NSLog(@"%@", car); // Ferrari458 Spider [car setString:@"Ferrari"]; [car appendFormat:@" %@", model]; NSLog(@"%@", car); // Ferrari 458 Spider [car setString:@"Ferrari Spider"]; [car insertString:]; NSLog(@"%@", car); // Ferrari 458 Spider
替换/删除子字符串
通过replaceCharactersInRange:withString:和deleteCharactersInRange:方法可以达到此目的:
NSMutableString *car = [NSMutableString stringWithCapacity:]; [car setString:@"Lotus Elise"]; [car replaceCharactersInRange:NSMakeRange(, ) withString:@"Exige"]; NSLog(@"%@", car); // Lotus Exige [car deleteCharactersInRange:NSMakeRange(, )]; NSLog(@"%@", car); // Lotus
什么时候适合使用可变字符串呢?
既然NSString和NSMutableString提供的功能差不多,所以很难说用哪个好。一般来说,NSString的静态属性在大多数时候更加高效。但是如果要修改字符串值的话有需要去新创建对象。
下面展示两个例子来展示可变字符串的优势。第一个例子中展示不可变字符串:
// DO NOT DO THIS. EVER. NSString *indices = @""; ; i<; i++) { indices = [indices stringByAppendingFormat:@"%d", i]; }
记住stringByAppendingFormat:方法始终会创建一个NSString对象,上述过程大概需呀1.76MB。不必多说,这样的效率真的很低。
现在可变字符串的表现:
NSMutableString *indices = [NSMutableString stringWithCapacity:]; ; i<; i++) { [indices appendFormat:@"%d", i]; }
既然可变字符串没有新建对象,没有发生对象间的拷贝,这个过程大概只要19KB内存。
所以,一个好的规则就是,在一个逻辑中如果需要修改对象则使用可变字符串,除此之外全部应该使用不可变字符串,这点也适用于sets, arrays, and dictionaries.