斯威夫特 – 如何从照片库最后拍摄3张照片?

我需要从viewDidload事件中获取并显示最后拍摄的照片库中的3张照片,没有任何点击。

在这一步之后,当我滚动scrollview时,我应该得到其他的照片3乘3。

你知道迅速做到这一点的正确方法吗? 谢谢。

样品

下面是一个使用设备iOS 8+的Photos框架的解决scheme:

 import Photos class ViewController: UIViewController { var images:NSMutableArray! // <-- Array to hold the fetched images var totalImageCountNeeded:Int! // <-- The number of images to fetch func fetchPhotos () { images = NSMutableArray() totalImageCountNeeded = 3 self.fetchPhotoAtIndexFromEnd(0) } // Repeatedly call the following method while incrementing // the index until all the photos are fetched func fetchPhotoAtIndexFromEnd(index:Int) { let imgManager = PHImageManager.defaultManager() // Note that if the request is not set to synchronous // the requestImageForAsset will return both the image // and thumbnail; by setting synchronous to true it // will return just the thumbnail var requestOptions = PHImageRequestOptions() requestOptions.synchronous = true // Sort the images by creation date var fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)] if let fetchResult: PHFetchResult = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions) { // If the fetch result isn't empty, // proceed with the image request if fetchResult.count > 0 { // Perform the image request imgManager.requestImageForAsset(fetchResult.objectAtIndex(fetchResult.count - 1 - index) as PHAsset, targetSize: view.frame.size, contentMode: PHImageContentMode.AspectFill, options: requestOptions, resultHandler: { (image, _) in // Add the returned image to your array self.images.addObject(image) // If you haven't already reached the first // index of the fetch result and if you haven't // already stored all of the images you need, // perform the fetch request again with an // incremented index if index + 1 < fetchResult.count && self.images.count < self.totalImageCountNeeded { self.fetchPhotoAtIndexFromEnd(index + 1) } else { // Else you have completed creating your array println("Completed array: \(self.images)") } }) } } } 

您可以使用AssetsLibrary框架中的函数提取3张最新的照片。 首先,您必须将该框架添加到项目中。 以下函数检索3张最新的照片并调用完成块。

 import AssetsLibrary func getLatestPhotos(completion completionBlock : ([UIImage] -> ())) { let library = ALAssetsLibrary() var count = 0 var images : [UIImage] = [] var stopped = false library.enumerateGroupsWithTypes(ALAssetsGroupSavedPhotos, usingBlock: { (group,var stop) -> Void in group?.setAssetsFilter(ALAssetsFilter.allPhotos()) group?.enumerateAssetsWithOptions(NSEnumerationOptions.Reverse, usingBlock: { (asset : ALAsset!, index, var stopEnumeration) -> Void in if (!stopped) { if count >= 3 { stopEnumeration.memory = ObjCBool(true) stop.memory = ObjCBool(true) completionBlock(images) stopped = true } else { // For just the thumbnails use the following line. let cgImage = asset.thumbnail().takeUnretainedValue() // Use the following line for the full image. let cgImage = asset.defaultRepresentation().fullScreenImage().takeUnretainedValue() if let image = UIImage(CGImage: cgImage) { images.append(image) count += 1 } } } }) },failureBlock : { error in println(error) }) } 

上面的函数可以这样调用

 getLatestPhotos(completion: { images in println(images) //Set Images in this block. }) 

细节

xCode 8.3,Swift 3.1

 import UIKit import Photos class PhotoLibrary { fileprivate var imgManager: PHImageManager fileprivate var requestOptions: PHImageRequestOptions fileprivate var fetchOptions: PHFetchOptions fileprivate var fetchResult: PHFetchResult<PHAsset> init () { imgManager = PHImageManager.default() requestOptions = PHImageRequestOptions() requestOptions.isSynchronous = true fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)] fetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions) } var count: Int { return fetchResult.count } func setPhoto(at index: Int, completion block: @escaping (UIImage?)->()) { if index < fetchResult.count { imgManager.requestImage(for: fetchResult.object(at: index) as PHAsset, targetSize: UIScreen.main.bounds.size, contentMode: PHImageContentMode.aspectFill, options: requestOptions) { (image, _) in block(image) } } else { block(nil) } } func getAllPhotos() -> [UIImage] { var resultArray = [UIImage]() for index in 0..<fetchResult.count { imgManager.requestImage(for: fetchResult.object(at: index) as PHAsset, targetSize: UIScreen.main.bounds.size, contentMode: PHImageContentMode.aspectFill, options: requestOptions) { (image, _) in if let image = image { resultArray.append(image) } } } return resultArray } } 

用法

  var photoLibrary = PhotoLibrary() // Number of all photos photoLibrary.count // Get photo self.photoLibrary.setPhoto(at: indexPath.row) { image in if let image = image { DispatchQueue.main.async { imageView.image = image } } } 

完整示例(带有来自PhotoLibrary的图像的collectionView)

的Info.plist

添加到Info.plist

 <key>NSPhotoLibraryUsageDescription</key> <string>{bla-bla-bla}</string> 

ViewController.swift

 import UIKit import Photos class ViewController: UIViewController { @IBOutlet weak var collectionView: UICollectionView! @IBOutlet weak var collectionViewFlowLayout: UICollectionViewFlowLayout! fileprivate var photoLibrary: PhotoLibrary! fileprivate var numberOfSections = 0 override func viewDidLoad() { initCollectionView() PHPhotoLibrary.requestAuthorization { [weak self] result in if let _self = self { if result == .authorized { _self.photoLibrary = PhotoLibrary() _self.numberOfSections = 1 DispatchQueue.main.async { _self.collectionView.reloadData() } } } } } } extension ViewController: UICollectionViewDataSource { fileprivate var numberOfElementsInRow: Int { return 4 } var sizeForCell: CGSize { let _numberOfElementsInRow = CGFloat(numberOfElementsInRow) let allWidthBetwenCells = _numberOfElementsInRow == 0 ? 0 : collectionViewFlowLayout.minimumInteritemSpacing*(_numberOfElementsInRow-1) let width = (collectionView.frame.width - allWidthBetwenCells)/_numberOfElementsInRow return CGSize(width: width, height: width) } func initCollectionView() { collectionView.dataSource = self collectionView.delegate = self } func numberOfSections(in collectionView: UICollectionView) -> Int { return numberOfSections } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return photoLibrary.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell return cell } } extension ViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return sizeForCell } func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { let cell = cell as! CollectionViewCell cell.cellImageView.image = nil DispatchQueue.global(qos: .background).async { self.photoLibrary.setPhoto(at: indexPath.row) { image in if let image = image { DispatchQueue.main.async { cell.cellImageView.image = image } } } } } } 

CollectionViewCell.swift

 import UIKit class CollectionViewCell: UICollectionViewCell { @IBOutlet weak var cellImageView: UIImageView! } 

PhotoLibrary.swift

如上所述

Main.storyboard

 <?xml version="1.0" encoding="UTF-8"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> <device id="retina4_7" orientation="portrait"> <adaptation id="fullscreen"/> </device> <dependencies> <deployment identifier="iOS"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12086"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> <!--View Controller--> <scene sceneID="tne-QT-ifu"> <objects> <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="stackoverflow_28259961" customModuleProvider="target" sceneMemberID="viewController"> <layoutGuides> <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/> <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> </layoutGuides> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="IZe-8T-NdF"> <rect key="frame" x="0.0" y="20" width="375" height="647"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="2" minimumInteritemSpacing="2" id="DNv-oA-G6j"> <size key="itemSize" width="100" height="100"/> <size key="headerReferenceSize" width="0.0" height="0.0"/> <size key="footerReferenceSize" width="0.0" height="0.0"/> <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/> </collectionViewFlowLayout> <cells> <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="CollectionViewCell" id="FND-c4-nYC" customClass="CollectionViewCell" customModule="stackoverflow_28259961" customModuleProvider="target"> <rect key="frame" x="0.0" y="0.0" width="100" height="100"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> <rect key="frame" x="0.0" y="0.0" width="100" height="100"/> <autoresizingMask key="autoresizingMask"/> <subviews> <imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="FA0-5K-Pxh"> <rect key="frame" x="0.0" y="0.0" width="100" height="100"/> </imageView> </subviews> </view> <color key="backgroundColor" red="0.82995896879999997" green="0.82995896879999997" blue="0.82995896879999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstItem="FA0-5K-Pxh" firstAttribute="top" secondItem="FND-c4-nYC" secondAttribute="top" id="0WE-w2-xTC"/> <constraint firstAttribute="trailing" secondItem="FA0-5K-Pxh" secondAttribute="trailing" id="7rj-8k-UrU"/> <constraint firstItem="FA0-5K-Pxh" firstAttribute="leading" secondItem="FND-c4-nYC" secondAttribute="leading" id="ofw-aq-B79"/> <constraint firstAttribute="bottom" secondItem="FA0-5K-Pxh" secondAttribute="bottom" id="ogx-56-qNt"/> </constraints> <connections> <outlet property="cellImageView" destination="FA0-5K-Pxh" id="DE1-DT-Oik"/> </connections> </collectionViewCell> </cells> </collectionView> </subviews> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstAttribute="trailing" secondItem="IZe-8T-NdF" secondAttribute="trailing" id="1W1-Fl-ZL8"/> <constraint firstItem="IZe-8T-NdF" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" id="9QC-93-vwd"/> <constraint firstItem="IZe-8T-NdF" firstAttribute="bottom" secondItem="wfy-db-euE" secondAttribute="top" id="BEF-2W-Otd"/> <constraint firstItem="IZe-8T-NdF" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="isg-PJ-70G"/> </constraints> </view> <connections> <outlet property="collectionView" destination="IZe-8T-NdF" id="z6G-PD-d44"/> <outlet property="collectionViewFlowLayout" destination="DNv-oA-G6j" id="y8U-CI-3CD"/> </connections> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> </objects> <point key="canvasLocation" x="133.59999999999999" y="129.98500749625188"/> </scene> </scenes> </document> 

结果

在这里输入图像说明

这是@Lindsey Scott的答案,但在Objective-C中。 我将Camera Roll的最后9张照片放入collections视图中:

 -(void)fetchPhotoFromEndAtIndex:(int)index{ PHImageRequestOptions *options = [[PHImageRequestOptions alloc]init]; options.synchronous = YES; PHFetchOptions *fetchOptions = [[PHFetchOptions alloc]init]; fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]]; PHFetchResult *photos = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:fetchOptions]; if (photos) { [[PHImageManager defaultManager] requestImageForAsset:[photos objectAtIndex:photos.count -1 -index] targetSize:CGSizeMake(self.collectionView.frame.size.width/3, self.collectionView.frame.size.height/3) contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage *result, NSDictionary *info) { [self.imagesArray addObject:result]; if (index + 1 < photos.count && self.imagesArray.count < 9) { [self fetchPhotoFromEndAtIndex:index + 1]; } }]; } [self.collectionView reloadData]; }