
NSScanner官方文檔
NSScanner類(lèi)是一個(gè)類(lèi)簇的抽象父類(lèi),該類(lèi)簇為一個(gè)從NSString對(duì)象掃描值的對(duì)象提供了程序接口。
NSScanner對(duì)象把NSString 對(duì)象的的字符解釋和轉(zhuǎn)化成 number和string 類(lèi)型的值缴啡。在創(chuàng)建NSScanner對(duì)象的時(shí)候?yàn)樗峙渥址?string )优构,當(dāng)你從NSScanner對(duì)象獲取內(nèi)容的時(shí)候,它會(huì)從頭到尾遍歷字符串(string)界牡。
由于類(lèi)簇的屬性簿寂, scanner對(duì)象并不是 NSScanner類(lèi)的實(shí)例,而是它一個(gè)私有子類(lèi)的實(shí)例宿亡。盡管scanner對(duì)象的類(lèi)是私有的陶耍,但是它的接口是公開(kāi)的(抽象父類(lèi)已經(jīng)聲明)。 NSScanner 的原始方法是string和Configuring a Scanner方法下面列舉的所有的方法她混。
在 NSScanner 對(duì)象掃描字符串的時(shí)候烈钞,你可以通過(guò)設(shè)置屬性charactersToBeSkipped
忽略某些字符。在掃描字符串之前坤按,那些位于忽略字符集
中的字符將會(huì)被跳過(guò)毯欣。默認(rèn)的忽略字符是空格
和回車(chē)
字符。
可以通過(guò)[[scanner string] substringFromIndex:[scanner scanLocation]]
獲取未掃描的字符串臭脓。
創(chuàng)建 Scanner對(duì)象
+ (instancetype)scannerWithString:(NSString *)aString
+ (id)localizedScannerWithString:(NSString *)aString
- (instancetype)initWithString:(NSString *)aString
- scannerWithString酗钞,返回值是 掃描過(guò)aString字符串的NSScanner 對(duì)象,該方法通過(guò)調(diào)用initWithString設(shè)置掃描字符串;
- localizedScannerWithString,返回值是 通過(guò)用戶(hù)默認(rèn)的 locale方式掃描字符串的NSScanner 對(duì)象来累,該方法也是通過(guò)調(diào)用initWithString設(shè)置掃描字符串;
- initWithString砚作,返回值是NSScanner 對(duì)象,該對(duì)象通過(guò)掃描aString完成初始化
獲取Scanner的字符串
@property(readonly, copy) NSString *string
配置Scanner
@property NSUInteger scanLocation
@property BOOL caseSensitive
@property(copy) NSCharacterSet *charactersToBeSkipped
@property(retain) id locale
- scanLocation,下次掃描開(kāi)始的位置嘹锁,如果該值超出了string的區(qū)域葫录,將會(huì)引起
NSRangeException
,該屬性在發(fā)生錯(cuò)誤后重新掃描時(shí)非常有用。 - caseSensitive领猾,是否區(qū)分字符串中大小寫(xiě)的標(biāo)志米同。默認(rèn)為NO,注意:該設(shè)置不會(huì)應(yīng)用到
被跳過(guò)的字符集
摔竿。 - charactersToBeSkipped,在掃描時(shí)
被跳過(guò)的字符集
面粮,默認(rèn)是空白格和回車(chē)鍵。被跳過(guò)的字符集
優(yōu)先于掃描的字符集:例如一個(gè)scanner被跳過(guò)的字符集
為空格继低,通過(guò)scanInt:去查找字符串中的整型數(shù)時(shí)熬苍,首先做的不是掃描,而是跳過(guò)空格袁翁,直到找到十進(jìn)制數(shù)據(jù)或者其他的字符柴底。在字符被掃描的時(shí)候钱磅,跳過(guò)功能就失效了。如果你掃描的字符和跳過(guò)的字符是一樣的似枕,結(jié)果將是未知的盖淡。被跳過(guò)的字符是一個(gè)唯一值,scanner不會(huì)將忽略大小寫(xiě)的功能應(yīng)用于它凿歼,也不會(huì)用這些字符做一些組合褪迟,如果在掃描字符換的時(shí)候你想忽略全部的元音字符,就要這么做(比如:將字符集設(shè)置成“AEIOUaeiou”}; - locale,scanner 的locale對(duì)它從字符串中區(qū)分?jǐn)?shù)值產(chǎn)生影響答憔,它通過(guò)locale的十進(jìn)制分隔符區(qū)分浮點(diǎn)型數(shù)據(jù)的整數(shù)和小數(shù)部分味赃。一個(gè)沒(méi)有l(wèi)ocale的scanner用非定域值。新的scanner若沒(méi)有設(shè)置locale虐拓,使用默認(rèn)locale心俗。
掃描字符串
- (BOOL)scanCharactersFromSet:(NSCharacterSet *)scanSet intoString:(NSString * _Nullable *)stringValue;
- (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)stopSet intoString:(NSString * _Nullable *)stringValue;
- (BOOL)scanString:(NSString *)string intoString:(NSString * _Nullable *)stringValue;
- (BOOL)scanUpToString:(NSString *)stopString intoString:(NSString * _Nullable *)stringValue;
- (BOOL)scanDecimal:(NSDecimal *)decimalValue;
- (BOOL)scanDouble:(double *)doubleValue;
- (BOOL)scanFloat:(float *)floatValue;
- (BOOL)scanHexDouble:(double *)result;
- (BOOL)scanHexFloat:(float *)result;
- (BOOL)scanHexInt:(unsigned int *)intValue;
- (BOOL)scanHexLongLong:(unsigned long long *)result;
- (BOOL)scanInt:(int *)intValue;
- (BOOL)scanInteger:(NSInteger *)value;
- (BOOL)scanUnsignedLongLong:(unsigned long long *)unsignedLongLongValue;
@property(getter=isAtEnd, readonly) BOOL atEnd;
scanCharactersFromSet:intoString:掃描字符串中和NSCharacterSet字符集中匹配的字符,是按字符單個(gè)匹配的蓉驹,例如城榛,NSCharacterSet字符集為@"test123Dmo",scanner字符串為 @" 123test12Demotest"态兴,那么字符串中所有的字符都在字符集中狠持,所以指針指向的地址存儲(chǔ)的內(nèi)容為"123test12Demotest"
scanUpToCharactersFromSet:intoString:掃描字符串直到遇到NSCharacterSet字符集的字符時(shí)停止,指針指向的地址存儲(chǔ)的內(nèi)容為遇到
跳過(guò)字符集
字符之前的內(nèi)容scanString:intoString:從當(dāng)前的掃描位置開(kāi)始掃描瞻润,判斷
掃描字符串
是否從當(dāng)前位置能掃描到和傳入字符串相同的一串字符喘垂,如果能掃描到就返回YES,指針指向的地址存儲(chǔ)的就是這段字符串的內(nèi)容。例如scanner的string內(nèi)容為123abc678
,傳入的字符串內(nèi)容為abc
绍撞,如果當(dāng)前的掃描位置為0正勒,那么掃描不到,但是如果將掃描位置設(shè)置成3傻铣,就可以?huà)呙璧搅恕?/p>scanUpToString:intoString:從當(dāng)前的掃描位置開(kāi)始掃描章贞,掃描到和傳入的字符串相同字符串時(shí),停止矾柜,指針指向的地址存儲(chǔ)的是遇到傳入字符串之前的內(nèi)容阱驾。例如scanner的string內(nèi)容為
123abc678
,傳入的字符串內(nèi)容為abc
,存儲(chǔ)的內(nèi)容為123
scanDecimal:掃描NSDecimal類(lèi)型的值怪蔑,有關(guān)NSDecimal類(lèi)型的值更多的信息可以查看
NSDecimalNumberscanDouble :掃描雙精度浮點(diǎn)型字符,溢出和非溢出都被認(rèn)為合法的浮點(diǎn)型數(shù)據(jù)丧荐。在溢出的情況下scanner將會(huì)跳過(guò)所有的數(shù)字缆瓣,所以新的掃描位置將會(huì)在整個(gè)浮點(diǎn)型數(shù)據(jù)的后面。double指針指向的地址存儲(chǔ)的數(shù)據(jù)為掃描出的值虹统,包括溢出時(shí)的
HUGE_VAL
或者–HUGE_VAL
弓坞,即未溢出時(shí)的0.0
隧甚。scanFloat:掃描單精度浮點(diǎn)型字符,具體內(nèi)容同
scanDouble
scanHexDouble: 掃描雙精度的十六進(jìn)制類(lèi)型渡冻,溢出和非溢出都被認(rèn)為合法的浮點(diǎn)型數(shù)據(jù)戚扳。在溢出的情況下scanner將會(huì)跳過(guò)所有的數(shù)字,所以新的掃描位置將會(huì)在整個(gè)浮點(diǎn)型數(shù)據(jù)的后面族吻。double指針指向的地址存儲(chǔ)的數(shù)據(jù)為掃描出的值帽借,包括溢出時(shí)的
HUGE_VAL
或者–HUGE_VAL
,即未溢出時(shí)的0.0
超歌。數(shù)據(jù)接收時(shí)對(duì)應(yīng)的格式為 %a 或%A 砍艾,雙精度十六進(jìn)制字符前面一定要加0x
或者0X
。scanHexInt 掃描十六進(jìn)制無(wú)符整型巍举,unsigned int指針指向的地址值為 掃描到的值脆荷,包含溢出時(shí)的UINT_MAX。
scanHexLongLong 同
scanHexDouble
scanInt 掃描整型懊悯,溢出也被認(rèn)為是有效的整型蜓谋,int 指針指向的地址的值為掃描到的值,包含溢出時(shí)的
INT_MAX
或INT_MIN
炭分。scanInteger 同
scanInt
scanLongLong 掃描LongLong 型孤澎,溢出也被認(rèn)為是有效的整型,LongLong指針指向的地址的值為掃描到的值欠窒,包含溢出時(shí)的
LLONG_MAX
或LLONG_MIN
覆旭。
實(shí)例:
#import <Foundation/Foundation.h>
@interface ConditionJudgmentController : NSObject
//輸入框中只能輸入數(shù)字和小數(shù)點(diǎn),且小數(shù)點(diǎn)只能輸入一位岖妄,參數(shù)number 可以設(shè)置小數(shù)的位數(shù)型将,該函數(shù)在-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string調(diào)用;
+(BOOL)isValidAboutInputText:(UITextField *)textfield shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string decimalNumber: (NSInteger) number;
@end
#import "ConditionJudgmentController.h"
@implementation ConditionJudgmentController
+(BOOL)isValidAboutInputText:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string decimalNumber:(NSInteger)number{
NSScanner *scanner = [NSScanner scannerWithString:string];
NSCharacterSet *numbers;
NSRange pointRange = [textField.text rangeOfString:@"."];
if ( (pointRange.length > 0) && (pointRange.location < range.location || pointRange.location > range.location + range.length) ){
numbers = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
}else{
numbers = [NSCharacterSet characterSetWithCharactersInString:@"0123456789."];
}
if ( [textField.text isEqualToString:@""] && [string isEqualToString:@"."] ){
return NO;
}
short remain = number; //保留 number位小數(shù)
NSString *tempStr = [textField.text stringByAppendingString:string];
NSUInteger strlen = [tempStr length];
if(pointRange.length > 0 && pointRange.location > 0){ //判斷輸入框內(nèi)是否含有“.”荐虐。
if([string isEqualToString:@"."]){ //當(dāng)輸入框內(nèi)已經(jīng)含有“.”時(shí)七兜,如果再輸入“.”則被視為無(wú)效。
return NO;
}
if(strlen > 0 && (strlen - pointRange.location) > remain+1){ //當(dāng)輸入框內(nèi)已經(jīng)含有“.”福扬,當(dāng)字符串長(zhǎng)度減去小數(shù)點(diǎn)前面的字符串長(zhǎng)度大于需要要保留的小數(shù)點(diǎn)位數(shù)腕铸,則視當(dāng)次輸入無(wú)效。
return NO;
}
}
NSRange zeroRange = [textField.text rangeOfString:@"0"];
if(zeroRange.length == 1 && zeroRange.location == 0){ //判斷輸入框第一個(gè)字符是否為“0”
if(![string isEqualToString:@"0"] && ![string isEqualToString:@"."] && [textField.text length] == 1){ //當(dāng)輸入框只有一個(gè)字符并且字符為“0”時(shí)铛碑,再輸入不為“0”或者“.”的字符時(shí)狠裹,則將此輸入替換輸入框的這唯一字符。
textField.text = string;
return NO;
}else{
if(pointRange.length == 0 && pointRange.location > 0){ //當(dāng)輸入框第一個(gè)字符為“0”時(shí)汽烦,并且沒(méi)有“.”字符時(shí)涛菠,如果當(dāng)此輸入的字符為“0”,則視當(dāng)此輸入無(wú)效。
if([string isEqualToString:@"0"]){
return NO;
}
}
}
}
NSString *buffer;
if ( ![scanner scanCharactersFromSet:numbers intoString:&buffer] && ([string length] != 0) ){
return NO;
}else{
return YES;
}
}
@end
注意:上面的方法要結(jié)合UITextField的代理方法使用
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
return [ConditionJudgmentController isValidAboutInputText:textField shouldChangeCharactersInRange:range replacementString:string decimalNumber:3];
}
結(jié)束語(yǔ):
平時(shí)讀者在進(jìn)行條件判斷時(shí)俗冻,可能使用正則表達(dá)式或者用if語(yǔ)句比較多一點(diǎn)礁叔,其實(shí)NSScanner類(lèi)為我們提供了一個(gè)非常好的方式進(jìn)行判斷。把它們結(jié)合起來(lái)使用迄薄,可以獲得更好的效果琅关。