{"id":7901,"date":"2013-10-03T08:10:34","date_gmt":"2013-10-03T12:10:34","guid":{"rendered":"http:\/\/blog.xamarin.com\/?p=7901"},"modified":"2013-10-03T08:10:34","modified_gmt":"2013-10-03T12:10:34","slug":"snapshotting-views-in-ios-7","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/snapshotting-views-in-ios-7\/","title":{"rendered":"Snapshotting Views in iOS 7"},"content":{"rendered":"<p dir=\"ltr\">Many apps now use &#8220;snapshotting&#8221; to enable users to capture and store images of the app for later processing or perusal. If you have kids, your Photo Stream probably features far more in-app art than you have refrigerator magnets &#8211; though, app snapshotting has many practical business applications as well, including testing and customer support.<\/p>\n<p dir=\"ltr\">Prior to iOS 7, taking a view snapshot was typically done by rendering the view&#8217;s layer in a graphics context. However, this method has several drawbacks such as being too slow in certain cases, and not providing a general purpose solution to snapshotting while animating or when using OpenGL.<\/p>\n<p dir=\"ltr\">Update: There are a couple other methods in Xamarin.iOS for snapshotting that existed before iOS 7. For UIViews there is UIScreen.Capture (). Also, for OpenGL there is iPhoneOSGameView.Capture (). The new iOS 7 methods are faster and provide a unified approach, but you should be aware of these convenience methods as well, especially if you are targeting pre-iOS 7 versions.<\/p>\n<p dir=\"ltr\">In iOS 7 snapshotting is vastly improved. For example, it&#8217;s now easy to take a snapshot during an animation, as the following video demonstrates:<\/p>\n<p dir=\"ltr\">[youtube http:\/\/www.youtube.com\/watch?v=C5pfzutuakE]<\/p>\n<p dir=\"ltr\">To provide a high performance, general way to snapshot views, iOS 7 has introduced several new methods on UIView:<\/p>\n<ul>\n<li>\n<p dir=\"ltr\">DrawViewHierarchy &#8211; Renders a view hierarchy snapshot.<\/p>\n<\/li>\n<li>\n<p dir=\"ltr\">SnapshotView &#8211; Renders a snapshot of a view to a new view.<\/p>\n<\/li>\n<li>\n<p dir=\"ltr\">ResizableSnapshotView &#8211; Renders a snapshot of a view to a new view with resizeable insets.<\/p>\n<\/li>\n<\/ul>\n<p dir=\"ltr\">To illustrate how much better the new snapshotting APIs are, consider the scenario shown above, where a view handles touch input to animate a UIImageView along a path.<\/p>\n<p dir=\"ltr\">Prior to iOS 7, taking a snapshot would have involved calling RenderInContext on the view&#8217;s layer, as shown below:<\/p>\n<pre class=\"lang:csharp decode:true\">\nvoid Snapshot()\n{\n  UIImage image;\n\n  UIGraphics.BeginImageContext (View.Frame.Size);\n\n  \/\/pre-iOS 7 using layer to snapshot\n  View.Layer.RenderInContext (UIGraphics.GetCurrentContext ());\n\n  image = UIGraphics.GetImageFromCurrentImageContext ();\n  UIGraphics.EndImageContext ();\n\n  \/\/...code to save to photo album omitted for brevity\n}\n<\/pre>\n<p dir=\"ltr\">This works fine if we take a snapshot of a static view. However if we take a snapshot while an animation is running, the snapshot shows the final state, as the following screenshot shows:<\/p>\n<p><img decoding=\"async\" alt=\"\" src=\"https:\/\/lh6.googleusercontent.com\/D9EAseQYeCkawQ1K2Kf2_Ms1UerJndYjYTR3tcZ7kMjWfldS59MHAjz5AjM9sthjP9FAu5O5t9kSZzDcw8L_FK69wLM4aaj2XazGYKmav5xcaXZTUcqW5qlWeg\" width=\"166px;\" height=\"334px;\" \/><\/p>\n<p dir=\"ltr\">iOS 7 offers an easy solution for this. We can simply use the new DrawViewHierachy method:<\/p>\n<pre class=\"lang:csharp decode:true\">\nvoid Snapshot()\n{\n  UIImage image;\n\n  UIGraphics.BeginImageContext (View.Frame.Size);\n\n  \/\/new iOS 7 method to snapshot\n  View.DrawViewHierarchy (View.Frame, true);\n\n  image = UIGraphics.GetImageFromCurrentImageContext ();\n  UIGraphics.EndImageContext ();\n\n  \/\/...code to save to photo album omitted for brevity\n}\n<\/pre>\n<p dir=\"ltr\">Now if we take a snapshot during the animation, the image shows the state at the time the snapshot was taken, even if in the middle of an animation:<\/p>\n<p><img decoding=\"async\" alt=\"\" src=\"https:\/\/lh6.googleusercontent.com\/YfoEFYjDnocPNBsHfybh67L0zt9z_Qs20iEO36Z9GfxTwEGUrzIClze_NrvWJl1xYn3dhflFevXfaWPcjtheWFE0oyahAc2s3SnfMMWNdEvsdRa3Q-ZAN-K8Xg\" width=\"166px;\" height=\"334px;\" \/><\/p>\n<p dir=\"ltr\">Another case that was not handled generally prior to iOS 7 was snapshotting an OpenGL view. The same code shown earlier using RenderInContext with OpenGL produces a &#8220;blank&#8221; image. There are ways to work around this, but the point is, the code is not generalized.<\/p>\n<p dir=\"ltr\">In iOS 7 however, we can call the same DrawViewHierarchy method to snapshot an EAGLView instance. For example, the following screenshot shows a snapshot taken from the default EAGLView created with the OpenGL application template:<\/p>\n<p><img decoding=\"async\" alt=\"\" src=\"https:\/\/lh6.googleusercontent.com\/5F41s9R5074-b_F9vwJQ5fzqE1u8IsqynR7jSEDrb9jXMZ9nQumZO0Zd34HUW310Wm8gyAZztJQgVnkeJqAVIHLW8vljWeAjOIrnjuZAMobABAGQ_8cn6ZqwJA\" width=\"166px;\" height=\"334px;\" \/><\/p>\n<p dir=\"ltr\">As you can see, snapshotting in iOS 7 is now very easy to do in a high performance, uniform way.<\/p>\n<p dir=\"ltr\">You can download the sample code shown in this post <a href=\"https:\/\/github.com\/mikebluestein\/iOS7Snapshotting\" target=\"_blank\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Many apps now use &#8220;snapshotting&#8221; to enable users to capture and store images of the app for later processing or perusal. If you have kids, your Photo Stream probably features far more in-app art than you have refrigerator magnets &#8211; though, app snapshotting has many practical business applications as well, including testing and customer support. [&hellip;]<\/p>\n","protected":false},"author":1932,"featured_media":39167,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[6,4],"class_list":["post-7901","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","tag-ios","tag-xamarin-platform"],"acf":[],"blog_post_summary":"<p>Many apps now use &#8220;snapshotting&#8221; to enable users to capture and store images of the app for later processing or perusal. If you have kids, your Photo Stream probably features far more in-app art than you have refrigerator magnets &#8211; though, app snapshotting has many practical business applications as well, including testing and customer support. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/7901","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/1932"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=7901"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/7901\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media\/39167"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=7901"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=7901"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=7901"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}