打印所有视图的子视图
po [[self view] recursiveDescription]
NSString判断特殊字符
if ([string rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet].invertedSet].location != NSNotFound) {
NSLog(@"%@", @"This field accepts only numeric entries.");
}
NSCharacterSet *set = [[NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ0123456789"] invertedSet];
if ([string rangeOfCharacterFromSet:set].location != NSNotFound) {
NSLog(@"This string contains illegal characters");
}
去除tableView中分割线多余的15个像素
- 首先在
viewDidLoad
方法加入以下代码:
if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
[self.tableView setSeparatorInset:UIEdgeInsetsZero];
}
if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
[self.tableView setLayoutMargins:UIEdgeInsetsZero];
}
- 然后在代理方法
willDisplayCell
中加入以下代码
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath {
if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
iOS直接退出应用
AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;
UIWindow *window = app.window;
[UIView animateWithDuration:1.0f animations:^{
window.alpha = 0;
}complain:^(BOOL finished){
exit(0);
}];
数组快速求和、最大值、最小值、平均值
NSArray *array = @[@"1.0",@"2.1",@"3.2",@"4.3"] ;
NSNumber *sum = [array valueForKeyPath:@"sum.floatValue"] ;
NSNumber *avg = [array valueForKeyPath:@"avg.floatValue"] ;
NSNumber *max = [array valueForKeyPath:@"max.floatValue"] ;
NSNumber *min = [array valueForKeyPath:@"min.floatValue"] ;
修改Label中不同文字的颜色
- (void)editStringColor:(NSString *)string editStr:(NSString *)editStr color:(UIColor *)color {
// string为整体字符串, editStr为需要修改的字符串
NSRange range = [string rangeOfString:editStr];
NSMutableAttributedString *attribute = [[NSMutableAttributedString alloc] initWithString:string];
// 设置属性修改字体颜色UIColor或大小UIFont
[attribute addAttributes:@{NSForegroundColorAttributeName:color} range:range];
self.label.attributedText = attribute;
}
播放声音
//1.获取音效资源的路径
NSString *path = [[NSBundle mainBundle]pathForResource:@"sound" ofType:@"wav"];
//2.将路径转化为url
NSURL *tempUrl = [NSURL fileURLWithPath:path];
//3.用转化成的url创建一个播放器
NSError *error = nil;
AVAudioPlayer *play = [[AVAudioPlayer alloc]initWithContentsOfURL:tempUrl error:&error];
//4.播放
[play play];
播放音效
SystemSoundID soundId ;
NSURL *soundURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:urlStr ? urlStr : @"" ofType:nil]] ;
AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)soundURL, &soundId) ;
if(didShock) {
//播放音效时带振动
AudioServicesPlayAlertSound(soundId) ;
}
else {
//播放音效时不带振动
AudioServicesPlaySystemSound(soundId) ;
}
修改TabBar Item
的属性
- 修改标题位置
self.tabBarItem.titlePositionAdjustment = UIOffsetMake(0, -10);
- 修改图片位置
self.tabBarItem.imageInsets = UIEdgeInsetsMake(-3, 0, 3, 0);
- 批量修改属性
for (UIBarItem *item in self.tabBarController.tabBar.items) {
[item setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont fontWithName:@"Helvetica" size:19.0], NSFontAttributeName, nil] forState:UIControlStateNormal];
}
- 未选中字体颜色
[[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor greenColor]} forState:UIControlStateNormal];
- 选中字体颜色
[[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor cyanColor]} forState:UIControlStateSelected];
修改UItextField中placeholder的文字颜色和字体大小
[textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
[textField setValue:[UIFont boldSystemFontOfSize:16] forKeyPath:@“_placeholderLabel.font”];
判断对像是否遵循了某协议
if ([self.selectedController conformsToProtocol:@protocol(RefreshPtotocol)]) {
[self.selectedController performSelector:@selector(onTriggerRefresh)];
}
侧滑手势
- 禁止侧滑手势
- (void)closePopGestureRecognizer{
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}
}
- 开启侧滑手势
- (void)openPopGestureRecognizer{
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
}
}
修改Label行间距
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:self.contentLabel.text];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:3];
//调整行间距
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [self.contentLabel.text length])];
self.contentLabel.attributedText = attributedString;
字符串相关操作
- 去除所有的空格
[str stringByReplacingOccurrencesOfString:@" " withString:@""];
- 去除首尾的空格
[str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
- 全部字符转为大写字母
- (NSString *)uppercaseString;
- 全部字符转为小写字母
- (NSString *)lowercaseString;
设置滑动的时候隐藏导航栏
self.navigationController.hidesBarsOnSwipe = YES ;
mac下wav转caf格式
打开终端(Terminal),先进入wav文件所在的目录,输入命令:/usr/bin/afconvert -f caff -d LEI16 “name.wav”
scrollView的触摸事件传递
从你的手指touch屏幕开始,scrollView开始一个timer,如果:
- 150ms内如果你的手指没有任何动作,消息就会传给subView
- 150ms内手指有明显的滑动(一个swipe动作),scrollView就会滚动,消息不会传给subView
- 150ms内手指没有滑动,scrollView将消息传给subView,但是之后手指开始滑动,scrollView传送touchesCancelled消息给subView,然后开始滚动。
观察下tableView的情况,你先按住一个cell,cell开始高亮,手不要放开,开始滑动,tableView开始滚动,高亮取消。
delaysContentTouches的作用:这个标志默认是YES,使用上面的150ms的timer,如果设置为NO,touch事件立即传递给subView,不会有150ms的等待。
cancelsTouches的作用:这个标准默认为YES,如果设置为NO,这消息一旦传递给subView,这scroll事件不会再发生。
mac下显示编译时间
打开终端,输入命令defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES
UIImageView序列帧动画
UIImageView *tom = [UIImageView alloc]init] ;
NSMutableArray *arrayM=[NSMutableArray array];
for (int i=0; i<40; i++) {
[arrayM addObject:[UIImage imageNamed:[NSString stringWithFormat:@"eat_%02d.jpg",i]]];
}
//0.是否正在动画
[self.tom isAnimating];
//1.设置图片的数组
[self.tom setAnimationImages:arrayM];
//2.设置动画播放次数
[self.tom setAnimationRepeatCount:1];
//3.设置动画时长,默认每秒播放30张图片
[self.tom setAnimationDuration:40*0.075];
//4.开始动画
[self.tom startAnimating];
//5.动画播放完成后,清空动画数组
[self.tom performSelector:@selector(setAnimationImages:) withObject:nil afterDelay:self.tom.animationDuration];
补充
Images.xcassets中的素材只支持png格式的图片
图片只支持[UIImage imageNamed]的方式实例化,但是不能从Bundle中加载
在编译时,Images.xcassets中的所有文件会被打包为Assets.car的文件
跳转至应用系统权限配置
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString] ;
if([[UIApplication sharedApplication] canOpenURL:url]) {
[[UIApplication sharedApplication] openURL:url] ;
}
判断某个viewController是否正在显示
- (BOOL)isVisable {
return (_curViewController.isViewLoaded && _curViewController.view.window) ;
}
- (UIViewController*)getCurrentVC {
UIViewController *displayVC = nil;
UIWindow *window = [[UIApplication sharedApplication] keyWindow] ;
if(window.windowLevel != UIWindowLevelNormal)
{
NSArray *windows = [[UIApplication sharedApplication] windows] ;
for(UIWindow *tmpWindow in windows) {
if(tmpWindow.windowLevel == UIWindowLevelNormal) {
window = tmpWindow ;
break;
}
}
}
id nextResponder = nil ;
UIViewController *rootVC = window.rootViewController ;
if(rootVC.presentedViewController) {
nextResponder = rootVC.presentedViewController;
}
else {
UIView *frontView = [[window subviews] objectAtIndex:0] ;
nextResponder = [frontView nextResponder] ;
}
if([nextResponder isKindOfClass:[UITabBarController class]]) {
UITabBarController *tabVC = (UITabBarController*)nextResponder ;
UINavigationController *navVC = tabVC.selectedViewController ;
displayVC = navVC.childViewControllers.lastObject;
}
else if([nextResponder isKindOfClass:[UINavigationController class]]) {
UINavigationController *navVC = (UINavigationController*)nextResponder ;
displayVC = navVC.childViewControllers.lastObject;
}
else {
displayVC = nextResponder ;
}
return displayVC ;
}
检查第三方APP是否安装及跳转启动
通过[[UIApplication sharedApplication] canOpenUrl:[NSURL URLWithString:@""]]
判断是否安装第三方app
通过[[UIApplication sharedApplication] openUrl:[NSURL URLWithString:@""]]
跳转启动
控件局部圆角
CGRect rect = CGRectMake(0, 0, button.bounds.size.width, button.bounds.size.height) ;
CGSize radio = CGSizeMake(5, 5); //圆角尺寸
UIRectCorner corner = UIRectCornerTopLeft|UIRectCornerTopRight;//圆角位置
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:corner cornerRadii:radio];
//图层蒙版
CAShapeLayer *masklayer = [[CAShapeLayer alloc]init];
masklayer.frame = button.bounds;
masklayer.path = path.CGPath;
button.layer.mask = masklayer;
隐藏状态栏
隐藏状态栏有两种途径,一种是在应用层面,即整个应用隐藏状态栏;另一种是在控制器层面,即在该控制器隐藏状态栏。使用哪种途径由info.plist
文件中的View controller-based status bar appearence
项来决定的。
-
View controller-based status bar appearence
项设为YES,则viewController对状态栏的设置优先级高于application
对状态栏的设置,具体的代码为:
- 在
viewWillAppear
或viewDidAppear
中添加代码:
if ([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) {
[self prefersStatusBarHidden];
[self performSelector:@selector(setNeedsStatusBarAppearanceUpdate)];
}
- 覆盖
viewController
的prefersStatusBarHidden
方法的实现,返回YES:
- (BOOL)prefersStatusBarHidden {
return YES;
}
-
View controller-based status bar appearence
项设为NO,则application
对状态栏的设置优先级高于viewController
对状态栏的设置,viewController
对状态栏的设置无效,具体的代码为:
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:NO] ;
- 建议使用第一种方法。因为第一种方法之影响当前viewController,而第二种方法则影响整个应用。iOS9.0后第二种方法已经被弃用。
隐藏tableView底部多余的分割线
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero] ;
tableView带有动画效果的刷新
通常刷新UITableView
采用的是[self.tableView reloadData]
,但是这种刷新方式没有动画效果,目前有两种方式,一种是系统提供的,另一种是自定义的。
- 系统提供的方式
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation ;
- (void)reloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation ;
对于方法1,如果UITableView
的样式为UITableViewStylePlain
,则可以通过[NSIndexSet indexSetWithIndex:0]
生成相应的sections
;如果UITableView
的样式为UITableViewStyleGrouped
,则可以通过[NSIndexSet indexSetWithIndex:section]生成相应的sections
。
- 自定义方式
在cell
中自定义动画显示方式,并且在UITableView
的代理方法- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
实现中适时调用。
NSString使用stringWithFormat的小技巧
- 保留2位小数
NSString *string = [NSString stringWithFormat:@"%.2f",M_PI] ;
- 用0补全
NSString *string = [NSString stringWithFormat:@"%02d",5] ;
- 包含特殊符号%
NSString *string = [NSString stringWithFormat:@"%d%%",5] ;
- 包含特殊符号"
NSString *string = [NSString stringWithFormat:@"%d%\"",5] ;
Button禁止触摸事件的2种方式
- 会改变按钮的状态
button.enable = NO ;
- 不会改变按钮的状态
button.userInteractionEnabled = NO ;
忽略备份文件
+ (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *) filePathString {
NSURL* fileURL= [NSURL fileURLWithPath: filePathString];
assert([[NSFileManager defaultManager] fileExistsAtPath: [fileURL path]]) ;
NSError *error = nil ;
BOOL success = [fileURL setResourceValue: [NSNumber numberWithBool: YES] forKey: NSURLIsExcludedFromBackupKey error: &error] ;
return success;
}
通过图片Data数据第一个字节来获取图片扩展名
- (NSString *)contentTypeForImageData:(NSData *)data {
uint8_t c;
[data getBytes:&c length:1];
switch (c) {
case 0xFF:
return @"jpeg";
case 0x89:
return @"png";
case 0x47:
return @"gif";
case 0x49:
case 0x4D:
return @"tiff";
case 0x52:
if ([data length] < 12) {
return nil;
}
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
return @"webp";
}
return nil;
}
return nil;
}
##在宏中的使用
在宏中,##
起连接的作用
#define weakSelf(type) __weak typeof(type) weak##type = type;
上述宏会把weak
和type
连接起来。
数组排序
- 简单排序
声明:
- (NSArray<objectType>*)sortedArrayUsingSelector:(SEL)comparator
使用:
//在自定义类中添加比较方法
- (NSComparisonResult)compare:(Person *)otherObject {
return [self.birthDate compare:otherObject.birthDate] ;
}
NSArray *sortedArray = [persons sortedArrayUsingSelector:@selector(compare:)] ;
- block语法
声明:
- (NSArray<objectType>*)sortedArrayUsingComparator:(NSComparator)cmptr
- (void)sortUsingComparator:(NSComparator)cmptr
使用:
NSArray *sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSDate *first = [(Person*)a birthDate] ;
NSDate *second = [(Person*)b birthDate] ;
return [first compare:second];
}] ;
- 高级排序
声明:
-(NSArray<ObjectType>*)sortedArrayUsingDescriptors:(NSArray<NSSortDescriptor *> *)sortDescriptors
参数:
NSSortDescriptor
对象可以通过NSSortDescriptor
的+(instancetype)sortDescriptorWithKey:(nullable NSString *)key ascending:(BOOL)ascending
方法获得。
使用:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate" ascending:YES] ;
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor] ;
NSArray *sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors] ;
- 相关常用方法
- (NSComparisonResult)compare:(NSString *)aString options:(NSStringCompareOptions)mask
typedef NS_OPTIONS (NSUInteger, NSStringCompareOptions)
{
NSCaseInsensitiveSearch,//不区分大小写
NSLiteralSearch,//逐字节比较,区分大小写(大写在前)
NSNumericSearch,//含数字时整体比较数字
}
图片拉伸
iOS 5.0之前
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;
- 功能:该方法是
UIImage
的一个实例方法,用来创建一个整体拉伸而指定区域不拉伸的UIImage
对象 - 参数:
-
leftCapWidth
:左边不拉伸区域的宽度 -
topCapHeight
:上方不拉伸区域的高度
-
- 注意:
- 根据设置的宽度和高度,将接下来的一个像素进行左右扩展和上下拉伸
- 进行拉伸的是距离
UIImage
对象左边沿leftCapWidth+1
处的一竖排像素和距离UIImage
对象上边沿topCapHeight+1
处的一横排像素 - 只是对一个像素进行复制拉伸,后面剩余的像素也不会拉伸
- 举例:
UIImage *normalImg = [UIImage imageNamed:@"img_bg_n_red"] ;
UIImageView *bgImageView = [[UIImageView alloc] initWithImage:[normalImg stretchableImageWithLeftCapWidth:floorf(normalImg.size.width * 0.5) topCapHeight:(normalImg.size.height * 0.5)]] ;
iOS 5.0
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets;
功能:该方法是
UIImage
的一个实例方法,用来创建一个整体拉伸而指定区域不拉伸的UIImage
对象-
参数:
capInsets
的top,left,bottom,right
分别指定上、左、下、右四个距离,具体如下图所示:
注意:拉伸部分如下图所示:
iOS 6.0
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode;
具体的与上一个方法的一致,只是多了一个参数resizingMode
来指定拉伸模式
模式 | 说明 |
---|---|
UIImageResizingModeStretch | 拉伸模式,通过拉伸来填充图片 |
UIImageResizingModeTile | 平铺模式,通过重复显示来填充图片 |
根据颜色和尺寸绘制图片
+ (UIImage *)imageFromColor:(UIColor *)color size:(CGSize)size {
CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height) ;
UIGraphicsBeginImageContext(rect.size) ;
CGContextRef context = UIGraphicsGetCurrentContext() ;
CGContextSetFillColorWithColor(context, [color CGColor]) ;
CGContextFillRect(context, rect) ;
UIImage *image = UIGraphicsGetImageFromCurrentImageContext() ;
UIGraphicsEndImageContext() ;
return image;
}
根据图片和指定大小生成平铺的图片
- (UIImage *)spreadImage:(UIImage *)image WithSize:(CGSize)size {
UIView *tempView = [[UIView alloc] init] ;
tempView.bounds = (CGRect){CGPointZero, size} ;
tempView.backgroundColor = [UIColor colorWithPatternImage:image] ;
UIGraphicsBeginImageContext(size) ;
[tempView.layer renderInContext:UIGraphicsGetCurrentContext()] ;
UIImage *bgImage = UIGraphicsGetImageFromCurrentImageContext() ;
UIGraphicsEndImageContext() ;
return bgImage ;
}
UIButton标题文字居左
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
button.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
裁剪圆形图片
- 不带边框
+ (nullable UIImage *)clipCircleImageWithImage:(nullable UIImage *)image {
//1、开启上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0) ;
//2、设置裁剪区域
UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect:(CGRect){CGPointZero, image.size}] ;
[path addClip] ;
//3、绘制图片
[image drawAtPoint:CGPointZero] ;
/*
//2、设置裁剪区域
CGContextRef ctx = UIGraphicsGetCurrentContext() ;
CGFloat radius = image.size.width/2.0 ;
CGContextAddArc(ctx, radius, radius, radius, 0, M_PI * 2, 0) ;
CGContextClip(ctx) ;
//3、绘制图片
[image drawInRect:(CGRect){CGPointZero, image.size}] ;
*/
//4、获取新图片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//5、关闭上下文
UIGraphicsEndImageContext();
//6、返回新图片
return newImage;
}
- 带边框
+ (nullable UIImage *)clipCircleImageWithImage:(nullable UIImage *)image circleRect:(CGRect)rect borderWidth:(CGFloat)borderW borderColor:(nullable UIColor *)borderColor {
//1:开启上下文
UIGraphicsBeginImageContext(image.size) ;
//2:设置边框
UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect:rect] ;
[borderColor setFill] ;
[path fill] ;
//3:设置裁剪区域
UIBezierPath * clipPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(rect.origin.x + borderW , rect.origin.y + borderW , rect.size.width - borderW * 2, rect.size.height - borderW *2)];
[clipPath addClip];
//4:绘制图片
[image drawAtPoint:CGPointZero];
//5:获取新图片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//6:关闭上下文
UIGraphicsEndImageContext();
//7:返回新图片
return newImage;
}
tablviewCell中添加scrollView后点击手势冲突
scrollView.userInteractionEnabled = NO ;
[self.contentView addSubview:scrollView] ;
[self.contentView addGestureRecognizer:scrollView.panGestureRecognizer] ;
小数NSNumber转换成NSString
NSNumber *num = @(8.30) ;
NSString *str = [NSString stringWithFormat:@"%lf", [num floatValue]];
NSDecimalNumber *num1 = [NSDecimalNumber decimalNumberWithString:str];
NSString *str1 = [num1 stringValue];
设置图片透明度
- (UIImage *)imageByApplyingAlpha:(CGFloat)alpha image:(UIImage*)image {
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0f);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGRect area = CGRectMake(0, 0, image.size.width, image.size.height);
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -area.size.height);
CGContextSetBlendMode(ctx, kCGBlendModeMultiply);
CGContextSetAlpha(ctx, alpha);
CGContextDrawImage(ctx, area, image.CGImage);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}