【问题标题】:iOS8 scale glitch when calling drawViewHierarchyInRect afterScreenUpdates:YESiOS8 在屏幕更新后调用 drawViewHierarchyInRect 时出现缩放故障:YES
【发布时间】:2015-09-22 10:33:12
【问题描述】:

我正在将一个项目从 iOS7 转换为 iOS8,该项目使用自定义转换,需要在完成加载 afterScreenUpdates:YES 后捕获模态,并且看到整个屏幕放大一秒钟并缩小。在 iOS8 上转换为照片时,我还在适用于 iOS 的 Flickr 应用程序的部分之间和 Yelp 应用程序中看到了这种情况。

  UIGraphicsBeginImageContextWithOptions(self.view.frame.size, YES, 22.0); 
  [self.view drawViewHierarchyInRect:self.view.frame afterScreenUpdates:YES];
  UIGraphicsEndImageContext();

添加更大的比例因子有助于更加强调故障......但我只是在示例中按下按钮时调用它。

编辑这似乎发生在 iPhone 6 和 6 plus 上,而不是 5。

Sample project github

【问题讨论】:

  • [view.layer renderInContext:UIGraphicsGetCurrentContext()]; 目前是一种解决方法,但最好不要使用 ios6 和更旧的方式
  • 几乎所有在 iPhone 6 和 6 Plus 上运行的 iPhone 6 之前的设备都会出现这种情况。绝对是关于屏幕尺寸/分辨率/图形上下文/比例因子的 UIKit 错误。
  • 如果我在模拟器中关闭缩放(通过提供 6 和 6+ 启动图像),我看不到这个错误。看起来像是 iOS 缩放应用程序以适应屏幕的方式中的一个错误。
  • 我也有同样的问题
  • 在 ios 8.1.3 中仍然存在问题

标签: ios ios8 screenshot


【解决方案1】:

屏幕更新后你需要它来绘制吗?因为我正在使用:

[view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO];

它似乎在 iOS7 和 iOS8 上运行良好。我想这不是定期捕获图像的好解决方案(例如每秒多次),但它似乎适用于一次性模糊。

【讨论】:

    【解决方案2】:

    您必须为 6 和 6 plus 提供 @3x 启动图像。 6 被缩放为 750x1334,6 plus 图像被缩放为 1242x2208。

    【讨论】:

    • 这确实解决了问题。
    【解决方案3】:

    即使它看起来像 API 中的错误,您也可以调用 drawViewHierarchyInRect 并将 afterScreenUpdates 设置为 NO 如果您使用这样的 cunstruction 来构建屏幕更新后的快照:

    typedef void (^CompletionHandlerWithId)(id result);
    
    -(void)imageContaining:(CGRect)rect afterScreenUpdates:(bool)afterScreenUpdates opaque:(BOOL)opaque completion:(CompletionHandlerWithId)completion
    {
        bool success __block;
        UIImage *snapshotImage __block = nil;
    
        CompletionHandler block = ^{
    
            // Create the image
            UIGraphicsBeginImageContextWithOptions(self.bounds.size, opaque, [[UIScreen mainScreen] scale]);
    
            success = [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:NO];
    
            if (success)
            {
                snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
    
                CGImageRef imageRef = CGImageCreateWithImageInRect(
                                       [snapshotImage CGImage],
                                       CGRectMake(
                                              snapshotImage.scale*rect.origin.x,
                                              snapshotImage.scale*rect.origin.y,
                                              snapshotImage.scale*rect.size.width,
                                              snapshotImage.scale*rect.size.height));
    
                // or use the UIImage wherever you like
                snapshotImage = [UIImage imageWithCGImage:imageRef scale:snapshotImage.scale orientation:UIImageOrientationUp];
    
                CGImageRelease(imageRef);
            }
    
            UIGraphicsEndImageContext();
    
            if (completion)
            {
                if (! success)
                {
                    NSLog(@"Error: [UIView drawViewHierarchyInRect] failed on %@", self);
    
                    (completion)(nil);
                }
                else
                {
                    NSLog(@"Success: [UIView drawViewHierarchyInRect] on %@", self);
    
                    (completion)(snapshotImage);
                }
            }
        };
    
        if (afterScreenUpdates)
    
            [CATransaction setCompletionBlock:^{
                (block)();
            }];
    
        else
    
            (block)();
    }    
    

    【讨论】:

      【解决方案4】:

      当您在运行 iOS7 的 iPad2 上运行时,也会存在此错误。

      修复:将 afterScreenUpdates: 设置为 NO

      我的应用有一些移动的 UIButtons,所以在移动停止之前我不允许模糊过渡。据我到目前为止发现,YES或NO没有区别。

      【讨论】:

        【解决方案5】:

        似乎在 iOS9 / XCODE 7 版本中已修复

        【讨论】:

          【解决方案6】:

          我找到了解决这个问题的方法。

          我将@3x 启动图像添加到我的项目中。并选择启动屏幕文件到“主要”。 这将使应用程序以原始分辨率运行,在 iphone6 上运行时边界更小,但在调用 drawViewHierarchyInRect 时不会出现故障。 Like this.

          然后,在 viewDidLoad 时将我的视图缩放到全屏。

          - (void)viewDidLoad{ 
                 [super viewDidLoad];
                 UIScreen *mainScreen = [UIScreen mainScreen];
                 CGRect tempFrame=mainScreen.bounds;
                 double aspect=tempFrame.size.width/320;
                 self.view.transform = CGAffineTransformScale(CGAffineTransformIdentity, aspect, aspect);
          }
          

          希望有帮助:)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-01-01
            • 2022-06-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-04-09
            • 1970-01-01
            • 2014-04-22
            相关资源
            最近更新 更多