一、强制屏幕旋转
在很多情况下,我们并不希望在手机屏幕未锁定的情况下当手机旋转的时候页面也跟着一起旋转,最简单的方法是将Controller里的代理设置为NO
- (BOOL)shouldAutorotate
{
return NO;
}
这样可以禁止屏幕的自动旋转。但是在有些场景下,我们需要在不允许自动转屏的页面进行全屏的操作,这个时候就要用到强制全屏的操作。
/** 全屏 */
- (void)_fullScreenAction
{
_couludRound = YES;
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
UIInterfaceOrientation interfaceOrientation = (UIInterfaceOrientation)orientation;
switch (interfaceOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:{
[self interfaceOrientation:UIInterfaceOrientationLandscapeRight];
}
break;
case UIInterfaceOrientationPortrait:{
[self interfaceOrientation:UIInterfaceOrientationLandscapeRight];
}
break;
case UIInterfaceOrientationLandscapeLeft:{
[self interfaceOrientation:UIInterfaceOrientationPortrait];
}
break;
case UIInterfaceOrientationLandscapeRight:{
[self interfaceOrientation:UIInterfaceOrientationPortrait];
}
break;
default: {
[self interfaceOrientation:UIInterfaceOrientationPortrait];
}
break;
}
}
/**
- 强制屏幕转屏
- @param orientation 屏幕方向
*/
-
(void)interfaceOrientation:(UIInterfaceOrientation)orientation
{
[[NSNotificationCenter defaultCenter] postNotificationName:@"Could_Round_Screen" object:nil];
// arc下
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
SEL selector = NSSelectorFromString(@"setOrientation:");
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
[invocation setSelector:selector];
[invocation setTarget:[UIDevice currentDevice]];
int val = orientation;
// 从2开始是因为0 1 两个参数已经被selector和target占用
[invocation setArgument:&val atIndex:2];
[invocation invoke];
}BOOL orientationIsLandscapeIsLandscape = (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown);
if (orientationIsLandscapeIsLandscape) {
self.isFullScreen = NO;
}else{
self.isFullScreen = YES;
}
_couludRound = NO;
}
调用_fullScreenAction方法即可实现全屏。
当设备发生旋转的时候,设备会回调supportedInterfaceOrientations代理方法来确认可以旋转的方向,因为我们不允许旋转,所以在全屏和非全屏的状态下,我们返回了不同但是唯一的状态值,来控制页面的方向。
调用强制全屏的时候,设备也会回调supportedInterfaceOrientations代理方法来确认可以旋转的方向,我在次设置了_couludRound和_isFullScreen两个阈值来控制设备应该往哪个方向旋转。
这样就实现了在不允许自动旋转的页面强制进行屏幕旋转的功能。
二、强制屏幕旋转容易闪退的地方
当前controller的将要被显示出来的时候,他的preferredInterfaceOrientationForPresentation代理方法回被回调,接着回再去回调supportedInterfaceOrientations代理方法,如果preferredInterfaceOrientationForPresentation代理方法的返回值不包含在supportedInterfaceOrientations的方法返回值内,那么就会出现闪退的情况。这个地方很重要,但是却很容易被忽略。所以我们使用了两个阀值来确保这两个方法的返回值对应一定是没问题的。
// 支持哪些转屏方向 -
(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
if (_couludRound) {
return UIInterfaceOrientationMaskAllButUpsideDown;
}else if(_isFullScreen){
return UIInterfaceOrientationMaskLandscape;
}else{
return UIInterfaceOrientationMaskPortrait;
}
} -
(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
if (_isFullScreen) {
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
UIInterfaceOrientation interfaceOrientation = (UIInterfaceOrientation)orientation;
if (interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
return UIInterfaceOrientationLandscapeRight;
}else{
return UIInterfaceOrientationLandscapeLeft;
}
}else{
return UIInterfaceOrientationPortrait;
}
}
三、高并发聊天性能优化
1.数据加载的优化
因为正常情况下,APP里不会出现一秒钟要处理几千条列表数据的情况,而且在数据未加载出来的时候,页面是空白的用户操作也没有意义,所以一般情况下我们会在主线程去接收从异步数据处理线程处理好的数据,并在页面显示出来。但是在直播回放的时候,会遇到进度条一拖动,立刻接收到六七千条数据的情况,所以这里就要做单独优化处理,否则当聊天人数过多或者回放拖动的时候,页面会形成卡顿。处理的方法是将接收数据的操作也放在子线程里,保证主线程不受任何影响,当在子线程里将数据格式化好之后,再回到主线程将数据刷新在页面上。
2.动态计算页面高度的优化
列表页面还有一个性能占用过高的地方是列表高度的计算,因为Ios没有高度自适应的机制,所以要显示的列表数据都是要提前计算好要显示的内容高度然后返还给列表高度获取代理。在我们处理数据的时候,会在本地创建一个Dictionary来缓存每个列表内容的高度,key是数据的id,value是这个id的高度数据,把对高度的计算放在子线程处理列表数据的时候,而不是在列表滑动将要显示出来内容的时候。当列表滑动的时候,在高度代理方法里通过消息的ID匹配Dictionary里的key来获取计算好的高度并返回,如果有未缓存的高度,那么就计算并缓存下来,这样就保证了列表滑动的顺滑体验。
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
BJLMessage message = self.messages[indexPath.row];
NSNumber heigt = [self.heightCatch valueForKey:[NSString stringWithFormat:@"msgID:%@",message.ID]];
if ([heigt floatValue] <= 0) {
BMWLivingChatCell cell = (BMWLivingChatCell)[self tableView:self.messageTV cellForRowAtIndexPath:indexPath];
heigt = @([cell getHeight]);
[self.heightCatch setValue:heigt forKey:[NSString stringWithFormat:@"msgID:%@",message.ID]];
}
return [heigt floatValue];
}
网友评论