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

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

思路
因为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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值