一個實用的NSString分類工具 (一)—— 玩轉(zhuǎn)數(shù)字

版本記錄

版本號 時間
V1.0 2017.12.15

前言

NSString是我們經(jīng)常使用的一個類瓤漏,但是蘋果的API很多用起來不是那么方便,需要根據(jù)我們特殊需求進行個性化的改變和定制颊埃,接下來蔬充,我就寫一個NSString分類工具,以后在使用的時候直接調(diào)用這個分類中的方法竟秫,可以實現(xiàn)很多小的功能,用起來也很方便跷乐。相關(guān)代碼已經(jīng)上傳至GitHub - 刀客傳奇肥败。

計算字符串的占的寬度

很多時候,我們需要計算UILabel或者UIButton的寬度愕提,因為里面的文字可能是從服務(wù)器返回的馒稍,所以要求這個控件的寬度也是自適應(yīng)的,這就需要我們實時的計算返回的字符串占的寬度浅侨。

先看下面的代碼纽谒。

//根據(jù)字符串長度獲取字符串尺寸

- (CGSize)jj_textSizeWithFont:(UIFont *)font
            constrainedToSize:(CGSize)size;
//根據(jù)字符串長度獲取字符串尺寸

- (CGSize)jj_textSizeWithFont:(UIFont *)font
            constrainedToSize:(CGSize)size
{
    CGSize textSize;
    
    if (CGSizeEqualToSize(size, CGSizeZero)) {
        NSDictionary *attributes = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
        textSize = [self sizeWithAttributes:attributes];
        textSize = CGSizeMake(floor(size.width), floor(size.height));
    }
    else {
        NSStringDrawingOptions option = NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading;
        
        //NSStringDrawingTruncatesLastVisibleLine如果文本內(nèi)容超出指定的矩形限制,文本將被截去并在最后一個字符后加上省略號如输。 如果指定了NSStringDrawingUsesLineFragmentOrigin選項鼓黔,則該選項被忽略 NSStringDrawingUsesFontLeading計算行高時使用行間距。(譯者注:字體大小+行間距=行高)
        
        NSDictionary *attributes = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
        
        CGRect rect = [self boundingRectWithSize:size options:option attributes:attributes context:nil];
        textSize = rect.size;
        
        //注意:當(dāng)字符串同時存在@和&字符時不见,使用NSStringDrawingUsesLineFragmentOrigin時rect會變?yōu)榱?        if (CGSizeEqualToSize(textSize, CGSizeZero)) {
            option = NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesFontLeading;
            rect = [self boundingRectWithSize:size options:option attributes:attributes context:nil];
            textSize = rect.size;
        }
    }
    return textSize;
}

下面我們就調(diào)用一下澳化。

#import "ViewController.h"
#import "NSString+JJNSStringExt.h"

@interface ViewController ()

@end

@implementation ViewController

#pragma mark - Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor lightGrayColor];
    
    NSString *str = @"我們是一家人";
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [self.view addSubview:button];
    [button setTitle:str forState:UIControlStateNormal];
    button.titleLabel.font = [UIFont systemFontOfSize:17.0];
    button.backgroundColor = [UIColor blueColor];
    CGSize size = [str jj_textSizeWithFont:button.titleLabel.font constrainedToSize:CGSizeMake(MAXFLOAT, 22.0)];
    button.frame = CGRectMake(100.0, 150.0, size.width + 20.0, 30.0);
    NSLog(@"button = %@", button);
}

@end

下面看一下輸出結(jié)果

2017-12-15 23:46:56.149169+0800 JJNSStringTool[1259:19762] button = <UIButton: 0x7ffa9fc07ee0; frame = (100 150; 123.938 30); opaque = NO; layer = <CALayer: 0x604000222340>>

下面看一下效果圖


判斷是否是手機號

先看分類方法

//是否是手機號的判定

- (BOOL)jj_isPhoneNumberWithStr:(NSString *)str;
/*
 是否是手機號的判定
 
 移動:139 138 137 136 135 134 147 188 187 184 183 182 178 159 158 157 152 151 150 1703 1705 1706 198
 聯(lián)通:186 185 176 145 156 155 132 131 130 175 176 1704 1707 1708 1709 171 166
 電信:189 181 180 177 153 133 173 1700 1701 1702 199
 */

- (BOOL)jj_isPhoneNumberWithStr:(NSString *)str
{
    str = [str stringByReplacingOccurrencesOfString:@" " withString:@""];
    if (str.length != 11) {
        return NO;
    }
    else {
        
        //移動
        NSString *CM_NUM = @"^((13[4-9])|(147)|(15[0-2,7-9])|(178)|(18[2-4,7-8])|(198))\\d{8}|(170[3,5,6])\\d{7}$";
        //聯(lián)通
        NSString *CU_NUM = @"^((13[0-2])|(145)|(15[5-6])|(17[5,6])|(18[5,6])|(166))\\d{8}|(170[4,7-9])\\d{7}|171[0-9]\\d{7}$";
        //電信
        NSString *CT_NUM = @"^((133)|(153)|(17[3,7])|(18[0,1,9])|(199))\\d{8}|(170[0-2])\\d{7}$";
        
        NSPredicate *pred1 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CM_NUM];
        BOOL isMatch1 = [pred1 evaluateWithObject:str];
        NSPredicate *pred2 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CU_NUM];
        BOOL isMatch2 = [pred2 evaluateWithObject:str];
        NSPredicate *pred3 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CT_NUM];
        BOOL isMatch3 = [pred3 evaluateWithObject:str];
        if (isMatch1 || isMatch2 || isMatch3) {
            return YES;
        }
        else {
            return NO;
        }
    }
}

下面看調(diào)用過程

    NSString *str = @"18613546782";
    BOOL result = [str jj_isPhoneNumberWithStr:str];
    NSLog(@"result = %d", result);
    
    NSString *str1 = @"11111111111";
    BOOL result1 = [str1 jj_isPhoneNumberWithStr:str1];
    NSLog(@"result1 = %d", result1);

下面看輸出結(jié)果

2017-12-16 00:21:15.543055+0800 JJNSStringTool[1675:35852] result = 1
2017-12-16 00:21:15.543518+0800 JJNSStringTool[1675:35852] result1 = 0

可見,可以實現(xiàn)對手機號碼的判定稳吮。


身份證號碼的驗證

還是直接看代碼

//身份證號碼驗證

- (BOOL)jj_isCardIdValid;
//身份證號碼驗證

- (BOOL)jj_isCardIdValid
{
    NSString * cardId = self;
    cardId = [cardId stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    NSUInteger length =0;
    if (!cardId) {
        return NO;
    }
    else {
        length = cardId.length;
        
        if (length !=15 && length !=18) {
            return NO;
        }
    }
    // 省份代碼
    NSArray *areasArray =@[@"11",@"12", @"13",@"14", @"15",@"21", @"22",@"23", @"31",@"32", @"33",@"34", @"35",@"36", @"37",@"41", @"42",@"43", @"44",@"45", @"46",@"50", @"51",@"52", @"53",@"54", @"61",@"62", @"63",@"64", @"65",@"71", @"81",@"82", @"91"];
    
    NSString *valueStart2 = [cardId substringToIndex:2];
    BOOL areaFlag =NO;
    for (NSString *areaCode in areasArray) {
        if ([areaCode isEqualToString:valueStart2]) {
            areaFlag =YES;
            break;
        }
    }
    
    if (!areaFlag) {
        return false;
    }
    
    
    NSRegularExpression *regularExpression;
    NSUInteger numberofMatch;
    
    int year =0;
    switch (length) {
        case 15:
            year = [cardId substringWithRange:NSMakeRange(6,2)].intValue +1900;
            
            if (year %4 ==0 || (year %100 ==0 && year %4 ==0)) {
                
                regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$"
                                                                        options:NSRegularExpressionCaseInsensitive
                                                                          error:nil];//測試出生日期的合法性
            }
            else {
                regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$"
                                                                        options:NSRegularExpressionCaseInsensitive
                                                                          error:nil];//測試出生日期的合法性
            }
            numberofMatch = [regularExpression numberOfMatchesInString:cardId
                                                               options:NSMatchingReportProgress
                                                                 range:NSMakeRange(0, cardId.length)];
            
            
            if(numberofMatch >0) {
                return YES;
            }
            else {
                return NO;
            }
        case 18:
            
            year = [cardId substringWithRange:NSMakeRange(6,4)].intValue;
            if (year %4 ==0 || (year %100 ==0 && year %4 ==0)) {
                
                regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$"
                                                                        options:NSRegularExpressionCaseInsensitive
                                                                          error:nil];//測試出生日期的合法性
            }
            else {
                regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$"
                                                                        options:NSRegularExpressionCaseInsensitive
                                                                          error:nil];//測試出生日期的合法性
            }
            numberofMatch = [regularExpression numberOfMatchesInString:cardId
                                                               options:NSMatchingReportProgress
                                                                 range:NSMakeRange(0, cardId.length)];
            
            
            if(numberofMatch >0) {
                int S = ([cardId substringWithRange:NSMakeRange(0,1)].intValue + [cardId substringWithRange:NSMakeRange(10,1)].intValue) *7 +
                ([cardId substringWithRange:NSMakeRange(1,1)].intValue + [cardId substringWithRange:NSMakeRange(11,1)].intValue) *9 +
                ([cardId substringWithRange:NSMakeRange(2,1)].intValue + [cardId substringWithRange:NSMakeRange(12,1)].intValue) *10 +
                ([cardId substringWithRange:NSMakeRange(3,1)].intValue + [cardId substringWithRange:NSMakeRange(13,1)].intValue) *5 +
                ([cardId substringWithRange:NSMakeRange(4,1)].intValue + [cardId substringWithRange:NSMakeRange(14,1)].intValue) *8 +
                ([cardId substringWithRange:NSMakeRange(5,1)].intValue + [cardId substringWithRange:NSMakeRange(15,1)].intValue) *4 +
                ([cardId substringWithRange:NSMakeRange(6,1)].intValue + [cardId substringWithRange:NSMakeRange(16,1)].intValue) *2 +
                [cardId substringWithRange:NSMakeRange(7,1)].intValue *1 + [cardId substringWithRange:NSMakeRange(8,1)].intValue *6 +
                [cardId substringWithRange:NSMakeRange(9,1)].intValue *3;
                int Y = S %11;
                NSString *M =@"F";
                NSString *JYM =@"10X98765432";
                M = [JYM substringWithRange:NSMakeRange(Y,1)];// 判斷校驗位
                if ([M isEqualToString:[cardId substringWithRange:NSMakeRange(17,1)]]) {
                    return YES;// 檢測ID的校驗位
                }
                else {
                    return NO;
                }
            }
            else {
                return NO;
            }
        default:
            return NO;
    }
    return NO;
}

下面我們就看一下調(diào)用過程

    NSString *str1 = @"990606198808183611";
    BOOL result1 = [str1 jj_isCardIdValid];
    NSLog(@"result1 = %d", result1);

下面看輸出結(jié)果

2017-12-16 00:39:31.180822+0800 JJNSStringTool[2099:49567] result1 = 0

正確的身份證號碼我就不去驗證了缎谷,大家可以自行去驗證。


判斷是否是整數(shù)

還是直接看代碼

// 判斷是否是整數(shù)

- (BOOL)jj_isIntNumber;
// 判斷是否是整數(shù)

- (BOOL)jj_isIntNumber
{
    NSString *regex = @"^-?[0-9]\\d*$";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
    return [predicate evaluateWithObject:self];
}

這里就不給大家驗證了灶似,大家感興趣的可以自行驗證列林。


判斷是否是小數(shù)

還是直接看代碼

//判斷是否是小數(shù)

- (BOOL)jj_isFloatNumber;
//判斷是否是小數(shù)

- (BOOL)jj_isFloatNumber
{
    NSString *regex = @"^-?([1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*|0?\\.0+|0)$";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
    return [predicate evaluateWithObject:self];
}

這里就帶著大家一起驗證下。

//是否是小數(shù)

- (void)isFloatNumber
{
    NSString *str = @"12.13";
    BOOL result = [str jj_isFloatNumber];
    NSLog(@"result = %d", result);
    
    NSString *str1 = @"999";
    BOOL result1 = [str1 jj_isFloatNumber];
    NSLog(@"result1 = %d", result1);
}

看輸出結(jié)果

2017-12-16 00:51:41.022796+0800 JJNSStringTool[2221:55765] result = 1
2017-12-16 00:51:41.023191+0800 JJNSStringTool[2221:55765] result1 = 0

可以酪惭,看見可以很好的識別是否是小數(shù)希痴。

后記

未完,待續(xù)~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末春感,一起剝皮案震驚了整個濱河市润梯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖纺铭,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寇钉,死亡現(xiàn)場離奇詭異,居然都是意外死亡舶赔,警方通過查閱死者的電腦和手機扫倡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來竟纳,“玉大人撵溃,你說我怎么就攤上這事∽独郏” “怎么了缘挑?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長桶略。 經(jīng)常有香客問我语淘,道長,這世上最難降的妖魔是什么际歼? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任惶翻,我火速辦了婚禮,結(jié)果婚禮上鹅心,老公的妹妹穿的比我還像新娘吕粗。我一直安慰自己,他們只是感情好旭愧,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布颅筋。 她就那樣靜靜地躺著,像睡著了一般输枯。 火紅的嫁衣襯著肌膚如雪垃沦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天用押,我揣著相機與錄音肢簿,去河邊找鬼。 笑死蜻拨,一個胖子當(dāng)著我的面吹牛池充,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播缎讼,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼收夸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了血崭?” 一聲冷哼從身側(cè)響起卧惜,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤厘灼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后咽瓷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體设凹,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年茅姜,在試婚紗的時候發(fā)現(xiàn)自己被綠了闪朱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡钻洒,死狀恐怖奋姿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情素标,我是刑警寧澤称诗,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站头遭,受9級特大地震影響寓免,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜任岸,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一再榄、第九天 我趴在偏房一處隱蔽的房頂上張望狡刘。 院中可真熱鬧享潜,春花似錦、人聲如沸嗅蔬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽澜术。三九已至艺蝴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鸟废,已是汗流浹背猜敢。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留盒延,地道東北人缩擂。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像添寺,于是被迫代替她去往敵國和親胯盯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容