{"id":12371,"date":"2014-07-07T11:59:22","date_gmt":"2014-07-07T15:59:22","guid":{"rendered":"http:\/\/blog.xamarin.com\/?p=12371"},"modified":"2014-07-07T11:59:22","modified_gmt":"2014-07-07T15:59:22","slug":"build-great-photo-experiences-in-ios-8-with-photokit","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/build-great-photo-experiences-in-ios-8-with-photokit\/","title":{"rendered":"Build Great Photo Experiences in iOS 8 with PhotoKit"},"content":{"rendered":"<p>\t\t\t\t<strong>PhotoKit<\/strong> is a new framework in iOS 8 that allows you to query the system image library and create custom user interfaces to view and modify its contents. To use PhotoKit from Xamarin.iOS, you can download the preview release in our alpha channel.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-12378\" src=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/photokit1.png\" alt=\"PhotoKit1\" width=\"393\" height=\"554\" \/><\/p>\n<p>PhotoKit includes a number of classes that represent image and video assets, as well as collections of assets\u00a0such as albums and folders. Collectively, PhotoKit represents these in what it calls model objects.<\/p>\n<p>The model objects that represents the photos and videos themselves are of type <strong>PHAsset<\/strong>. A <strong>PHAsset<\/strong> contains metadata such as the asset&#8217;s media type and its creation date.<\/p>\n<p>Similarly, the <strong>PHAssetCollection<\/strong> and <strong>PHCollectionList<\/strong> classes contain metadata about asset collections and collection lists respectively. Asset collections are groups of assets, such as all the photos and videos for a given year. Likewise, collection lists are groups of asset collections, such as photos and videos grouped by year.<\/p>\n<p>PhotoKit makes it easy to query model data through a variety of <em>fetch<\/em> methods. For example, to retrieve all images, you would call <code>PFAsset.Fetch<\/code>, passing the <code>PHAssetMediaType.Image<\/code> media type.<\/p>\n<pre class=\"lang:csharp decode:true\">\nPHFetchResult fetchResults = PHAsset.FetchAssets (PHAssetMediaType.Image, null);\n<\/pre>\n<p>The <strong>PHFetchResult<\/strong> instance would then contain all the <strong>PFAsset<\/strong> instances representing images. To get the images themselves, you use the <strong>PHImageManager<\/strong> (or the caching version, <strong>PHCachingImageManager<\/strong>) to make a request for the image by calling <code>RequestImageForAsset<\/code>. For example, the following code retrieves an image for each asset in a <strong>PHFetchResult<\/strong> to display in a collection view cell:<\/p>\n<pre class=\"lang:csharp decode:true\">\npublic override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)\n{\n  var imageCell = (ImageCell)collectionView.DequeueReusableCell (cellId, indexPath);\n\n  imageMgr.RequestImageForAsset ((PHAsset)fetchResults [(uint)indexPath.Item], thumbnailSize,\n    PHImageContentMode.AspectFill, new PHImageRequestOptions (), (img, info) =&gt; {\n      imageCell.ImageView.Image = img;\n    });\n\n    return imageCell;\n}\n<\/pre>\n<p>This results in a grid of images as shown below:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-12378\" src=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/photokit1.png\" alt=\"PhotoKit1\" width=\"393\" height=\"554\" \/><\/p>\n<p>That&#8217;s how to handle querying and reading data. You can also write changes back to the library. Since multiple interested applications are able to interact with the system photo library, you can register an observer to be notified of changes using a <strong>PhotoLibraryObserver<\/strong>. Then, when changes come in, your application can update accordingly. For example, here&#8217;s a simple implementation to reload the collection view above:<\/p>\n<pre class=\"lang:csharp decode:true\">\nclass PhotoLibraryObserver : PHPhotoLibraryChangeObserver\n{\n  readonly PhotosViewController controller;\n\n  public PhotoLibraryObserver (PhotosViewController controller)\n  {\n    this.controller = controller;\n  }\n\n  public override void PhotoLibraryDidChange (PHChange changeInstance)\n  {\n    DispatchQueue.MainQueue.DispatchAsync (() =&gt; {\n\n      var changes = changeInstance.GetFetchResultChangeDetails (controller.fetchResults);\n      controller.fetchResults = changes.FetchResultAfterChanges;\n      controller.CollectionView.ReloadData ();\n    });\n  }\n}\n<\/pre>\n<p>To actually write changes back from your application, you create a change request. Each of the model classes has an associated change request class. For example, to change a <strong>PHAsset<\/strong>, you create a <strong>PHAssetChangeRequest<\/strong>. The steps to perform changes that are written back to the photo library and sent to observers like the one above are:<\/p>\n<ol>\n<li>Perform the editing operation.<\/li>\n<li>Save the filtered image data to a <strong>PHContentEditingOutput<\/strong> instance.<\/li>\n<li>Make a change request to publish the changes form the editing output.<\/li>\n<\/ol>\n<p>Here&#8217;s an example that writes back a change to an image that applies a core image noir filter:<\/p>\n<pre class=\"lang:csharp decode:true\">\nvoid ApplyNoirFilter (object sender, EventArgs e)\n{\n  Asset.RequestContentEditingInput (new PHContentEditingInputRequestOptions (), (input, options) =&gt; {\n    \/\/\n    \/\/ perform the editing operation, which applies a noir filter in this case\n    var image = CIImage.FromUrl (input.FullSizeImageUrl);\n    image = image.CreateWithOrientation ((CIImageOrientation)input.FullSizeImageOrientation);\n    var noir = new CIPhotoEffectNoir {\n      Image = image\n    };\n    var ciContext = CIContext.FromOptions (null);\n    var output = noir.OutputImage;\n\n    var uiImage = UIImage.FromImage (ciContext.CreateCGImage (output, output.Extent));\n    imageView.Image = uiImage;\n    \/\/\n    \/\/ save the filtered image data to a PHContentEditingOutput instance\n    var editingOutput = new PHContentEditingOutput(input);\n    var adjustmentData = new PHAdjustmentData();\n    var data = uiImage.AsJPEG();\n    NSError error;\n    data.Save(editingOutput.RenderedContentUrl, false, out error);\n    editingOutput.AdjustmentData = adjustmentData;\n    \/\/\n    \/\/ make a change request to publish the changes form the editing output\n    PHPhotoLibrary.GetSharedPhotoLibrary.PerformChanges (\n      () =&gt; {\n        PHAssetChangeRequest request = PHAssetChangeRequest.ChangeRequest(Asset);\n        request.ContentEditingOutput = editingOutput;\n      },\n      (ok, err) =&gt; Console.WriteLine (&quot;photo updated successfully: {0}&quot;, ok));\n  });\n}\n<\/pre>\n<p>When the users selects the button, the filter is applied:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-12379\" src=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/photokit2.png\" alt=\"PhotoKit2\" width=\"827\" height=\"568\" \/><\/p>\n<p>And thanks to the <strong>PHPhotoLibraryChangeObserver<\/strong>, the change is reflected in the collection view when the user navigates back:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-12380\" src=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/photokit3.png\" alt=\"PhotoKit3\" width=\"393\" height=\"554\" \/><\/p>\n<p>PhotoKit is a welcome addition to iOS that allows greater flexibility for incorporating photo library data into applications. It opens the doors for third party developers to build more integrated photo and video experiences than ever before.<\/p>\n<p>The code from this post is available in my <a href=\"https:\/\/github.com\/mikebluestein\/PhotoKitDemo\" title=\"PhotoKitDemo source code\" target=\"_blank\">GitHub repo<\/a>.<\/p>\n<p><a href=\"http:\/\/forums.xamarin.com\/discussion\/19886\" title=\"Discuss in Forums\" target=\"_blank\"><em>Discuss this blog post in the Xamarin Forums<\/em><\/a><\/p>\n<p>&nbsp;\t\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>PhotoKit is a new framework in iOS 8 that allows you to query the system image library and create custom user interfaces to view and modify its contents. To use PhotoKit from Xamarin.iOS, you can download the preview release in our alpha channel. PhotoKit includes a number of classes that represent image and video assets, [&hellip;]<\/p>\n","protected":false},"author":1932,"featured_media":39167,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[6,4],"class_list":["post-12371","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","tag-ios","tag-xamarin-platform"],"acf":[],"blog_post_summary":"<p>PhotoKit is a new framework in iOS 8 that allows you to query the system image library and create custom user interfaces to view and modify its contents. To use PhotoKit from Xamarin.iOS, you can download the preview release in our alpha channel. PhotoKit includes a number of classes that represent image and video assets, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/12371","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=12371"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/12371\/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=12371"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=12371"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=12371"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}