IOS基础工具:常用方法

原创:知识点总结性文章
创作不易,请珍惜,之后会持续更新,不断完善
个人比较喜欢做笔记和写总结,毕竟好记性不如烂笔头哈哈,这些文章记录了我的IOS成长历程,希望能与大家一起进步
温馨提示:由于不支持目录跳转,大家可通过command + F 输入目录标题后迅速寻找到你所需要的内容

目录

  • 一、格式校验方法
    • 1、数字格式校验
    • 2、混合校验
    • 3、文字校验
  • 二、常用的宏
    • 1、Block
    • 2、判断系统版本
    • 3、移除Nil
    • 4、消除PerformSelector警告
    • 5、创建单例
  • 三、实用小方法
    • 获取随机数
    • 打印系统中所有字体的类型名字
    • 点击链接跳转
    • 点击背景隐藏键盘
    • 获取当前页面的控制器
    • 在导航栏栈中寻找到指定的页面返回
    • 设置导航栏全透明
    • 禁止侧滑返回上个页面功能
    • 更改导航栏的返回按钮的标题与颜色
    • 从相册中选择图片作为头像并上传该头像到服务器
    • 将图片转化base64并获取图片类型
  • Demo
  • 参考文献

一、格式校验方法

1、数字格式校验

判断文本框字数是否符合规范
+ (BOOL)validateTextCount:(NSString *)text
{
    NSString * regexExpress = @"^.{1,8}$";
    NSPredicate * predicate = [NSPredicate predicateWithFormat: @"SELF MATCHES %@", regexExpress];
    return [predicate evaluateWithObject: text];
}

输出结果为:

2020-09-27 10:52:46.477566+0800 FunctionCodeBlockDemo[18729:18850103] 待校验的字符串为:1234567
2020-09-27 10:52:46.479235+0800 FunctionCodeBlockDemo[18729:18850103] 格式正确
2020-09-27 10:53:51.828923+0800 FunctionCodeBlockDemo[18772:18852912] 待校验的字符串为:123456789
2020-09-27 10:53:51.830487+0800 FunctionCodeBlockDemo[18772:18852912] 格式错误

判断验证码是否正确
+ (BOOL)validateAuthen:(NSString *)text
{
    NSString * regexExpress = @"^\\d{6}$";
    NSPredicate * predicate = [NSPredicate predicateWithFormat: @"SELF MATCHES %@", regexExpress];
    return [predicate evaluateWithObject: text];
}

输出结果为:

2020-09-27 10:56:37.743354+0800 FunctionCodeBlockDemo[18824:18855832] 待校验的字符串为:123456
2020-09-27 10:56:37.744975+0800 FunctionCodeBlockDemo[18824:18855832] 格式正确
2020-09-27 10:56:48.175096+0800 FunctionCodeBlockDemo[18834:18856731] 待校验的字符串为:12345
2020-09-27 10:56:48.176840+0800 FunctionCodeBlockDemo[18834:18856731] 格式错误

判断输入金额是否正确
+ (BOOL)validateMoney:(NSString *)text
{
    NSString * regexExpress = @"^\\d{1,}$";
    NSPredicate * predicate = [NSPredicate predicateWithFormat: @"SELF MATCHES %@", regexExpress];
    return [predicate evaluateWithObject: text];
}

输出结果为:

2020-09-27 10:58:21.199859+0800 FunctionCodeBlockDemo[18865:18858669] 待校验的字符串为:12.5
2020-09-27 10:58:21.201540+0800 FunctionCodeBlockDemo[18865:18858669] 格式错误
2020-09-27 10:58:48.960328+0800 FunctionCodeBlockDemo[18883:18859971] 待校验的字符串为:12
2020-09-27 10:58:48.962059+0800 FunctionCodeBlockDemo[18883:18859971] 格式正确
2020-09-27 10:59:00.854211+0800 FunctionCodeBlockDemo[18896:18860861] 待校验的字符串为:
2020-09-27 10:59:00.855838+0800 FunctionCodeBlockDemo[18896:18860861] 格式错误

判断是否是手机号
+ (BOOL)isMobilePhone:(NSString *)phoneNumber
{
    NSString * Mobile = @"^1(3[0-9]|4[579]|5[0-35-9]|7[01356]|8[0-9])\\d{8}$";
    NSPredicate *regexMobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", Mobile];
    if ([regexMobile evaluateWithObject:phoneNumber])
    {
        return YES;
    }
    return NO;
}

输出结果为:

2020-09-27 11:01:11.720826+0800 FunctionCodeBlockDemo[18936:18863245] 待校验的字符串为:15659281708
2020-09-27 11:01:11.722522+0800 FunctionCodeBlockDemo[18936:18863245] 格式正确
2020-09-27 11:01:48.114921+0800 FunctionCodeBlockDemo[18956:18864543] 待校验的字符串为:11111111111
2020-09-27 11:01:48.116660+0800 FunctionCodeBlockDemo[18956:18864543] 格式错误

判断是否是移动号
+ (BOOL)isCMMobilePhone:(NSString *)phoneNumber
{
    NSString * CM = @"^1(34[0-8]|70[356]|(3[5-9]|4[7]|5[0-27-9]|7[8]|8[2-47-8])\\d)\\d{7}$";
    NSPredicate *regexTestCM = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CM];
    if ([regexTestCM evaluateWithObject:phoneNumber])
    {
        return YES;
    }
    return NO;
}

输出结果为:

2020-09-27 11:20:23.235448+0800 FunctionCodeBlockDemo[19152:18874471] 待校验的字符串为:17859733953
2020-09-27 11:20:23.237178+0800 FunctionCodeBlockDemo[19152:18874471] 格式正确
2020-09-27 11:20:39.546122+0800 FunctionCodeBlockDemo[19165:18877042] 待校验的字符串为:15659281708
2020-09-27 11:20:39.547760+0800 FunctionCodeBlockDemo[19165:18877042] 格式错误

判断是否是联通号
+ (BOOL)isCUMobilePhone:(NSString *)phoneNumber
{
    NSString * CU = @"^1(70[07-9]|(3[0-2]|4[5]|5[5-6]|7[15-6]|8[5-6])\\d)\\d{7}$";
    NSPredicate *regexTestCU = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CU];
    if ([regexTestCU evaluateWithObject:phoneNumber])
    {
        return YES;
    }
    return NO;
}

输出结果为:

2020-09-27 11:22:36.249312+0800 FunctionCodeBlockDemo[19238:18880954] 待校验的字符串为:15659281708
2020-09-27 11:22:36.250896+0800 FunctionCodeBlockDemo[19238:18880954] 格式正确
2020-09-27 11:22:50.018542+0800 FunctionCodeBlockDemo[19257:18881900] 待校验的字符串为:17859733953
2020-09-27 11:22:50.020172+0800 FunctionCodeBlockDemo[19257:18881900] 格式错误

判断是否是电信号
+ (BOOL)isCTMobilePhone:(NSString *)phoneNumber
{
    NSString * CT = @"^1(34[9]|70[0-2]|(3[3]|4[9]|5[3]|7[37]|8[019])\\d)\\d{7}$";
    NSPredicate *regexTestCT = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CT];
    if ([regexTestCT evaluateWithObject:phoneNumber])
    {
        return YES;
    }
    return NO;
}

输出结果为:

2020-09-27 11:24:30.699399+0800 FunctionCodeBlockDemo[19300:18884939] 待校验的字符串为:17338760223
2020-09-27 11:24:30.701030+0800 FunctionCodeBlockDemo[19300:18884939] 格式正确
2020-09-27 11:24:47.980577+0800 FunctionCodeBlockDemo[19317:18886002] 待校验的字符串为:17859733953
2020-09-27 11:24:47.982231+0800 FunctionCodeBlockDemo[19317:18886002] 格式错误
2020-09-27 11:24:59.420994+0800 FunctionCodeBlockDemo[19327:18886842] 待校验的字符串为:15659281708
2020-09-27 11:24:59.422598+0800 FunctionCodeBlockDemo[19327:18886842] 格式错误

18位身份证格式和合法性验证
+(BOOL)checkUserID:(NSString *)userID
{
    // 长度不为18的都排除掉
    if (userID.length != 18)
    {
        return NO;
    }
    
    // 校验格式
    NSString *regex = @"^(^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$)|(^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[Xx])$)$";
    NSPredicate *identityCardPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
    BOOL flag = [identityCardPredicate evaluateWithObject:userID];
    
    if (!flag)// 格式错误
    {
        return flag;
    }
    else// 格式正确再判断是否合法
    {
        // 将前17位加权因子保存在数组里
        NSArray *idCardWiArray = @[@"7", @"9", @"10", @"5", @"8", @"4", @"2", @"1", @"6", @"3", @"7", @"9", @"10", @"5", @"8", @"4", @"2"];
        
        // 这是除以11后,可能产生的11位余数、验证码,也保存成数组
        NSArray *idCardYArray = @[@"1", @"0", @"10", @"9", @"8", @"7", @"6", @"5", @"4", @"3", @"2"];
        
        // 用来保存前17位各自乖以加权因子后的总和
        NSInteger idCardWiSum = 0;
        for(int i = 0;i < 17;i++)
        {
            NSInteger subStrIndex = [[userID substringWithRange:NSMakeRange(i, 1)] integerValue];
            NSInteger idCardWiIndex = [[idCardWiArray objectAtIndex:i] integerValue];
            idCardWiSum += subStrIndex * idCardWiIndex;
        }
        
        // 计算出校验码所在数组的位置
        NSInteger idCardMod = idCardWiSum%11;
        
        // 得到最后一位身份证号码
        NSString * idCardLast= [userID substringWithRange:NSMakeRange(17, 1)];
        
        // 如果等于2,则说明校验码是10,身份证号码最后一位应该是X
        if(idCardMod == 2)
        {
            if([idCardLast isEqualToString:@"X"] || [idCardLast isEqualToString:@"x"])
            {
                return YES;
            }
            else
            {
                return NO;
            }
        }
        else
        {
            // 用计算出的验证码与最后一位身份证号码匹配,如果一致,说明通过,否则是无效的身份证号码
            if([idCardLast isEqualToString: [idCardYArray objectAtIndex:idCardMod]])
            {
                return YES;
            }
            else
            {
                return NO;
            }
        }
    }
}

输出结果为:

2020-09-27 11:27:05.324091+0800 FunctionCodeBlockDemo[19364:18889544] 待校验的字符串为:11010119900307643X
2020-09-27 11:27:05.325713+0800 FunctionCodeBlockDemo[19364:18889544] 格式正确
2020-09-27 11:27:20.754961+0800 FunctionCodeBlockDemo[19374:18890477] 待校验的字符串为:11010119900
2020-09-27 11:27:20.755146+0800 FunctionCodeBlockDemo[19374:18890477] 格式错误

车牌号格式校验(粤A8888澳)
+ (BOOL)checkCarID:(NSString *)carID
{
    if (carID.length != 7)
    {
        return NO;
    }
    
    NSString *carRegex = @"^[\u4e00-\u9fa5]{1}[a-hj-zA-HJ-Z]{1}[a-hj-zA-HJ-Z_0-9]{4}[a-hj-zA-HJ-Z_0-9_\u4e00-\u9fa5]$";
    NSPredicate *carTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",carRegex];
    return [carTest evaluateWithObject:carID];
}

输出结果为:

2020-09-27 11:28:45.787246+0800 FunctionCodeBlockDemo[19396:18892383] 待校验的字符串为:粤A8888澳
2020-09-27 11:28:45.788894+0800 FunctionCodeBlockDemo[19396:18892383] 格式正确
2020-09-27 11:29:00.628475+0800 FunctionCodeBlockDemo[19412:18893523] 待校验的字符串为:粤A88
2020-09-27 11:29:00.628629+0800 FunctionCodeBlockDemo[19412:18893523] 格式错误

银行卡格式验证
+ (BOOL)isBankCard:(NSString *)bankCard
{
    if (bankCard.length < 16)
    {
        return NO;
    }
    
    NSInteger oddSum = 0;// 奇数求和
    NSInteger evenSum = 0;// 偶数求和
    NSInteger allSum = 0;
    NSInteger cardNumberLength = (NSInteger)[bankCard length];
    
    // 取了最后一位数
    NSInteger lastNumber = [[bankCard substringFromIndex:cardNumberLength - 1] intValue];
    
    // 测试的是除了最后一位数外的其他数字
    bankCard = [bankCard substringToIndex:cardNumberLength - 1];
    
    for (NSInteger i = cardNumberLength - 1 ; i >= 1;i--)
    {
        NSString *tempString = [bankCard substringWithRange:NSMakeRange(i - 1, 1)];
        NSInteger tempValue = [tempString integerValue];
        if (cardNumberLength % 2 == 1 )// 卡号位数为奇数
        {
            if((i % 2) == 0)// 偶数位置
            {
                tempValue *= 2;
                if (tempValue >= 10)
                {
                    tempValue -= 9;
                }
                evenSum += tempValue;
            }
            else// 奇数位置
            {
                oddSum += tempValue;
            }
        }
        else
        {
            if((i % 2) == 1)
            {
                tempValue *= 2;
                if(tempValue >= 10)
                {
                    tempValue -= 9;
                }
                    
                evenSum += tempValue;
            }
            else
            {
                oddSum += tempValue;
            }
        }
    }
    
    allSum = oddSum + evenSum;
    allSum += lastNumber;
    if((allSum % 10) == 0)
    {
        return YES;
    }
    else
    {
        return NO;
    }
}

输出结果为:

2020-09-27 11:30:28.815633+0800 FunctionCodeBlockDemo[19439:18895693] 待校验的字符串为:6221882600114166800
2020-09-27 11:30:28.815815+0800 FunctionCodeBlockDemo[19439:18895693] 格式正确
2020-09-27 11:30:55.528978+0800 FunctionCodeBlockDemo[19456:18896846] 待校验的字符串为:6221882
2020-09-27 11:30:55.529138+0800 FunctionCodeBlockDemo[19456:18896846] 格式错误

2、混合校验

6~16位数字/字母/下划线组成的密码格式校验
+ (BOOL)checkPassword:(NSString *)passwordString
{
    NSString *pattern = @"^[A-Za-z0-9_]{6,16}$";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", pattern];
    return [predicate evaluateWithObject:passwordString];
}

输出结果为:

2020-09-27 11:33:42.387144+0800 FunctionCodeBlockDemo[19490:18899693] 待校验的字符串为:Ab123456
2020-09-27 11:33:42.388725+0800 FunctionCodeBlockDemo[19490:18899693] 格式正确
2020-09-27 11:34:56.640539+0800 FunctionCodeBlockDemo[19547:18903956] 待校验的字符串为:AAAAAAAAA
2020-09-27 11:34:56.642130+0800 FunctionCodeBlockDemo[19547:18903956] 格式正确
2020-09-27 11:34:33.141514+0800 FunctionCodeBlockDemo[19529:18902842] 待校验的字符串为:12345678910
2020-09-27 11:34:33.143212+0800 FunctionCodeBlockDemo[19529:18902842] 格式正确
2020-09-27 11:35:08.997045+0800 FunctionCodeBlockDemo[19557:18904861] 待校验的字符串为:A
2020-09-27 11:35:08.998633+0800 FunctionCodeBlockDemo[19557:18904861] 格式错误

判断字符串是否全为[(数字)、(字母)、(数字|字母)、(汉字)]
+(BOOL)isAllNumber:(NSString *)string
{
    NSString *condition = @"^[0-9]*$";// 是否都是数字
    //NSString *condition = @"^[A-Za-z]+$";//是否都是字母
    //NSString *condition = @"^[A-Za-z0-9]+$";//是否都是字母和数字
    //NSString *condition = @"^[A-Za-z0-9]{6,16}$";//是否都是字母和数字且长度在[6,16]
    //NSString *condition = @"^[\u4e00-\u9fa5]{0,}$";//只能输入汉字
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES%@",condition];
    return [predicate evaluateWithObject:string];
}

输出结果为:

2020-09-27 11:36:12.740745+0800 FunctionCodeBlockDemo[19578:18906474] 待校验的字符串为:12345
2020-09-27 11:36:12.742450+0800 FunctionCodeBlockDemo[19578:18906474] 格式正确
2020-09-27 11:36:29.644180+0800 FunctionCodeBlockDemo[19589:18907523] 待校验的字符串为:123AB
2020-09-27 11:36:29.645862+0800 FunctionCodeBlockDemo[19589:18907523] 格式错误

邮箱格式验证
+(BOOL)isEmail:(NSString *)email
{
    NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
    NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
    return [emailTest evaluateWithObject:email];
}

输出结果为:

2020-09-27 11:37:41.488681+0800 FunctionCodeBlockDemo[19608:18909237] 待校验的字符串为:[email protected]
2020-09-27 11:37:41.490287+0800 FunctionCodeBlockDemo[19608:18909237] 格式正确
2020-09-27 11:37:53.592850+0800 FunctionCodeBlockDemo[19621:18910897] 待校验的字符串为:212226@gmail
2020-09-27 11:37:53.594444+0800 FunctionCodeBlockDemo[19621:18910897] 格式错误

判断密码格式是否正确
+ (BOOL)validatePassword:(NSString *)passwordString
{
    NSString *length = @"^\\w{6,20}$";// 长度
    NSString *number = @"^\\w*\\d+\\w*$";// 数字
    NSString *lower = @"^\\w*[a-z]+\\w*$";// 小写字母
    NSString *upper = @"^\\w*[A-Z]+\\w*$";// 大写字母
    
    NSPredicate *lengthPredicate = [NSPredicate predicateWithFormat: @"SELF MATCHES %@", length];
    NSPredicate *numberPredicate = [NSPredicate predicateWithFormat: @"SELF MATCHES %@", number];
    NSPredicate *lowerPredicate = [NSPredicate predicateWithFormat: @"SELF MATCHES %@", lower];
    NSPredicate *upperPredicate = [NSPredicate predicateWithFormat: @"SELF MATCHES %@", upper];
    
    BOOL lengthFlag = [lengthPredicate evaluateWithObject:passwordString];
    BOOL numberFlag = [numberPredicate evaluateWithObject:passwordString];
    BOOL lowerFlag = [lowerPredicate evaluateWithObject:passwordString];
    BOOL upperFlag = [upperPredicate evaluateWithObject:passwordString];
    return (lengthFlag && numberFlag && lowerFlag && upperFlag);
}

输出结果为:

2020-09-27 11:42:43.940427+0800 FunctionCodeBlockDemo[19707:18915828] 待校验的字符串为:212226gmail
2020-09-27 11:42:43.942167+0800 FunctionCodeBlockDemo[19707:18915828] 格式错误
2020-09-27 11:43:18.438507+0800 FunctionCodeBlockDemo[19727:18917110] 待校验的字符串为:212226Gmail
2020-09-27 11:43:18.440343+0800 FunctionCodeBlockDemo[19727:18917110] 格式正确

3、文字校验

昵称校验
+ (BOOL)validateNickname:(NSString *)nickname
{
    NSString *nicknameRegex = @"^[\u4e00-\u9fa5]{1,8}$";
    NSPredicate *passWordPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",nicknameRegex];
    return [passWordPredicate evaluateWithObject:nickname];
}

输出格式为:

2020-09-27 11:44:25.958665+0800 FunctionCodeBlockDemo[19752:18918805] 待校验的字符串为:212226Gmail
2020-09-27 11:44:25.960309+0800 FunctionCodeBlockDemo[19752:18918805] 格式错误
2020-09-27 11:44:41.052712+0800 FunctionCodeBlockDemo[19762:18919744] 待校验的字符串为:谢佳培
2020-09-27 11:44:41.054403+0800 FunctionCodeBlockDemo[19762:18919744] 格式正确

文本框校验:小数点后两位以上便禁止输入
UITextFieldDelegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    BOOL judgeTwoDecimalPlaces = [self JudgeTwoDecimalPlaces:textField shouldChangeCharactersInRange:range replacementString:string];
    return judgeTwoDecimalPlaces;
}
校验方法
- (BOOL)JudgeTwoDecimalPlaces:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    // 如果输入的是“.”  判断之前已经有"."或者字符串为空
     if ([string isEqualToString:@"."] && ([textField.text rangeOfString:@"."].location != NSNotFound || [textField.text isEqualToString:@""]))
     {
         NSLog(@"文本框内容为:%@,已经有小数点了,禁止再输入小数点",textField.text);
         return NO;
     }
    
     // 拼出输入完成的str,判断str的长度大于等于“.”的位置+4,则返回false,此次插入string失败
     // "379132.424",长度10,"."的位置6, 10>=6+4
     NSMutableString *str = [[NSMutableString alloc] initWithString:textField.text];
     [str insertString:string atIndex:range.location];
    
     if (str.length >= [str rangeOfString:@"."].location + 4)
     {
         NSLog(@"文本框内容为:%@,小数点后两位以上了,禁止输入",str);
         return NO;
     }
    
     return YES;
}

输出结果为:

2020-09-28 09:54:21.094432+0800 FunctionCodeBlockDemo[26113:19329511] 文本框内容为:1234.555,小数点后两位以上了,禁止输入
2020-09-28 09:54:40.504445+0800 FunctionCodeBlockDemo[26113:19329511] 文本框内容为:1234.5,已经有小数点了,禁止再输入小数点

二、常用的宏

1、Block

void
typedef void (^VoidBlock)(void);
typedef void (^ClickBlock)(void);
typedef void (^ClickIndexBlock)(NSInteger index);
typedef BOOL (^BoolBlock)(void);
typedef int  (^IntBlock)(void);
typedef id   (^IDBlock)(void);
int
typedef void (^Void_IntBlock)(int index);
typedef BOOL (^Bool_IntBlock)(int index);
typedef int  (^Int_IntBlock)(int index);
typedef id   (^ID_IntBlock)(int index);
string
typedef void (^Void_StringBlock)(NSString *str);
typedef BOOL (^Bool_StringBlock)(NSString *str);
typedef int  (^Int_StringBlock)(NSString *str);
typedef id   (^ID_StringBlock)(NSString *str);
id
typedef void (^Void_IDBlock)(id data);
typedef BOOL (^Bool_IDBlock)(id data);
typedef int  (^Int_IDBlock)(id data);
typedef id   (^ID_IDBlock)(id data);
bool
typedef void (^VoidBoolBlock)(BOOL flag);
调用方式
@property (nonatomic, copy) ClickBlock clickBlock;

2、判断系统版本

宏定义
#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
调用方式
- (void)testSystemVersion
{
    if (SYSTEM_VERSION_GREATER_THAN(@"13.0"))
    {
        NSLog(@"系统当前版本号为14.2");
    }
}
输出结果
2020-11-25 15:35:11.792044+0800 Macro[78684:5115639] 系统当前版本号为14.2

3、移除Nil

nil 转换 ""
+ (NSString *)removeNil:(NSString *)str
{
    return [NSString removeNilToValue:str value:@""];
}
nil 转换 value
+ (NSString *)removeNilToValue:(NSString *)str value:(NSString *)value
{
    if (str == nil)
    {
        return value;
    }
    return str;
}
nil 转换 "-"
+ (NSString *)removeNilToConnect:(NSString *)str
{
    return [NSString removeNilToValue:str value:@"-"];
}
int 转 str
+ (NSString *)intToStr:(NSInteger)num
{
    return [NSString stringWithFormat:@"%ld", num];
}
#define StrRemoveNiL(v)  ([NSString removeNil:v])
#define StrNilToValue(k,v)  ([NSString removeNilToValue:k value:v])
#define StrNilToConnect(v)  ([NSString removeNilToConnect:v])
#define IntToStr(v)  ([NSString intToStr:v])
调用方式
- (void)testRemoveNiL
{
    NSString *name = nil;
    NSString *phone = nil;
    NSString *provinceName = @"福建省";
    
    NSString *detailAddress = [NSString stringWithFormat:@"%@ %@ %@",
                               StrNilToValue(name,@"谢佳培"),
                               StrRemoveNiL(phone),
                               StrRemoveNiL(provinceName)];
    NSLog(@"收货地址:%@",detailAddress);
}

输出结果

2020-11-25 15:52:11.489857+0800 Macro[78948:5130842] 收货地址:谢佳培  福建省

4、消除PerformSelector警告

#define SuppressPerformSelectorLeakWarning(Stuff) \
do { \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \
Stuff; \
_Pragma("clang diagnostic pop") \
} while (0)
调用方式
- (void)copyAction
{
    SuppressPerformSelectorLeakWarning(
    if ([self.formViewController canPerformAction:self.rowDescriptor.action.formSelector withSender:self.orderLabel.text])
    {
        [self.formViewController performSelector:self.rowDescriptor.action.formSelector withObject:self.orderLabel.text];
    });
}

5、创建单例

#define SingleH(name) +(instancetype)share##name;

#define SingleM(name)  \
static id instanceMessages;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
\
static dispatch_once_t onceToken;\
\
dispatch_once(&onceToken, ^{\
\
instanceMessages = [super allocWithZone:zone];\
\
});\
\
return instanceMessages;\
}\
-(id)copy\
{\
return instanceMessages;\
}\
+(instancetype)share##name\
{\
    \
    static dispatch_once_t onceToken;\
    \
    dispatch_once(&onceToken, ^{\
        \
        instanceMessages = [[self alloc]init];\
        \
    });\
    \
    return instanceMessages;\
}
调用方式
/** 工具类单例 */
SingleH(UCARAudioTool)
SingleM(UCARAudioTool)

三、实用小方法

获取随机数
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    int randomNumber = [self getRandomNumber:0 to:100];
    NSLog(@"随机数:%d",randomNumber);
}

获取一个随机整数,范围在[from,to],包括from,包括to

- (int)getRandomNumber:(int)from to:(int)to
{
    return (int)(from + (arc4random() % (to - from + 1)));
}

输出结果为:

2020-09-25 11:00:54.338468+0800 FunctionCodeBlockDemo[5532:18165243] 随机数:65

打印系统中所有字体的类型名字
- (void)getFontNames
{
    NSArray *familyNames = [UIFont familyNames];
    for(NSString *familyName in familyNames )
    {
        printf("字体家族名称: %s \n", [familyName UTF8String]);
        
        NSArray *fontNames = [UIFont fontNamesForFamilyName:familyName];
        for(NSString *fontName in fontNames)
        {
            printf("\t字体名称: %s \n", [fontName UTF8String]);
        }
    }
}

输出结果为:

字体家族名称: Academy Engraved LET 
    字体名称: AcademyEngravedLetPlain 
字体家族名称: Al Nile 
    字体名称: AlNile 
    字体名称: AlNile-Bold 
.......

点击链接跳转
- (void)ClickLinkToJump
{
    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"百度"];
    
    NSDictionary *linkDict = @{ NSLinkAttributeName:[NSURL URLWithString:@"http://www.baidu.com"] };
    
    [str setAttributes:linkDict range:[[str string] rangeOfString:@"百度"]];
    
    self.textView.attributedText = str;
    self.textView.editable = NO;
    self.textView.dataDetectorTypes = UIDataDetectorTypeLink;
}

运行效果如下:

点击链接跳转

点击背景隐藏键盘
// 点击背景隐藏键盘
- (void)tapBackgroundHideKeyboard
{
    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(keyboardHide:)];
    
    // 设置成NO表示当前控件响应后会传播到其他控件上,默认为YES
    tapGestureRecognizer.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer:tapGestureRecognizer];
}

- (void)keyboardHide:(UITapGestureRecognizer*)tap
{
    [self.textField resignFirstResponder];
    NSLog(@"点击了背景,键盘被隐藏了");
}

输出结果为:

2020-09-25 11:23:13.630446+0800 FunctionCodeBlockDemo[5946:18186936] 点击了背景,键盘被隐藏了

获取当前页面的控制器
- (UIViewController *)currentViewController
{
    UIViewController* currentViewController = [[[UIApplication sharedApplication] delegate] window].rootViewController;
    BOOL runLoopFind = YES;
    while (runLoopFind)
    {
        if (currentViewController.presentedViewController)
        {
            currentViewController = currentViewController.presentedViewController;
            
        }
        else if ([currentViewController isKindOfClass:[UINavigationController class]])
        {
            UINavigationController* navigationController = (UINavigationController* )currentViewController;
            currentViewController = [navigationController.childViewControllers lastObject];
            
        }
        else if ([currentViewController isKindOfClass:[UITabBarController class]])
        {
            UITabBarController* tabBarController = (UITabBarController* )currentViewController;
            currentViewController = tabBarController.selectedViewController;
            
        }
        else
        {
            NSUInteger childViewControllerCount = currentViewController.childViewControllers.count;
            
            if (childViewControllerCount > 0)
            {
                currentViewController = currentViewController.childViewControllers.lastObject;
                return currentViewController;
            }
            else
            {
                return currentViewController;
            }
        }
    }
    
    return currentViewController;
}

在导航栏栈中寻找到指定的页面返回
- (void)backToNeedViewController
{
    NSMutableArray *viewControllers = [[NSMutableArray alloc] init];
    
    for (UIViewController *viewController in [self.navigationController viewControllers])
    {
        [viewControllers addObject:viewController];
    
        if ([viewController isKindOfClass:[NeedViewController class]])
        {
            break;
        }
    }
    
    [self.navigationController setViewControllers:viewControllers   animated:YES];
}

设置导航栏全透明
- (void)viewWillAppear:(BOOL)animated
{
    // 设置导航栏背景图片为一个空的image,这样就透明了
    [self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];
    
    // 去掉透明后导航栏下边的黑边
    [self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];
}

- (void)viewWillDisappear:(BOOL)animated
{
    // 如果不想让其他页面的导航栏变为透明 需要重置
    [self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
    
    [self.navigationController.navigationBar setShadowImage:nil];
}

禁止侧滑返回上个页面功能
- (void)disableSideslipReturn
{
    // 1.首先把顶部左侧返回按钮隐藏掉
    self.navigationItem.hidesBackButton = YES;
    
    // 2.再禁止页面左侧滑动返回
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
    {
        self.navigationController.interactivePopGestureRecognizer.enabled = NO;
    }
}

如果仅仅需要禁止此单个页面返回,还需要重新开放侧滑权限。

- (void)viewWillDisappear:(BOOL)animated
{
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
    {
        self.navigationController.interactivePopGestureRecognizer.enabled = YES;
    }
}

更改导航栏的返回按钮的标题与颜色
- (void)changeNavigationBarTitleAndColor
{
    // 返回按钮
    self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:nil action:nil];
    
    // 修改返回按钮的颜色
    self.navigationController.navigationBar.tintColor = [UIColor redColor];

    // 设置导航条的色调
    self.navigationController.navigationBar.barTintColor = [UIColor blackColor];
    
    // 导航栏默认是半透明状态
    self.navigationController.navigationBar.backgroundColor = [UIColor blueColor];
    
    // 导航栏标题颜色
    [self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]}];
    
    self.navigationController.navigationBar.translucent = NO;
}

运行效果如下:

更改导航栏的返回按钮的标题与颜色

从相册中选择图片作为头像并上传该头像到服务器

先接受相册相关委托,然后再声明相册控制器,并设置其属性
UIImagePickerControllerDelegate, UINavigationControllerDelegate

@property (nonatomic, strong) UIImagePickerController *pickerController;
self.pickerController.delegate = self;
self.pickerController.allowsEditing = YES;
实现弹出相册选择器的方法
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"上传头像" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *takePhotoAction = [UIAlertAction actionWithTitle:@"拍照" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
        if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
            self.pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
            // 让相机页面出来
            [self presentViewController:self.pickerController animated:YES completion:nil];
        } else {
            // 请在设置-->隐私-->照片,中开启本应用的相机访问权限
            // 取消--我知道了
            [self alertInfo];
        }
    }];
[alertController addAction:takePhotoAction];
[self presentViewController:alertController animated:YES completion:nil];
实现用户选中图片时调用的委托方法
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{
    //获得可编辑图片
    UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
    //给头像赋予图片(和没选中到时候就显示的照片不一样获取途径)
    self.headCell.profileimageView.image = image;
    //压缩图片
    UIImage *iconImage = [self imageWithImageSimple:image scaledToSize:CGSizeMake(200, 200)];
    //保存图片至本地,下次进来直接去沙盒路径取
    [self saveImage:iconImage withName:@"seticonImage.jpg"];
    //上传头像
    [self postIconImage];
    
    [picker dismissViewControllerAnimated:YES completion:nil];
}
压缩图片方法
- (UIImage*)imageWithImageSimple:(UIImage*)image scaledToSize:(CGSize)newSize
{
    UIGraphicsBeginImageContext(newSize);
    [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext()
    return newImage;
}
保存图片至沙盒
- (void)saveImage:(UIImage *)currentImage withName:(NSString *)imageName
{
    // 读取图片数据
    NSData *imageData = UIImagePNGRepresentation(currentImage);
    // 获取沙盒目录
    NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *fullPath = [documentPath stringByAppendingPathComponent:imageName];
    // 将图片写入文件
    [imageData writeToFile:fullPath atomically:NO];
    // 获得图片路径
    self.headPath = fullPath;
}
从本地沙盒取得图片
- (UIImage *)getImage:(NSString *)urlStr 
{
    return [UIImage imageWithContentsOfFile:urlStr];
}
头像先从本地沙盒获取显示,找不到再去网络下载
 if (self.headPath.length > 0) {//本地存有头像
     self.headCell.profileimageView.image = [self getImage:self.headPath];
} else {//否则从网上下载
     NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:self.userDetailInfo[@"imageUrl"]]];
     self.headCell.profileimageView.image = [UIImage imageWithData:data];
 }
上传头像方法
- (void)postIconImage {
    URLRequest *requestForPostIcon = [[URLRequest alloc] init];
    //一、构建URL,作为头像的上传地址
    NSString *urlStr = [requestForPostIcon requestForProfileImage:nil pathUrl:@"/member/updateImage"];
    //二、将图片转化为NSData
    NSData *imageData = UIImageJPEGRepresentation([self getImage:self.headPath], 0.5);
    //三、POST
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
    [manager POST:urlStr parameters:nil constructingBodyWithBlock:^(id  _Nonnull formData) {
        //@"file"需要设置为需要上传参数的字段
        [formData appendPartWithFileData:imageData name:@"file" fileName:@"iconImage.jpg" mimeType:@"image/jpeg"];
    } progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"上传成功");
        
        [MBProgressHUD hideHUDForView:self.view animated:YES];
        if ([responseObject[@"result_code"] isEqual:@(1)]) {
           
//            self.iconImageStr = responseObject[@"data"][@"save_path"];
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        [MBProgressHUD showError:error.localizedDescription];
    }];
}
实现用户点击取消退出picker时候调用的委托方法
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    [picker dismissViewControllerAnimated:YES completion:^{
        NSLog(@"%@",picker);
    }];
}

将图片转化base64并获取图片类型

- (NSString *)base64StringForHTMLWtithImageData:(NSData *)imageData
{
    SDImageFormat imageFormat = [NSData sd_imageFormatForImageData:imageData];
    NSString *imageTypeStr = [self imageTypeStringWithSDImageFormat:imageFormat];
    if (imageTypeStr.length <= 0)
    {
        return @"";
    }
    NSString *base64Str = [imageData base64EncodedString];
    return [NSString stringWithFormat:@"data:image/%@;base64,%@",imageTypeStr, base64Str];
}
- (NSString *)imageTypeStringWithSDImageFormat:(SDImageFormat)imageFormate
{
    switch (imageFormate)
    {
        case SDImageFormatJPEG:
        {
            return @"jpeg";
        }
        case SDImageFormatPNG:
        {
            return @"png";
        }
        case SDImageFormatGIF:
        {
            return @"gif";
        }
        case SDImageFormatTIFF:
        {
            return @"tiff";
        }
        case SDImageFormatWebP:
        {
            return @"webP";
        }
        case SDImageFormatHEIC:
        {
            return @"heic";
        }
        default:
            return @"";
    }
}

Demo

Demo在我的Github上,欢迎下载。
BasicsDemo

参考文献

你可能感兴趣的:(IOS基础工具:常用方法)