版本记录
版本号 | 时间 |
---|---|
V1.0 | 2017.12.15 |
前言
NSString是我们经常使用的一个类,但是苹果的API很多用起来不是那么方便,需要根据我们特殊需求进行个性化的改变和定制,接下来,我就写一个NSString分类工具,以后在使用的时候直接调用这个分类中的方法,可以实现很多小的功能,用起来也很方便。相关代码已经上传至GitHub - 刀客传奇。
计算字符串的占的宽度
很多时候,我们需要计算UILabel
或者UIButton
的宽度,因为里面的文字可能是从服务器返回的,所以要求这个控件的宽度也是自适应的,这就需要我们实时的计算返回的字符串占的宽度。
先看下面的代码。
//根据字符串长度获取字符串尺寸
- (CGSize)jj_textSizeWithFont:(UIFont *)font
constrainedToSize:(CGSize)size;
//根据字符串长度获取字符串尺寸
- (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如果文本内容超出指定的矩形限制,文本将被截去并在最后一个字符后加上省略号。 如果指定了NSStringDrawingUsesLineFragmentOrigin选项,则该选项被忽略 NSStringDrawingUsesFontLeading计算行高时使用行间距。(译者注:字体大小+行间距=行高)
NSDictionary *attributes = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
CGRect rect = [self boundingRectWithSize:size options:option attributes:attributes context:nil];
textSize = rect.size;
//注意:当字符串同时存在@和&字符时,使用NSStringDrawingUsesLineFragmentOrigin时rect会变为零
if (CGSizeEqualToSize(textSize, CGSizeZero)) {
option = NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesFontLeading;
rect = [self boundingRectWithSize:size options:option attributes:attributes context:nil];
textSize = rect.size;
}
}
return textSize;
}
下面我们就调用一下。
#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
下面看一下输出结果
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
联通: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}$";
//联通
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;
}
}
}
下面看调用过程
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);
下面看输出结果
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
可见,可以实现对手机号码的判定。
身份证号码的验证
还是直接看代码
//身份证号码验证
- (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;
}
下面我们就看一下调用过程
NSString *str1 = @"990606198808183611";
BOOL result1 = [str1 jj_isCardIdValid];
NSLog(@"result1 = %d", result1);
下面看输出结果
2017-12-16 00:39:31.180822+0800 JJNSStringTool[2099:49567] result1 = 0
正确的身份证号码我就不去验证了,大家可以自行去验证。
判断是否是整数
还是直接看代码
// 判断是否是整数
- (BOOL)jj_isIntNumber;
// 判断是否是整数
- (BOOL)jj_isIntNumber
{
NSString *regex = @"^-?[0-9]\\d*$";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
return [predicate evaluateWithObject:self];
}
这里就不给大家验证了,大家感兴趣的可以自行验证。
判断是否是小数
还是直接看代码
//判断是否是小数
- (BOOL)jj_isFloatNumber;
//判断是否是小数
- (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];
}
这里就带着大家一起验证下。
//是否是小数
- (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);
}
看输出结果
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
可以,看见可以很好的识别是否是小数。
后记
未完,待续~~~