iOS photo Frame

Source: Internet
Author: User

Introduced

Every day, the number of photos taken with the iPhone exceeds any camera. Every year, the display on IOS devices is getting better, and back in the days when the IPad just appeared without the Retina display, one of the killer features of the big screen was the ability to showcase user photos and browser photo galleries. Since the camera became the most important and popular feature of the IPhone, there is a huge need for applications and tools that can manage and process the valuable photos in the user photo gallery.

Until the summer of 2014, developers could only use the Assetslibrary framework to access the growing user's photo gallery. For several years, camera applications and photo applications have changed dramatically, adding many new features, including how to organize photos at a moment's time. But at the same time, the assetslibrary framework did not keep pace.

With the advent of IOS 8, Apple has provided us with a modern framework--photokit, which is better than Assetslibrary and has the features to make apps and device photo libraries work seamlessly.

Profile

We'll start with a bird's eye view of the framework object model: Relationships between entities and entities, get instances of entities, and work with the results obtained.

In addition to this, our presentation will involve some resource metadata that has not yet been opened to developers when using Assetslibrary.

We then discuss the image data that loads the resource: the process itself, a number of available options, some traps and boundary cases.

Finally, we'll talk about the changes in the photo gallery through external participants and learn how to create and submit changes to our own changes.

Photokit Object Model

Photokit defines an entity chart that is consistent with the model objects presented to the user within the Photos application of the system. These photo entities are lightweight, immutable objects. All Photokit objects are inherited from the PHObject abstract base class, and their public interface provides only one localIdentifier property.

PHAssetRepresents a separate resource in the user photo Gallery that provides metadata for the resource.

A group of resources is called a resource collection, represented by a PHAssetCollection class. A separate collection of resources can be an album in photo gallery or a moment, or a special "smart album". This smart album includes all the video collections, recently added items, user favorites, all burst photos, and more. PHAssetCollectionis PHCollection the child class.

PHCollectionListRepresents a group of PHCollections . Because it is itself PHCollection , the collection list can contain a list of other collections that allow complex collections to inherit. In fact, we can see it in the time column of the photo app: Photo---Moment---selected---year, is an example.

Get (FETCH) photo entity get vs. enumeration

Developers who are familiar with the assetslibrary framework may remember that assetslibrary can use some specific attributes to find the resources they need, one of which must enumerate the user repository to get the matching resources. Admittedly, this API provides some way to narrow down the search domain, but it's still very inefficient.

In stark contrast, examples of photokit entities are obtained by acquiring them. Those who are familiar with Core Data will feel that they are closer to photokit in terms of concepts and descriptions.

GET request

The get operation is implemented by the class method of the entity described above. Which class/method to use depends on the scope of the problem and how you show and traverse the photo gallery. The naming of all get methods is similar: class func fetchXXX(..., options: PHFetchOptions) -> PHFetchResult . The options parameters give us a way to filter and sort the results, which NSFetchRequest is similar to predicate the sortDescriptors parameters.

Get results

You may have noticed that these fetch operations are not asynchronous. They return an PHFetchResult object that can use a similar NSArray interface to access the collection within the result. It dynamically loads content on demand and caches the most recently requested content. This behavior batchSize is similar to the NSFetchRequest returned result array that sets the property. PHFetchResultThere is no way to specify this behavior with parameters, but the official website document guarantees "the best performance even when dealing with a large number of return results".

The object returned by the Get method PHFetchResult is not automatically updated even if the content of the photo library that satisfies the request has changed. In a later section, we'll show you how to look at the changes to the returned PHFetchResult object and work with the updated content.

Temporary collection (Transient collections)

You may find that you have designed a component that can manipulate the resource collection, and you want it to be able to handle any set of resources. Photokit through a collection of temporary resources, so that we can easily do this.

You can PHAsset create a temporary collection of resources through an object array or an object that contains resources PHFetchResult . The actions created are PHAssetCollection transientAssetCollectionWithAssets(...) transientAssetCollectionWithFetchResult(...) completed within the and factory methods. The objects created by these methods can be PHAssetCollection used just like other objects. However, these collections are not stored in the user photo gallery and are naturally not displayed in the photo app.

Similar to the resource collection, you can use PHCollectionList the transientCollectionListWithXXX(...) factory method in to create a temporary collection list.

When you want to merge two request requests, you will find that this thing is very useful.

Photo Meta data

As mentioned at the beginning of the article, Photokit provides additional metadata about the user's resources, which are not accessible in the previously used alassetslibrary framework or are difficult to access.

HDR and Panorama photos

You can use the properties of the photo resource to verify that the mediaSubtypes image in the asset Library has HDR turned on when capturing, and whether the camera app's Panorama mode was used when shooting.

Collect and hide Resources

To verify that a resource is marked as favorite or hidden by the user, simply check PHAsset the instance's favorite and hidden properties.

Burst Mode photos

For a resource, if its PHAsset representsBurst property is, it means that true the resource is a representative photo in a series of burst photos (multiple photos were taken while the user was holding down the shutter). It also has a property burstIdentifier that if you want to get the remaining other photos in a burst photo, you can get it by passing this value into the fetchAssetsWithBurstIdentifier(...) method.

The user can mark a shot in a continuous sequence, and the system automatically uses various heuristics to mark a potential representative photo that the user may choose. This metadata is PHAsset accessible through the burstSelectionTypes properties. This property is a bitmask of three constants: a .UserPick resource that represents a manually tagged user, represents a .AutoPick potential resource that a user might tag, and .None represents a resource that is not marked.

This screenshot shows how the photo app automatically marks potential resources that a user might tag in a burst photo.

Photo Loading

In the past few years of working with user photo galleries, developers have created hundreds (if not thousands) of tips to improve the efficiency of photo loading and presentation. These techniques handle the dispatch and cancellation of requests, image size modification and cropping, caching, and so on. Photokit provides a class that can do all of these things with a more convenient and modern API: PHImageManager .

Request image

Image requests are requestImageForAsset(...) distributed through methods. This method accepts one PHAsset that can set the size of the returned image and other optional options for the image (via the PHImageRequestOptions Parameter object settings), and the result callback (results handler). The return value of this method can be used to cancel the request when the requested data is no longer required.

Size and cropping of images

Oddly, the parameters for the size definition and clipping of the returned image are distributed in two places. targetSizeand contentMode These parameters are passed directly inside the requestImageForAsset(...) method. This content mode is similar to the UIView contentMode parameter, which determines whether the photo should be placed in the target size in a scaled or proportional manner. Note: If you do not modify or crop the photo size, then the method parameter is the PHImageManagerMaximumSize and PHImageContentMode.Default .

In addition, PHImageRequestOptions there are several ways to determine how the image Manager will resize the image. resizeModeproperty can be set to .Exact (The return image must match the target size), .Fast (ratio.) Exact is more efficient, but the returned image may not be the same as the target size) or .None . Also worth mentioning is that the normalizedCroppingMode attribute lets us determine how the image manager should crop the image. Note: If you set normalizedcroppingMode the value, you resizeMode need to set it to .Exact .

Request delivery and Progress

By default, if the image manager decides to use an optimal policy, it passes a lower-quality version before delivering a high-quality version of the image to you. You can deliveryMode control this behavior through attributes, and the value of the default behavior described above is .Opportunistic . If you only want high-quality images and can accept longer load times, set the property to .HighQualityFormat . If you want to load faster, and you can sacrifice a bit of image quality, set the property to .FastFormat .

You can use PHImageRequestOptions the synchronous properties to make the requestImage... series method into a synchronous operation. Note: When synchronous set to true , the deliveryMode property is ignored and treated as a .HighQualityFormat .

When setting these parameters, it is important to consider that some of your users might have ICloud photo gallery turned on. The Photokit API doesn't necessarily differentiate between photos on your device and photos on ICloud-they all load in the same requestImage way. This means that any image request is likely to be a very slow network request over a cellular network. Keep this in mind when you want to use .HighQualityFormat or make a synchronous request. Note: If you want to make sure that the request does not go through the network, it can be networkAccessAllowed set to false .

Another ICloud-related property is progressHandler . You can set it to a phassetimageprogresshandler block, which is automatically called by the image Manager when you download photos from ICloud.

Resource version

Photokit allows the app to make lossless changes to the photo. For edited photos, a copy of the original photo and adjustment data for the app are saved separately. When you use the Image Manager to get a resource, you can specify which version of the image resource should be delivered through result handler. This can be done by setting version properties that .Current will deliver images that contain all adjustments and modifications, .Unadjusted deliver images that have not been modified, .Original and deliver images in the original, highest-quality format, such as raw data. When the property is set to .Unadjusted , a JPEG is delivered.

You can read more about this in the framework in Sam Davies's article, "Photo extensions".

Results callback (Result handler)

The result callback is a UIImage block that contains a variable and a info dictionary as a parameter. Depending on the parameters and the requested option, it can be called multiple times by the image manager throughout the lifetime of the request.

infoThe dictionary provides information about the status of the current request, such as:

    • Whether the image must be requested from ICloud (if you set it up when you initialize it networkAccessAllowed false , you must re-request the image)-- PHImageResultIsInCloudKey .
    • The low- UIImage quality format of whether the current delivery is the final result. When high-quality images are being downloaded, this allows you to show a preview image to the user first- PHImageResultIsDegradedKey .
    • The request ID (which makes it easy to cancel the request), and whether the request has been canceled-- PHImageResultRequestIDKey and PHImageCancelledKey .
    • If no image is provided to result handler, there is an error message in the dictionary-- PHImageErrorKey .

These values allow you to update your UI to inform the user, as discussed above progressHandler , to indicate their loading status.

Cache

When images are about to appear on the screen, such as when you want to display a large number of thumbnail images of a resource image on a set of scrolling collection views, it is sometimes useful to preload some images into memory. Photokit provides a PHImageManager subclass to handle This particular usage scenario-- PHImageCachingManager .

PHImageCachingManagerProvides a key approach- startCachingImagesForAssets(...) . You pass in an PHAssets array of types, some request parameters, and some optional options that you will use to request a single image. In addition, there are methods that let you notify the cache manager to stop caching a specific list of resources and to stop caching all images.

allowsCachingHighQualityImagesproperty allows you to specify whether the image manager should prepare high-quality images. The default properties behave well when caching a short and immutable list of resources true . However, when you want to do a cache operation on the collection view, it is best to set it to false .

Note: In my experience, using the cache manager can damage the performance of a slide when users are sliding extremely fast on a collection view with a large amount of resources. It is extremely important to customize a caching behavior for this particular usage scenario. The size of the cache window, the time and frequency of moving the cache window, allowsCachingHighQualityImages the attribute values--these parameters are carefully adjusted in the real photo library on the target hardware and tested for performance. Further, you can consider dynamically setting these parameters on the basis of user behavior.

Request image Data

Finally, in addition to asking for normal UIImage , PHImageManager another method can return NSData resource data for an object type, including its generic type identifier, and the orientation of the image. This method returns the most information for this resource.

The vicissitudes of Things

We have discussed the metadata for requesting resources in the user photo gallery, but so far we have not mentioned how to update the data we get. Photo Gallery is essentially a bunch of mutable states, and the photo entities mentioned in the first section are immutable objects. Photokit allows you to receive all the information you need about the changes in the photo gallery to properly update your cache status.

Observing changes

First, you need to PHPhotoLibrary registerChangeObserver(...) register a change observer by means of a shared object (the observer will obey the PHPhotoLibraryChangeObserver protocol). As long as another app or user's changes in the photo gallery affect any resource or resource collection that you get before the change, the Change observer's photoLibraryDidChange(...) method is called. This method has only one PHChange type of argument that you can use to verify that the changes are related to the object you are interested in acquiring.

Update the results obtained

PHChangeThere are several ways to track changes by passing in any object or object that you are interested in PHObject PHFetchResult . These several methods are changeDetailsForObject(...) and changeDetailsForFetchResult(...) . If there are no changes, these methods will return nil , otherwise you can use PHObjectChangeDetails or PHFetchResultChangeDetails object to observe the changes.

PHObjectChangeDetailsProvides a reference to the most recent photo entity object and a Boolean value that tells you if the object's image data has changed and whether the object has been deleted.

PHFetchResultChangeDetailsEncapsulates the information that is applied before you by getting the PHFetchResult changes you get. PHFetchResultChangeDetailsis designed to simplify the update operation of CollectionView or TableView as much as possible. Its properties map exactly to the information you need when using a typical CollectionView update handler. Note that to correct the update UITableView / UICollectionView , you must handle the change in the correct order, that is: rice--removedindexes,insertedindexes,changedindexes, Enumeratemoveswithblock (if that's hasMoves the true case). In addition, PHFetchResultChangeDetails the hasIncrementalChanges properties can be set false , which means that the old fetch results should all be replaced by the new values. In this case, you should call UITableView/UICollectionView the reloadData .

Note: There is no need to handle changes in a centralized manner. If you have multiple components in your app that need to work with photo entities, then each of them has its own PHPhotoLibraryChangeObserver . The component then can query the object on its own PHChange and detect if (and how) to update its own state.

Change with the Wind

Now that we know how to observe the changes caused by users and other applications, let's try to make changes ourselves.

Change the objects that exist

Using Photokit to make a change in a photo gallery is to create a change request object that is linked to a resource or resource set, set the properties of the requested object, or call the appropriate method to describe the change you want to commit. This must be performChanges(...) done through the method, within the block submitted to the share PHPhotoLibrary . Note: You need to be prepared to performChanges handle the failure in the completion block of the method. While dealing with a state that can be changed by multiple participants (such as your app, users, other apps, photo extensions, etc.), this approach provides security and is relatively easy to use.

To modify a resource, you need to create one PHAssetChangeRequest . You can then modify the creation date, the resource location, and whether the resource will be hidden, whether the resource is viewed as a user collection, and so on. In addition, you can delete resources from the user's library.

Similarly, to modify a resource collection or collection list, you need to create one PHAssetCollectionChangeRequest or an PHCollectionListChangeRequest object. You can then modify the collection title, add or Remove collection members, or completely delete the collection.

Before your changes are submitted to the user photo gallery, the user is presented with an explicit warning box to get permission.

Create a new object

The practice of creating a new resource is similar to modifying a resource that already exists. Simply use the creationRequestForAssetFromXXX(...) factory method to create a change request and pass in the resource image data (or a URL). If you need to make additional changes to the newly created resource, you can create the properties of the change request placeholderForCreatedAsset . It returns an available placeholder instead of a "real" PHAsset reference.

Conclusion

I've discussed the basics of photokit, but there's still a lot of stuff waiting for us to explore. You can watch the WWDC session video to learn more, dig deeper, and write some of your own code by looking at the code of the sample everywhere: Photokit opens the possibility for IOS developers to new worlds, and in the coming months or years we will certainly see more creative and excellent products based on this foundation.

iOS photo Frame

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.