[TOC]
###iOS10 AVPlayer有时播放失败的处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| //如果你的视频使用的是HLS(m3u8)协议的,是不会由于升级ios10出现这个播放问题的。 如果不是基于HLS协议的,解决方法如下 if([[UIDevice currentDevice] systemVersion].intValue>=10){ // 增加下面这行可以解决iOS10兼容性问题了 self.player.automaticallyWaitsToMinimizeStalling = NO; }
/*ios10中AVPlayer增加了多个属性,其中有几个需要注意一下 1、timeControlStatus 2、automaticallyWaitsToMinimizeStalling 正是第二个属性的默认值导致了不使用HLS的方式(比如使用localhttpserver间接实现在线播放、或者下载到本地再播放的方式)就会播放不了的问题。 */
//在之前的版本中,我们通过rate来判断avplayer是否处于播放中 - (Boolean)isPlaying { return self.player.rate==1; }
//在iOS10中,AVPlayer多了一个timeControlStatus,我们就应该这么实现 - (Boolean)isPlaying { if([[UIDevice currentDevice] systemVersion].intValue>=10){ return self.player.timeControlStatus == AVPlayerTimeControlStatusPlaying; }else{ return self.player.rate==1; } }
|
字符串去除空格
1 2 3 4 5 6 7
| //去除首尾空格: NSString * content = [textView.text stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
//去除首尾空格和换行: NSString *content = [textView.text stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
控制器禁用左侧手势返回功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| //关闭手势返回 - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; // 禁用返回手势 if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) { self.navigationController.interactivePopGestureRecognizer.enabled = NO; } } //重新开启手势返回 - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; // 开启返回手势 if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) { self.navigationController.interactivePopGestureRecognizer.enabled = YES; } }
|
UIView 视频全屏 masonry 约束设置
1 2 3 4 5 6 7 8 9 10 11
| UIView *player = [[UIView alloc] init]; [self.view addSubview:player];
CGFloat wid = [UIScreen mainScreen].bounds.size.width; CGFloat hei = [UIScreen mainScreen].bounds.size.height; CGFloat rate = wid < hei ? (wid/hei) : (hei/wid); [player mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view); make.left.right.equalTo(self.view); make.height.mas_equalTo(player.mas_width).multipliedBy(rate); }];
|
Masonry实现动画更新约束
1 2 3 4 5 6 7 8
| // 告诉self.view约束需要更新 [self.view setNeedsUpdateConstraints]; // 调用此方法告诉self.view检测是否需要更新约束,若需要则更新,下面添加动画效果才起作用 [self.view updateConstraintsIfNeeded];
[UIView animateWithDuration:0.3 animations:^{ [self.view layoutIfNeeded]; }];
|
UISlider更改进度条的粗细 、修改圆点位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| //需要重写UISlider的trackRectForBounds 方法 - (CGRect)trackRectForBounds:(CGRect)bounds { bounds.origin.y = bounds.size.height / 2.0 - 2; bounds.size.height = 4; return bounds; }
//小圆点Rect修改 - (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value { rect.origin.x = rect.origin.x - 3 ; rect.size.width = rect.size.width +6; return [super thumbRectForBounds:bounds trackRect:rect value:value]; }
|
iOS获取View所在的控制器、导航控制器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| //获取控制器 - (UIViewController*)viewController { for (UIView* next = [self superview]; next; next = next.superview) { UIResponder* nextResponder = [next nextResponder]; if ([nextResponder isKindOfClass:[UINavigationController class]]) { return (UIViewController*)nextResponder; } } return nil; }
//获取导航控制器 - (UINavigationController*)navigationController { for (UIView* next = [self superview]; next; next = next.superview) { UIResponder* nextResponder = [next nextResponder]; if ([nextResponder isKindOfClass:[UINavigationController class]]) { return (UINavigationController*)nextResponder; } } return nil; }
|
UILabel 设置行间距
1 2 3 4 5 6 7 8 9 10 11 12 13
| - (NSAttributedString *)getParagraphText:(NSString*)text LineSpacing:(CGFloat)spacing{ if(text == nil || text.length == 0){ return nil; } NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc]initWithString:text];; NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc]init]; [paragraphStyle setLineSpacing:spacing]; [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, text.length)]; return attributedString; }
//使用 self.titleLabel.attributedText = [self getParagraphText:infModel.title LineSpacing:7];
|
UIView获取父控制器/父导航控制器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| //创建UIView的分类 //获取当前控制器 - (UIViewController *)getCurrentVC { UIResponder *next = self.nextResponder; do { //判断响应者是否为视图控制器 if ([next isKindOfClass:[UIViewController class]]) { return (UIViewController *)next; } next = next.nextResponder; } while (next != nil); return nil; }
//获取导航控制器 - (UINavigationController *)getCurrentNavVC { UIResponder *next = self.nextResponder; do { //判断响应者是否为视图控制器 if ([next isKindOfClass:[UINavigationController class]]) { return (UINavigationController *)next; } next = next.nextResponder; } while (next != nil); return nil; }
|
拉伸图片
1 2 3 4 5 6 7 8 9 10 11
| //拉伸图片 + (UIImage *)resizedImageWithName:(NSString *)name { return [self resizedImageWithName:name left:0.5 top:0.5]; }
+ (UIImage *)resizedImageWithName:(NSString *)name left:(CGFloat)left top:(CGFloat)top { UIImage *image = [UIImage imageNamed:name]; return [image stretchableImageWithLeftCapWidth:image.size.width * left topCapHeight:image.size.height * top]; }
|
判断当前控制器是push 还是present
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| //方法一 - (IBAction)dismiss:(id)sender { if (self.presentingViewController) { [self dismissViewControllerAnimated:YES completion:nil]; } else { [self.navigationController popViewControllerAnimated:YES]; } }
//方法二 - (IBAction)dismiss:(id)sender { if (self.navigationController.topViewController == self) { [self.navigationController popViewControllerAnimated:YES]; } else { [self dismissViewControllerAnimated:YES completion:nil]; } }
|
导航栏全透明 、去除黑线
1 2 3
| [self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; [self.navigationController.navigationBar setShadowImage:[UIImage new]];
|
获取文字字符数(汉字两个其他1个)
1 2 3 4 5 6
| //返回字符个数 汉字两个字符 - (NSInteger)getStrLength:(NSString*)strtemp { NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000); NSData* da = [strtemp dataUsingEncoding:enc]; return [da length]; }
|
判断iPhone尺寸
1 2 3 4 5
| #define iPhone4Size (CGSizeEqualToSize(CGSizeMake(320, 480), [[UIScreen mainScreen] bounds].size)) #define iPhone5Size (CGSizeEqualToSize(CGSizeMake(320, 568), [[UIScreen mainScreen] bounds].size)) #define iPhone6Size (CGSizeEqualToSize(CGSizeMake(375, 667), [[UIScreen mainScreen] bounds].size)) #define iPhone6PlusSize (CGSizeEqualToSize(CGSizeMake(414,736), [[UIScreen mainScreen] bounds].size))
|
直播聊天列表的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| - (void) addMessageWithStr:(NSString *)str { __weak typeof(self) weakSelf = self; if ([NSThread isMainThread]) { dispatch_async(dispatch_get_global_queue(0, 0), ^{ [weakSelf insertChatView:str]; }); } else { [self insertChatView:str]; } }
- (void)insertChatView:(NSString *)str { dispatch_sync(dispatch_get_main_queue(), ^{ if (self.array.count > 50) { for (int i = 0; i< 20; i++) { [_array removeObjectAtIndex:i]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0]; [self.tableView beginUpdates]; [_tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; [self.tableView endUpdates]; NSInteger row = self.array.count>0 ? (self.array.count -1): 0 ; NSIndexPath *inde = [NSIndexPath indexPathForRow:row inSection:0]; [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:inde.row inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; } } [_array addObject:str]; NSInteger row = self.array.count>0 ? (self.array.count -1): 0 ; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:0]; [self.tableView beginUpdates]; [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; [self.tableView endUpdates]; if (indexPath.row >0) { [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES]; } });
}
|
全屏幕拖动返回简单实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| viewDidLoad方法中添加 //1.获取系统右滑手势对应的 target 和 action //1.1 获取系统右滑返回手势 guard let systemGesture = interactivePopGestureRecognizer else { return } //1.2获取手势对应的 target-action 对象 let targets = systemGesture.value(forKey: "_targets") as? [NSObject] guard let targetObjc = targets?.first else { return } //1.3获取target guard let target = targetObjc.value(forKey: "target") else { return } //1.4获取action let action = Selector(("handleNavigationTransition:")) //2.创建自定义手势,并赋值 target, action let customGesture = UIPanGestureRecognizer() customGesture.addTarget(target, action: action) //3.将自定义手势添加到系统手势的view上 guard let gestureView = systemGesture.view else { return } gestureView.addGestureRecognizer(customGesture)
|
导航栏隐藏显示
1 2 3 4 5 6 7 8 9 10
| - (void)viewWillAppear:(BOOL)animated { [self.navigationController setNavigationBarHidden:NO animated:animated]; [super viewWillAppear:animated]; }
- (void)viewWillDisappear:(BOOL)animated { [self.navigationController setNavigationBarHidden:YES animated:animated]; [super viewWillDisappear:animated]; }
|
iOS TableView reloadData闪动的问题
1 2 3 4 5 6 7
| 解决方法:
//在iOS 11 Self-Sizing自动打开后,contentSize和contentOffset都可能发生改变。可以通过以下方式禁用
self.estimatedRowHeight = 0; self.estimatedSectionHeaderHeight = 0; self.estimatedSectionFooterHeight = 0;
|
避免父view视图手势影响
1 2 3 4 5 6 7 8 9 10
| //设置手势代理 tap.delegate = self;
//实现代理方法 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if ([touch.view isDescendantOfView:self.alertView]) { return NO; } return YES; }
|
1 2 3 4 5 6 7 8
| //scrollview contentSize的处理 - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; [self.scrollView layoutIfNeeded]; [self.view layoutIfNeeded]; self.scrollView.contentSize = CGSizeMake(0, self.rewardView.bottom + 80 * 5 + 100 +20); }
|
presentViewController后view 透明效果设置
1 2 3 4 5 6
| if ([[[UIDevice currentDevice] systemVersion] floatValue]>=8.0) { VC.modalPresentationStyle = UIModalPresentationOverCurrentContext; }else{ VC.modalPresentationStyle = UIModalPresentationCurrentContext; } [controller presentViewController:vC animated:NO completion:nil];
|
AlertView动画效果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| - (void)animationAlert:(UIView *)view { CAKeyframeAnimation *popAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; popAnimation.duration = 0.4; popAnimation.removedOnCompletion = NO; popAnimation.fillMode = kCAFillModeForwards; popAnimation.values = @[[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.01f, 0.01f, 1.0f)], [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.1f, 1.1f, 1.0f)], [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.9f, 0.9f, 1.0f)], [NSValue valueWithCATransform3D:CATransform3DIdentity]]; popAnimation.keyTimes = @[@0.0f, @0.5f, @0.75f, @1.0f]; popAnimation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]]; [view.layer addAnimation:popAnimation forKey:nil]; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| /**UIScrollview 内部包含 slider引起的手势冲突 重写scrollview 继承自UIScrollview 重写下面方法 参考https://blog.csdn.net/findhappy117/article/details/82781071 */ - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { /* 直接拖动UISlider,此时touch时间在150ms以内,UIScrollView会认为是拖动自己,从而拦截了event,导致UISlider接受不到滑动的event。但是只要按住UISlider一会再拖动,此时此时touch时间超过150ms,因此滑动的event会发送到UISlider上。 */ UIView *view = [super hitTest:point withEvent:event]; if([view isKindOfClass:[UISlider class]]) { //如果接收事件view是UISlider,则scrollview禁止响应滑动 self.scrollEnabled = NO; } else { //如果不是,则恢复滑动 self.scrollEnabled = YES; } return view; }
|
获取当前正在展示的控制器
1 2 3 4 5 6 7 8 9 10
| //UITabBarController + UINavigationController UIWindow *window = [UIApplication sharedApplication].delegate.window; UIViewController *vc = window.rootViewController; UIViewController *result = nil; if ([vc isKindOfClass:[UITabBarController class]]) { UITabBarController *tabbar = (UITabBarController *)vc; result = [tabbar selectedViewController]; //UINavigationController result = [result.childViewControllers lastObject];//UINavigationController所嵌套的控制器 }
|