String Programming Guide 2

String Format Specifiers

Format Specifiers

IEEE printf specification:

屏幕快照 2015-06-10 上午10.28.02.png

PlatForm Dependencies

屏幕快照 2015-06-10 上午10.32.20.png

直接用 ld 代替 d, 但是要区分 float(f) 和 double(lf)


Reading Strings From and Writing Strings To Files and URLS

Reading From Files and URLs

1.知道编码方式的时候:

//这个例子写不出来,以后再回来填坑,,,如果我还记得的话
NSURL *URL = ...;
NSError *error;
NSString *stringFromFileAtURL = [[NSString alloc]initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:&error];
if (stringFromFileAtURL == nil){
    //an error occurred
    NSLog(@"Error reading file at %@\n%@", URL, [error localizedFailureReason]);
    //implementation continues...

也可以通过 NSData 来读入字符串,然而也要指定编码方式:

NSURL *URL = ...;
NSData *data = [NSData dataWithContentsOfURL: URL];
//假设编码是 UTF8
NSString *string = [NSString stringWithUTF8String:[data bytes]];
//如果编码是ISO-8859-1
NSString *string = [[NSString alloc] initWithData data encoding: NSISOLatin1StringEncoding];


2.不知道编码方式的时候:

a. 尝试使用 stringWithContentsOfFile:usedEncoding:error: 或者 initWithContentsOfFile:usedingEncoding:error:(还有其他基于 URL 的方法也可以)

b.如果 a 不行的话,尝试 UTF-8

c.如果 b 也不行的话,调查下数据源看看哪些比较有可能. 如 windows/ISO 的 Latin 1

d.尝试使用NSAttributedString的加载方法(如initWithURL:options:documentAttributes:error:)


Writing to Files and URLs

使用writeToFile:atomically:encoding:error:或者writeToURL:atomically:encoding:error:方法

这里又是一个我暂时没有办法自己写的坑

NSURL *URL = ...;
NSString *string = ...;
NSError *error;
BOOL ok = [string writeToURL:URL atomically:YES encoding:NSUnicodeStringEncoding error:&error];
if (!ok) {
    //an error occurred
    NSLog(@"Error writing file at %@\n%@", path, [error localozedFailureReason]);
    //implementation continues ...

小结

SourceCreation MethodExtraction Method
URL contens

stringWithContentsOfURL:encoding:error:

stringWithContentsOfURL:usedEncoding:error:

writeToURL:atomically:encoding:error:
File contents

stringWithContentsOfFile:encoding:error

stringWithContentsOfFile:usedEncoding:error:

writeToFile:atomically:encoding:error:


Searching, Comparing, and Sorting Strings

Search and Comparison Methods

1433931316794033.png

Searching strings

rangeOfString:...方法传入 NSString 作为搜索参数

rangeOfCharacterFromSet:... 方法传入一个字符串集合作为搜索参数. 

都是返回找到的第一个位置的 NSRange 没有找到则返回{NSNotFound, 0}


如果只是想知道是否包含某字符串, 可以直接这样用:(坑)

BOOL match = [myPredicate evaluateWithObject: aString];

Comparing and sorting strings

compare:...方法返回比较对象的大小排序关系

compare:options:range:

compare:options:

compare:options:range:locale:

options参数可以传入很多已经定好了的搜索规则可以直接使用

注意:对于直接呈现给用户看的排序结果, 一定要填写 locale 选项. 直接使用 localizedCompare: 或 localizedCaseInsensitiveCompare:也可以

如果需要像 Finder 一样排序的话,需要使用 compare:options:range:locale:,其中 options 参数传入:NSCaseInsensitiveCompare, NSNumberSearch, NSWidthInsensitiveSearch, NSForcedOrderingSearch(后面一点有例子)

Search and Comparison Options

屏幕快照 2015-06-10 下午7.17.53.png

Examples

Case-Insensitive Search for Prefix and suffix:

NSString中的 hasPreFix:和hasSuffix:方法可以用来搜索前缀后缀:

NSString *searchString = @"age";
NSString *beginsTest = @"Agencies";
NSRange prefixRange = [beginsTest rangeOfString:searchString options:(NSAnchoredSearch|NSCaseInsensitiveSearch)];
NSLog(@"{%lu,%lu}",prefixRange.location,prefixRange.length);
//OUTPUT: 2015-06-10 19:28:24.674 XYZPersonTest[1049:94971] {0,3}
NSString *endsTest = @"BRICOLAGE";
NSRange suffixRange = [endsTest rangeOfString:searchString options:(NSCaseInsensitiveSearch|NSAnchoredSearch|NSBackwardsSearch)];
NSLog(@"{%lu,%lu}",suffixRange.location,suffixRange.length);
//OUTPUT: 2015-06-10 19:30:10.596 XYZPersonTest[1058:95376] {6,3}

Comparing Strings:

基本形式

NSString *string1 = @"string1";
NSString *string2 = @"string2";
NSComparisonResult result;
result = [string1 compare:string2];
NSLog(@"%ld",result);
//OUTPUT: 2015-06-10 19:35:11.491 XYZPersonTest[1074:96680] -1(NSOrderedAscending)

加上 NSNumericSearch option(把数字组合起来再做数值上大小的比较)

NSString *string10 = @"string10";
NSString *string2 = @"string2";
NSComparisonResult result;
result = [string10 compare:string2];
NSLog(@"%lu",result);
//OUTPUT: 2015-06-10 19:40:59.793 XYZPersonTest[1114:98253] 18446744073709551615(什么鬼!本来应该是-1 NSOrderedAscending才对的)
result = [string10 compare:string2 options:NSNumericSearch];
NSLog(@"%lu",result);
//OUTPUT: 2015-06-10 19:40:59.794 XYZPersonTest[1114:98253] 1(NSOrderedDescending)
result = [string10 compare:string10];
NSLog(@"%lu",result);
//OUTPUT: 2015-06-10 19:40:59.794 XYZPersonTest[1114:98253] 1(NSOrderedSame)

你也可以直接使用caseInsensitiveCompare:和localizedCaseInsensitiveCompare:来实现不区分字母大小的比较

NSString *string_a = @"Arvdvard";
NSString *string_A = @"ARVDVARD";
NSComparisonResult result;
result = [string_a compare:string_A];
NSLog(@"%lu",result);
//OUTPUT:2015-06-10 19:48:30.923 XYZPersonTest[1139:100733] 1(NSOrderedDescending)
result = [string_a caseInsensitiveCompare:string_A];
NSLog(@"%lu",result);
//OUTPUT:2015-06-10 19:48:30.924 XYZPersonTest[1139:100733] 0(NSOrderedSame)
//same to result = [string_a compare: string_A options:NSCaseInsensitiveSearch];

Sorting strings like Finder

OS X v10.6及以后的版本里面, Finder 使用 localizedStandardCompare: 方法来实现文件排序.

int finderSortWithLocale(id string1, id string2, void *locale){
    static NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch|NSNumericSearch|NSWidthInsensitiveSearch|NSForcedOrderingSearch;
    
    NSRange string1Range = NSMakeRange(0, [string1 length]);
    
    return [string1 compare:string2 options:comparisonOptions range:string1Range locale:(NSLocale *)locale];
}

使用sortedArrayUsingFunction:context:方法调用上面比较函数

NSArray *stringArray = @[@"string 1",@"String 21",@"string 12",@"string 11", @"String 02"];
NSArray *sortedArray = [stringArray sortedArrayUsingFunction:finderSortedWithLocale context:[NSLocale currentLocale]];
//sortedArray:{"string 1", "String 02", "String 11", "string 12", "String 21"}


Words, Paragraphs, and Line Breaks

Word Boundaries

分词可以参考Unicode Standard Annex #29

苹果还自己加了一些本地化语言扩展

然而我们并不能修改这些规则

cocoa 框架里面中有一些函数会用到这些规则,如:NSAttributedString中doubleClickAtIndex:和nextWordFromIndex:forward:

 (都没有用过,猜测是只双击自动选中光标附近的某些词)

Line and Paragraph Separator Characters

Cocoa框架定义了换行和分段符


constunicode
换行符NSLineSeparatorCharacterU+2028
分段符NSParagraphSeparatorCharacterU+2029

一些系统识别换行分段符号的字符(应该):

POSIX-level:\n

旧macintosh 软件:\r

windows:\r\n

Cocoa 框架把上面的符号都当成是分段符NSParagraphSeparatorCharacter,例如方法insertNewline会插入\n(cocoa 默认就插\n)

而分行符NSLineSeparatorCharacter只有在特定的环境中才会有意义?例如 html<br>

Separating a String "by Paragraph"

如果确定平台的分行符\分段符

可以直接使用

NSString *myString = @"123\n456\n789\n10";
NSArray *arr = [myString componentsSeparatedByString:@"\n"];
NSLog(@"%@",arr);
/*
 OUTPUT:
 2015-06-10 20:33:27.104 XYZPersonTest[1174:109738] (
 123,
 456,
 789,
 10
 )
 */

为了适应多种系统使用不同的分行\分段符,可以这样干:

NSString *myString = @"123\n456\n789\n10\r11\r\n12";
unsigned length = [myString length];
unsigned paraStart = 0, paraEnd = 0, contentsEnd = 0;
NSMutableArray *array = [NSMutableArray array];
NSRange currentRange;
while (paraEnd < length) {
    [myString getParagraphStart:&paraStart end:&paraEnd contentsEnd:&contentsEnd forRange:NSMakeRange(paraEnd, 0)];
    currentRange = NSMakeRange(paraStart, contentsEnd-paraStart);
    [array addObject:[myString substringWithRange:currentRange]];
}
NSLog(@"%@",array);


Characters and Grapheme Clusters

NSString 内部使用的时 UTF-16编码

然后有些语言的字符需要使用两个 UTF-16组合才能表示,不过这个 NSString 会自己解决

在这种情况下需要对这些 string 对象操作,需要使用:

rangeOfComposedCharacterSequencesForRange:

rangeOfComposedCharacterSequenceAtIndex:

等方法来操作

尽量使用 NSString 自带的方法来处理字符串, 他们会很大程度上帮我们处理好这些组合字符:

lowercaseString

uppercaseString

capitalizedString

rangeOfString

rangeOfCharacterFromSet


如果cocoa 框架没有办法满♂足需求,可以参考 Unicode Standard Annex #29 寻找解决方法?


在 OS X v10.5及之后的系统, NSLayoutManager API 允许在文本内容任何地方插入字符,包括上述的组合字符串

参考:Cocoa Text Architecture Guide

标签:ios, object-c, nsstring