原创:知识点总结性文章
创作不易,请珍惜,之后会持续更新,不断完善
个人比较喜欢做笔记和写总结,毕竟好记性不如烂笔头哈哈,这些文章记录了我的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] 待校验的字符串为:212226@gmail.com
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<UIImagePickerControllerInfoKey,id> *)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<AFMultipartFormData> _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