iOSスクリーンショットについてあなたが知っているべきことについて


前言
ホームボタンと電源ボタンを同時に押して、ガチャンと音をたてたら携帯のスクリーンショットを手に入れました。この操作はきっとiPhoneのユーザーはもっと詳しいと思います。私達は研究開発者として、一つ一つのViewに直面していますが、コードでViewをスクリーンショットするにはどうすればいいですか?
この記事では主にUICbViewとWKWebViewを含むウェブページでどのように長いスクリーンショットを行うかを議論しています。対応するコードの例はここにあります。https://github.com/VernonVan/PPSnapshotKit。 ( ローカルダウンロード
UICWebViewのスクリーンショット
UICWebViewのスクリーンショットは比較的簡単で、rendeInContextはこの方法はみんながよく知らないと信じています。この方法はCALayerの実例的な方法で、ほとんどのViewをスクリーンショットするために使用できます。UICWebViewのベアラ内容は実はその子ViewであるUICScrrollViewであることを知っていますので、UICWebViewのスクリーンショットはそのscrollViewをスクリーンショットするべきです。具体的なスクリーンショットの方法は以下の通りです。

- (void)snapshotForScrollView:(UIScrollView *)scrollView
{
 // 1.      scrollView       
 CGPoint currentOffset = scrollView.contentOffset;
 CGRect currentFrame = scrollView.frame;

 scrollView.contentOffset = CGPointZero;
 // 2.   scrollView            
 scrollView.frame = CGRectMake(0, 0, scrollView.contentSize.width, scrollView.contentSize.height);

 // 3.          0               
 UIGraphicsBeginImageContextWithOptions(scrollView.contentSize, YES, 0);
 [scrollView.layer renderInContext:UIGraphicsGetCurrentContext()];
 UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
 UIGraphicsEndImageContext();
 
 // 4.      scrollView       ,    
 scrollView.contentOffset = currentOffset;
 scrollView.frame = currentFrame;
}
WKWebViewのスクリーンショット
WKWebViewにもscrollViewがありますが、直接にこのscrollViewのスクリーンショットに対して得られたのは空白で、具体的な原因は不明です。Googleの後には多くの人がdrawView HurarchyInRect方法に言及していますが、この方法はiOS 7.0から導入されたものと見られます。公式文書では次のように記述されています。
Renders a snapshot of the complete view hierarch as visible onscreen into the current context.
その中のvisible onscreen、つまり画面の可視部分をコンテキストに描画するということは、WKWebViewの中のscrollViewに対して実際のコンテンツサイズに展開する理由を説明しています。また、drawViewHurarchyInRect方法を呼び出して、いつも不完全なスクリーンショットが得られます。
しかし、このようにして、WKWebViewを画面の高さに応じてnページに切り、WKWebViewのページを1ページずつ上に押し上げることができます。ページを押すたびに、drawViewerschyInRectを呼び出して、現在のスクリーンのスクリーンショットを文脈に描画します。最後にUGraphics GetImageFroom CurrenntImageContextを呼び出してコンテキストから取得した画像は完全スクリーンショットです。
コアコードは以下の通りです。 ( ここです)表示:

- (void)snapshotForWKWebView:(WKWebView *)webView
{
 // 1
 UIView *snapshotView = [webView snapshotViewAfterScreenUpdates:YES];
 [webView.superview addSubview:snapshotView];

 // 2
 CGPoint currentOffset = webView.scrollView.contentOffset;
 ...

 // 3
 UIView *containerView = [[UIView alloc] initWithFrame:webView.bounds];
 [webView removeFromSuperview];
 [containerView addSubview:webView];

 
 // 4
 CGSize totalSize = webView.scrollView.contentSize;
 NSInteger page = ceil(totalSize.height / containerView.bounds.size.height);

 webView.scrollView.contentOffset = CGPointZero;
 webView.frame = CGRectMake(0, 0, containerView.bounds.size.width, webView.scrollView.contentSize.height);

 UIGraphicsBeginImageContextWithOptions(totalSize, YES, UIScreen.mainScreen.scale);
 [self drawContentPage:0 maxIndex:page completion:^{
  UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();

  // 8
  [webView removeFromSuperview];
  ...
 }];
}

- (void)drawContentPage(NSInteger)index maxIndex:(NSInteger)maxIndex completion:(dispatch_block_t)completion
{
 // 5
 CGRect splitFrame = CGRectMake(0, index * CGRectGetHeight(containerView.bounds), containerView.bounds.size.width, containerView.frame.size.height);
 CGRect myFrame = webView.frame;
 myFrame.origin.y = -(index * containerView.frame.size.height);
 webView.frame = myFrame;

 // 6
 [targetView drawViewHierarchyInRect:splitFrame afterScreenUpdates:YES];

 // 7
 if (index < maxIndex) {
  [self drawContentPage:index + 1 maxIndex:maxIndex completion:completion];
 } else {
  completion();
 }
}
コードの注意事項は以下の通りです。
  • は図を切り取る時にframeを操作してフラッシュスクリーンなどの現象が現れないようにするために、私達は「偽」のwebViewを現在の位置にかぶせて、本物のwebViewを「摘む」必要があります。snapshotView AfterSreenUpdatesを呼び出すと、このような「偽」のwebView
  • が得られます。
  • は、スクリーンショットが完了したら「復元現場」
  • になるように、本物のwebViewのオフセット、位置などの情報を保存する。
  • は、新しいビューで「本物」のwebViewを運んでいます。このビューも描画に使用されるコンテキスト
  • です。
  • は、webViewを実際のコンテンツの高さと画面の高さによって、ページ
  • に分割する。
  • は各ページの実際の位置を得て、webViewを上にしてこの位置
  • に押し上げます。
  • は、drawView HurarchyInRectを呼び出して、現在位置のwebViewをコンテキスト
  • にレンダリングする。
  • 最後のページにまだ到達していない場合、再度、DRawVieHerarchyInRect方法を呼び出してレンダリングする。全ページをレンダリングし終わったら、再度通知スクリーンショットが完成します。
  • UGraphics GetImageFroom Current ImageContext方法を起動し、現在のコンテキストから完全なスクリーンショットを取得し、第2ステップで保存された情報をwebViewに再付与し、「復元現場」

  • 注意:私達のスクリーンショットの方法にはwebViewのframeを操作していますが、他のところにframeを操作するとスクリーンショットに影響があります。したがって、スクリーンショット時に他のところのframeの変更を無効にするべきです。
    
    - (void)layoutWebView
    {
     if (!_isCapturing) {
      self.wkWebView.frame = [self frameForWebView];
     }
    }
    おわりに
    現在WKWebViewの使用はますます広くなりました。メモリの占有率を勝手に調べました。同じウェブページを開けて、UICbViewは直接160 MBのメモリを占有しました。WKWebViewは40 MBのメモリだけを占有しました。私たちの業務にWKWebViewを使ってスクリーンショットが必要なら、正直に完成しなければなりません。
    最後に、ここで対応するコードはここでローカルダウンロードhttps://github.com/VernonVan/PPSnapshotKit
    締め括りをつける
    以上はこの文章の全部の内容です。本文の内容は皆さんの学習や仕事に対して一定の参考となる学習価値を持っています。質問があれば、メッセージを書いて交流してください。ありがとうございます。