iOS 开发经常遇到的注意要点集合
iOS如何把所有界面的状态栏的字体颜色都设置为白色
第一步:在info.plist中添加一个字段:view controller -base status bar 设置为NO
第二步:在一个所有界面都继承的父类里添加:
if (IOS7_OR_LATER) { // 判断是否是IOS7
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:NO];
}
OC字符串过滤特殊字符
NSString *tempstring = [dic objectForKey:key];//@"[]{}(#%-*+=_)\\|~(<>$%^&*)_+ "
NSCharacterSet *doNotWant = [NSCharacterSet characterSetWithCharactersInString:@"@¥"];
tempstring = [[tempstring componentsSeparatedByCharactersInSet:doNotWant]componentsJoinedByString:@""];
关于网络请求设置代理后可能会导致崩溃的问题 ||ios中代理为什么要用weak修饰
在代理中,其实也不是用weak来修饰。在MRC的时候是用assign来修饰,在ARC之后用unsafe_unretained,作用是跟weak类似的。主要是为了防止循环引用。比如A引用了B,B引用了C,C又引用了A,这样循环引用之后,如果用strong强引用来修饰,这个代理就永远释放不掉了。
tableview 刷新后 显示到第一行
[self.tableView reloadData];
[self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionTop];
MesaSQLite可以创作、设计、修改一个SQLite3数据库,也被用于编辑、总结、分析客户数据。
官网下载地址: http://www.macupdate.com/app/mac/26079/mesasqlite/download
轻点手势和按钮的点击冲突机制
经过实验发现iOS5和iOS6里面,轻点手势和按钮的点击冲突机制是不同的,结果如下:
一个UIView上如果添加了一个按钮,又添加了Tap手势
在iOS5的设备上跑会只响应Tap手势,按钮不响应点击事件,只会有higlighted效果 在iOS5的设备上跑,按住了按钮,当过了3,4秒左右,跳过Tap手势的识别,再松手,按钮会响应 在iOS6的设备上跑,两者不会冲突,按钮可以点击,非按钮区域可以Tap手势
结论就是iOS5和6之间对于事件响应关系是有区别对待的,而且tap响应时间过后,系统会开始判断点击按钮,把刚才的长按理解为长期的touch down状态。这样处理我感觉很奇怪,万全之策还是要解决冲突,因为首先响应Tap事件,所以处理Tap事件的代理方法,过滤掉UIButton的影响。
具体实现,首先添加UIGestureRecognizerDelegate协议,然后把 Tap手势识别对象设置代理self,然后实现如下代码:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIButton class]]){
return NO;
}
return YES;
}
iOS7
#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
UIView *view = touch.view;
if ([[view.subviews lastObject] isKindOfClass:[UIButton class]]) {
return NO;
}
return YES;
}
键盘高度的位置变化
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
#pragma mark -
#pragma mark Responding to keyboard events
//键盘通知事件
- (void)keyboardWillChangeFrame:(NSNotification*)notification {
if ([self currentFirstResponder]) {
float changeHeight = 0.0;
NSDictionary *info = [notification userInfo];
NSValue *valueEnd = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
// NSValue *valueBegin = [info objectForKey:UIKeyboardFrameBeginUserInfoKey];
NSNumber *duration = [info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
// NSNumber *curve = [info objectForKey:UIKeyboardAnimationCurveUserInfoKey];
CGRect rectEnd = [valueEnd CGRectValue];
// CGRect rectBegin = [valueBegin CGRectValue];
CGRect main = self.view.window.frame;
changeHeight = main.size.height - rectEnd.origin.y;
if (changeHeight < 0) {
changeHeight = 0;
}
[UIView animateWithDuration:[duration doubleValue] animations:^{
_keyLayoutView.frame = CGRectMake(0, 0, _detailView.frame.size.width, _detailView.frame.size.height-changeHeight);
} completion:^(BOOL finished) {
[self getFirstResponder:self.scrollView];
}];
}
}
Xcode 真机调试中"There was an internal API error"错误解决方法
应该是product name名字是中文才出现的问题(算是xcode的bug么?),解决办法:把product name中的名字改成英文(app的名字如果是中文的,可是在plist中的Bundle display name设置中文,这并不会影响)
UITextView: 响应键盘的 return 事件
UITextFieldDelegate代理里面响应return键的回调:textFieldShouldReturn:。 但是 UITextView的代理UITextViewDelegate 里面并没有这样的回调。 但是有别的方法可以实现: UITextViewDelegate里面有这样一个代理函数:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
这个函数的最后一个参数text代表你每次输入的的那个字,所以:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
if ([text isEqualToString:@"\n"]){ //判断输入的字是否是回车,即按下return
//在这里做你响应return键的代码
return NO; //这里返回NO,就代表return键值失效,即页面上按下return,不会出现换行,如果为yes,则输入页面会换行
}
return YES;
}
UIViewAnimationOptions的类型
常规动画属性设置(可以同时选择多个进行设置)
UIViewAnimationOptionLayoutSubviews:动画过程中保证子视图跟随运动。
UIViewAnimationOptionAllowUserInteraction:动画过程中允许用户交互。
UIViewAnimationOptionBeginFromCurrentState:所有视图从当前状态开始运行。
UIViewAnimationOptionRepeat:重复运行动画。
UIViewAnimationOptionAutoreverse :动画运行到结束点后仍然以动画方式回到初始点。
UIViewAnimationOptionOverrideInheritedDuration:忽略嵌套动画时间设置。
UIViewAnimationOptionOverrideInheritedCurve:忽略嵌套动画速度设置。
UIViewAnimationOptionAllowAnimatedContent:动画过程中重绘视图(注意仅仅适用于转场动画)。
UIViewAnimationOptionShowHideTransitionViews:视图切换时直接隐藏旧视图、显示新视图,而不是将旧视图从父视图移除(仅仅适用于转场动画) UIViewAnimationOptionOverrideInheritedOptions :不继承父动画设置或动画类型。
2.动画速度控制(可从其中选择一个设置)
UIViewAnimationOptionCurveEaseInOut:动画先缓慢,然后逐渐加速。
UIViewAnimationOptionCurveEaseIn :动画逐渐变慢。
UIViewAnimationOptionCurveEaseOut:动画逐渐加速。
UIViewAnimationOptionCurveLinear :动画匀速执行,默认值。
3.转场类型(仅适用于转场动画设置,可以从中选择一个进行设置,基本动画、关键帧动画不需要设置)
UIViewAnimationOptionTransitionNone:没有转场动画效果。
UIViewAnimationOptionTransitionFlipFromLeft :从左侧翻转效果。
UIViewAnimationOptionTransitionFlipFromRight:从右侧翻转效果。
UIViewAnimationOptionTransitionCurlUp:向后翻页的动画过渡效果。
UIViewAnimationOptionTransitionCurlDown :向前翻页的动画过渡效果。
UIViewAnimationOptionTransitionCrossDissolve:旧视图溶解消失显示下一个新视图的效果。
UIViewAnimationOptionTransitionFlipFromTop :从上方翻转效果。
UIViewAnimationOptionTransitionFlipFromBottom:从底部翻转效果
拍完照把照片写入到iOS自带相册里面
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
iOS识别16进制颜色表方法
+ (UIColor *)colorWithHexString:(NSString *)color alpha:(CGFloat)alpha {
//删除字符串中的空格
NSString *cString = [[color stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString];
// String should be 6 or 8 characters
if ([cString length] < 6) {
return [UIColor clearColor];
}
// strip 0X if it appears
//如果是0x开头的,那么截取字符串,字符串从索引为2的位置开始,一直到末尾
if ([cString hasPrefix:@"0X"]) {
cString = [cString substringFromIndex:2];
}
//如果是#开头的,那么截取字符串,字符串从索引为1的位置开始,一直到末尾
if ([cString hasPrefix:@"#"]) {
cString = [cString substringFromIndex:1];
}
if ([cString length] != 6) {
return [UIColor clearColor];
}
// Separate into r, g, b substrings
NSRange range;
range.location = 0;
range.length = 2;
//r
NSString *rString = [cString substringWithRange:range];
//g
range.location = 2;
NSString *gString = [cString substringWithRange:range];
//b
range.location = 4;
NSString *bString = [cString substringWithRange:range];
// Scan values
unsigned int r, g, b;
[[NSScanner scannerWithString:rString] scanHexInt:&r];
[[NSScanner scannerWithString:gString] scanHexInt:&g];
[[NSScanner scannerWithString:bString] scanHexInt:&b];
return [UIColor colorWithRed:((float)r / 255.0f) green:((float)g / 255.0f) blue:((float)b / 255.0f) alpha:alpha];
}
//默认alpha值为1
+ (UIColor *)colorWithHexString:(NSString *)color {
return [self colorWithHexString:color alpha:1.0f];
}
画一个利用颜色充满的图片
+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size {
CGRect rect = CGRectMake(0, 0, size.width, size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
iOS获取字符串的拼音
//获取字符串的拼音
- (NSString *)phonetic {
NSString *str = [self stringByReplacingOccurrencesOfString:@"-" withString:@" "];
NSMutableString *source = [str mutableCopy];
CFStringTransform((__bridge CFMutableStringRef)source, NULL, kCFStringTransformMandarinLatin, NO);
CFStringTransform((__bridge CFMutableStringRef)source, NULL, kCFStringTransformStripDiacritics, NO);
return source;
}
NSString 取得首字母
//根据输入的NSString 取得首字母 (中文为拼音首字母)
+ (NSString*)getInitialsFromString:(NSString*)string {
NSString *str = @"";
if(string != nil && string.length > 0) {
str = [[NSString stringWithFormat:@"%c",pinyinFirstLetter([string characterAtIndex:0])]uppercaseString];
NSString *userNameRegex = @"^[A-Z]$";
NSPredicate *userNamePredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",userNameRegex];
BOOL B = [userNamePredicate evaluateWithObject:str];
if (B) {
return str;
}else {
return @"#";
}
} else {
return @"#";
}
}
iOS常用的正则表达式
//邮箱
+ (BOOL) validateEmail:(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];
}
//手机号码验证
+ (BOOL) validateMobile:(NSString *)mobile {
//手机号以13, 15,18开头,八个 \d 数字字符
NSString *phoneRegex = @"^((13[0-9])|(15[^4,\\D])|(18[0,0-9]))\\d{8}$";
NSPredicate *phoneTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",phoneRegex];
return [phoneTest evaluateWithObject:mobile];
}
//车牌号验证
+ (BOOL) validateCarNo:(NSString *)carNo {
NSString *carRegex = @"^[\u4e00-\u9fa5]{1}[a-zA-Z]{1}[a-zA-Z_0-9]{4}[a-zA-Z_0-9_\u4e00-\u9fa5]$";
NSPredicate *carTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",carRegex];
NSLog(@"carTest is %@",carTest);
return [carTest evaluateWithObject:carNo];
}
//车型
+ (BOOL) validateCarType:(NSString *)CarType {
NSString *CarTypeRegex = @"^[\u4E00-\u9FFF]+$";
NSPredicate *carTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",CarTypeRegex];
return [carTest evaluateWithObject:CarType];
}
//用户名
+ (BOOL) validateUserName:(NSString *)name {
NSString *userNameRegex = @"^[A-Za-z0-9]{6,20}+$";
NSPredicate *userNamePredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",userNameRegex];
BOOL B = [userNamePredicate evaluateWithObject:name];
return B;
}
//密码
+ (BOOL) validatePassword:(NSString *)passWord {
NSString *passWordRegex = @"^[a-zA-Z0-9]{6,20}+$";
NSPredicate *passWordPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",passWordRegex];
return [passWordPredicate evaluateWithObject:passWord];
}
//昵称
+ (BOOL) validateNickname:(NSString *)nickname {
NSString *nicknameRegex = @"^[\u4e00-\u9fa5]{4,8}$";
NSPredicate *passWordPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",nicknameRegex];
return [passWordPredicate evaluateWithObject:nickname];
}
//身份证号
+ (BOOL) validateIdentityCard: (NSString *)identityCard {
BOOL flag;
if (identityCard.length <= 0) {
flag = NO;
return flag;
}
NSString *regex2 = @"^(\\d{14}|\\d{17})(\\d|[xX])$";
NSPredicate *identityCardPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex2];
return [identityCardPredicate evaluateWithObject:identityCard];
}
oc中取类名
+ (NSString*)classString {
return NSStringFromClass([self class]);
}
解决interfaceOrientation is deprecated:first deprecated in ios8.0
使用他人代码中出现下面的警告,需要将该方法改为如下所示:
interfaceOrientation is deprecated:first deprecated in ios8.0
[[UIApplication sharedApplication] statusBarOrientation]
请求响应消息
1xx:信息响应类,表示接收到请求并且继续处理
2xx:处理成功响应类,表示动作被成功接收、理解和接受
3xx:重定向响应类,为了完成指定的动作,必须接受进一步处理
4xx:客户端错误,客户请求包含语法错误或者是不能正确执行
5xx:服务端错误,服务器不能正确执行一个正确的请求;
详细描述:状态码
iOS中防止两个按钮同时点击的方法
在iOS开发中通常会遇到,两个靠的很近的按钮,一不小心两个按钮同时点击了。 神奇的bug就产生了,如果两个按钮事件都是跳转页面的话,就会出现连跳两个页面的情况。 通常解决此问题的方法是:定义一个BaseViewController。 设置一个方法setExclusiveTouchForButtons:(UIView *)myView
-(void)setExclusiveTouchForButtons:(UIView *)myView {
for (UIView * v in [myView subviews]) { if([v isKindOfClass:[UIButton class]]) {
[((UIButton *)v) setExclusiveTouch:YES];
} else if (
[v isKindOfClass:[UIView class]]) {
[self setExclusiveTouchForButtons:v];
}
}
}
然后在viewDidDisappear中调用次方法。
- (void)viewDidDisappear:(BOOL)animated {
[self setExclusiveTouchForButtons:self.view];
}
所有ViewController都继承这个BaseViewController就行了 或者使用运行时重写viewDidDisappear也可以。
清理缓存
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showWithStatus:@"正在清理缓存" maskType:SVProgressHUDMaskTypeClear];
});
dispatch_queue_t queue = dispatch_queue_create("cleanQueue", nil);
dispatch_async(queue, ^{
NSFileManager *fileManager = [NSFileManager defaultManager];
//NSDate* begin = [NSDate date];
//__block NSError* error = nil;
//获取Books的缓存
NSArray* subFiles = [fileManager subpathsAtPath:[NSString filePathDir]];
for (NSString* fileName in subFiles) {
if ([[NSFileManager defaultManager]fileExistsAtPath:fileName]) {
BOOL BOOL1 = [fileManager removeItemAtPath:[NSString filePathWithName:fileName] error:nil];
if (BOOL1) {
}
}
}
// 线程睡1秒 测试,实际用到是将下面代码删除即可
//[NSThread sleepForTimeInterval:1.0];
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss];
});
});
}