带大图显示的图片选择器&自定义相机(选中的自动前移)-----》PhotoKit

来源:互联网 发布:名片制作软件美图秀秀 编辑:程序博客网 时间:2024/05/19 17:57

最终效果:
这里写图片描述
这里写图片描述
模拟器没有相机功能,所以这里就不展示了。

思路
因为ALAssetLibrary获取系统资源的方法在iOS9中不被推荐,所以这里使用PhotoKit
关于PhotoKit跟ALAssetLibrary的差异以及使用详细使用方法可以点击iOS 开发之照片框架详解
图中的图片表格列表是用的UICollectionView,collectionview是类似tableview的列表控件,但是功能更强大,有兴趣的同学可以参考UICollection学习总结以及案例集合
里面有7个关于collectionview的demo,有一些功能比较好玩的实现,这里就不一一介绍了。
回到正题,
因为用的是photokit,photokit中获取的资源并不是直接的是图片资源,而是PHAsset(代表照片库中的一个资源,跟 ALAsset 类似,通过 PHAsset 可以获取和保存资源)所以基本的思路是,从系统相册获取到资源,都以PHAsset保存到模型中,在最后要展示的时候再通过统一的方法将PHAsset转换成图片
模型

class CHImage: NSObject {    var asset:PHAsset!    var isSelected = false    override init() {        super.init()    } }

用来保存获取的资源信息
图片有选中和未选中两个状态定义一个isSelected属性来记录选中状态
未完待续。。。。
续:
有了可以保存资源的Model以后,就需要去获取资源了,这路贴一张网上的关于photokit组成的图:
这里写图片描述
PhotoKit获取资源的方式,是通过一系列形如 class func fetchXXX(…, options: PHFetchOptions) -> PHFetchResult 的类方法,可以根据这些方法来封装一些方法:

/**  获取全部相册 */    func getPhotoListDatas() -> NSArray {        var dataArr = [AnyObject]()        // 列出所有相册智能相册        let smartAlbums = PHAssetCollection.fetchAssetCollectionsWithType(.SmartAlbum, subtype:.SmartAlbumUserLibrary, options: nil)        dataArr.append(smartAlbums[0])        // 列出所有用户创建的相册        let topLevelUserCollections:PHFetchResult = PHAssetCollection.fetchTopLevelUserCollectionsWithOptions(nil)        for i in 0  ..< topLevelUserCollections.count {            let sub = topLevelUserCollections[i]            dataArr.append(sub)        }        return dataArr    }/**  获取一个相册的结果集合 */    func getFetchResult(assetCollection:PHAssetCollection) -> PHFetchResult {        let fetchOptions = PHFetchOptions()        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]        let fetchResult = PHAsset.fetchAssetsInAssetCollection(assetCollection, options: fetchOptions)        return fetchResult    }/**  只获取相机胶卷结果集 */    func getCameraRollFetchResul() -> PHFetchResult{        let fetchOptions = PHFetchOptions()        let smartAlbumsFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.SmartAlbum, subtype:.SmartAlbumUserLibrary, options: fetchOptions)        let fetch = PHAsset.fetchAssetsInAssetCollection(smartAlbumsFetchResult[0] as! PHAssetCollection, options: nil)        return fetch    }/**  获取图片实体并把图片结果存放到数组中,返回数组 */    func getPhotoAssets(fetchResult:PHFetchResult) -> [CHImage]{        var dataArr = [CHImage]()        for i in 0  ..< fetchResult.count {            let asset = fetchResult[i] as! PHAsset            let image = CHImage()            /**  过滤视频 */            if asset.mediaType == .Image{                image.asset = asset                dataArr.append(image)            }        }        return dataArr    }// 获取某个分组的第一张照片缩略图    func firstPhotoThumbnails(assetCollection:PHAssetCollection,synchronous:Bool, resultHandler: (UIImage?, [NSObject : AnyObject]?) -> Void) {        self.photoThumbnails(self.getFetchResult(assetCollection).firstObject as! PHAsset,synchronous:synchronous, resultHandler: resultHandler)    }    // 获取某一张照片缩略图     func photoThumbnails(asset: PHAsset!,synchronous:Bool,resultHandler: (UIImage?, [NSObject : AnyObject]?) -> Void) {        let superSize = CGSizeMake(186 , 186 )        return self.photoImage(superSize,synchronous:synchronous ,asset: asset, resultHandler: resultHandler)    }    // 获取一张大图    func photoDefault(asset: PHAsset!, synchronous:Bool, targetSize:CGSize,resultHandler: (UIImage?, [NSObject : AnyObject]?) -> Void) {        return self.photoImage(targetSize, synchronous:synchronous, asset: asset, resultHandler: resultHandler)    }

最后,我们前面的这些方法获取到的最后的不管是缩略图还是大图,获取到的都是自定义的Model类型的而不是我们想要的UIImage类型的所以还需要一个方法来获取最后的image

/**  获取图片 */    func photoImage(targetSize: CGSize, synchronous:Bool,asset: PHAsset!, resultHandler: (UIImage?, [NSObject : AnyObject]?) -> Void) {        let options = PHImageRequestOptions()        options.resizeMode = .Exact        options.synchronous = synchronous        PHImageManager.defaultManager().requestImageForAsset(asset, targetSize:targetSize, contentMode: .AspectFill, options: options, resultHandler: resultHandler)    }

这里有一个坑,因为存在相册中的图片的宽高比我们是不知道的,所以获取图片的时候targetSize我们只能穿PhotoKi给我们的默认值就是原图大小PHImageManagerMaximumSize,但是这样获取到的图片大小肯定会超乎你的想象,所以获取到图片之后需要通过:

 /**  修改图片尺寸 */    static func scaleToSize(image:UIImage?,width:CGFloat,height:CGFloat) -> UIImage {        //        let scale = image!.size.height/image!.size.width        let size = CGSizeMake(width, height)        UIGraphicsBeginImageContext(size)        image!.drawInRect(CGRectMake(0, 0, size.width, size.height))        let newImage = UIGraphicsGetImageFromCurrentImageContext()        UIGraphicsEndImageContext()        return newImage    }

来重新画一张图片,缩小图片更好的展示的同时还可以缩小图片的大小,上传的时候更方便。注意,这里的width跟height应该是你所先要的图片尺寸的2以上倍,不然图片看上去会格外的不清晰(AV画质~)

获取到资源之后,就是用uicollectionview展示,实现delegate跟datasource这里就不赘述了。关键点是实习选中的图片前移,没选中的后移,移动的动画非常简单,用uicollectionview自带的func moveItemAtIndexPath(indexPath: NSIndexPath, toIndexPath newIndexPath: NSIndexPath) 这里要确定要交换的图的初始位置跟要换到的位置,而在点击继续之后需要从全部相册资源中选出isSelected = true的资源,如果用循环,因为大部分人的手机中照片都是500+,用循环会卡死,所以这里用正则来匹配,swift中的正则使用方法:

func getSelectedImageArray() -> [CHImage] {        let predicate1 = NSPredicate(format: "isSelected == true")        return (self.imageArray as NSArray).filteredArrayUsingPredicate(predicate1) as! [CHImage]    }

可以很快的匹配出条件符合的资源,并放入数组,之后只要将这个数组传给下一个页面,或者将资源转换成图片之后再传,这个可以根据需求自己定。下面是demo自定义相册&相机
里面还有一个相机的自定义,基本上就自定义了图标跟重拍之类的。仅供大家一起学习讨论。

0 0
原创粉丝点击