//
//  NAPublishAlbumTableViewController.swift
////
//  Created by  on 2019/3/23.
//  Copyright © 2019年 . All rights reserved.
//

import UIKit
import Photos

typealias HandlePhotos = ([PHAsset], [UIImage]) -> Void
class HandleSelectionPhotosManager: NSObject {
    static let share = HandleSelectionPhotosManager()
    
    var maxCount: Int = 0
    var callbackPhotos: HandlePhotos?
    
    private override init() {
        super.init()
    }
    
    func getSelectedPhotos(with count: Int, callback completeHandle: HandlePhotos? ) {
        // 限制长度
        maxCount = count < 1 ? 1 : (count > 9 ? 9 : count)
        self.callbackPhotos = completeHandle
    }
}

/// 后期可用来对相应的英文文件夹修改为汉语名,暂时未使用
enum AlbumTransformChina: String {
    case Favorites
    case RecentlyDeleted = "Recently Deleted"
    case Screenshots
    
    func chinaName() -> String {
        switch  self {
        case .Favorites:
            return "最爱"
        case .RecentlyDeleted:
            return "最近删除"
        case .Screenshots:
            return "手机截屏"
        }
    }
}


/// - albumAllPhotos: 所有
/// - albumSmartAlbums: 智能
/// - albumUserCollection: 收藏
enum AlbumSession: Int {
    case albumAllPhotos = 0
    case albumSmartAlbums
    case albumUserCollection
    
    static let count = 2
}
class NAPublishAlbumTableViewController : UITableViewController{
    // MARK: - 👉Properties
    fileprivate var allPhotos: PHFetchResult<PHAsset>!
    fileprivate var smartAlbums: PHFetchResult<PHAssetCollection>!
    fileprivate var userCollections: PHFetchResult<PHCollection>!
    private let sectionTitles = ["", "智能相册", "相册"]
    
    fileprivate var MaxCount: Int = 0
    fileprivate var handleSelectionAction: (([String], [String]) -> Void)?
    
    // MARK: - 👉Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        addCancleItem()
        
        fetchAlbumsFromSystemAlbum()
    }
    
    deinit {
        print(" ------1 deinit")
        PHPhotoLibrary.shared().unregisterChangeObserver(self)
    }
    
    // MARK: - 👉Private
    /// 获取所有系统相册概览信息
    private func fetchAlbumsFromSystemAlbum() {
        let allPhotoOptions = PHFetchOptions()
        // 时间排序
        allPhotoOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
        allPhotos = PHAsset.fetchAssets(with: allPhotoOptions)
        
        smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .albumRegular, options: nil)
        
        userCollections = PHCollectionList.fetchTopLevelUserCollections(with: nil)
        
        // 监测系统相册增加,即使用期间是否拍照
        PHPhotoLibrary.shared().register(self)
        
        // 注册cell
        tableView.register(MasterTableViewCell.self, forCellReuseIdentifier: MasterTableViewCell.cellIdentifier)
    }
    
    
    /// 添加取消按钮
    private func addCancleItem() {
        let barItem = UIBarButtonItem(title: "取消", style: .plain, target: self, action: #selector(dismissAction))
        navigationItem.rightBarButtonItem = barItem
    }
    @objc func dismissAction() {
        dismiss(animated: true, completion: nil)
    }
    
    // MARK: - 👉UITableViewDelegate & UITableViewDataSource
    override func numberOfSections(in tableView: UITableView) -> Int {
        return AlbumSession.count
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        switch AlbumSession(rawValue: section)! {
        case .albumAllPhotos: return 1
        case .albumSmartAlbums: return smartAlbums.count
        case .albumUserCollection: return userCollections.count
        }
    }
    
    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 64
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: MasterTableViewCell.cellIdentifier, for: indexPath) as! MasterTableViewCell
        cell.selectionStyle = .none
        
        switch AlbumSession(rawValue: indexPath.section)! {
        case .albumAllPhotos:
            cell.asset = allPhotos.firstObject
            cell.albumTitleAndCount = ("所有照片", allPhotos.count)
        case .albumSmartAlbums:
            let collection = smartAlbums.object(at: indexPath.row)
            cell.asset = PHAsset.fetchAssets(in: collection, options: nil).firstObject
            cell.albumTitleAndCount = (collection.localizedTitle, PHAsset.fetchAssets(in: collection, options: nil).count)
        case .albumUserCollection:
            let collection = userCollections.object(at: indexPath.row)
            cell.asset = PHAsset.fetchAssets(in: collection as! PHAssetCollection, options: nil).firstObject
            cell.albumTitleAndCount = (collection.localizedTitle, PHAsset.fetchAssets(in: collection as! PHAssetCollection, options: nil).count)
        }
        
        return cell
    }
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        let gridVC = NAPublishAssetViewController()
        switch AlbumSession(rawValue: indexPath.section)! {
        case .albumAllPhotos:
            gridVC.fetchAllPhtos = allPhotos
        case .albumSmartAlbums:
            gridVC.assetCollection = smartAlbums.object(at: indexPath.row)
            gridVC.fetchAllPhtos = PHAsset.fetchAssets(in: gridVC.assetCollection!, options: nil)
        case .albumUserCollection:
            gridVC.assetCollection = userCollections.object(at: indexPath.row) as? PHAssetCollection
            gridVC.fetchAllPhtos = PHAsset.fetchAssets(in: gridVC.assetCollection!, options: nil)
        }
        let currentCell = tableView.cellForRow(at: indexPath) as! MasterTableViewCell
        gridVC.title = currentCell.albumTitleAndCount?.0
        navigationController?.pushViewController(gridVC, animated: true)
        
    }
    
}

// MARK: - 👉PHPhotoLibraryChangeObserver
extension NAPublishAlbumTableViewController: PHPhotoLibraryChangeObserver {
    /// 系统相册改变
    func photoLibraryDidChange(_ changeInstance: PHChange) {
        
        DispatchQueue.main.sync {
            if let changeDetails = changeInstance.changeDetails(for: allPhotos) {
                allPhotos = changeDetails.fetchResultAfterChanges
            }
            
            if let changeDetail = changeInstance.changeDetails(for: smartAlbums) {
                smartAlbums = changeDetail.fetchResultAfterChanges
                tableView.reloadSections(IndexSet(integer: AlbumSession.albumSmartAlbums.rawValue), with: .automatic)
            }
            
            if let changeDetail = changeInstance.changeDetails(for: userCollections) {
                userCollections = changeDetail.fetchResultAfterChanges
                tableView.reloadSections(IndexSet(integer: AlbumSession.albumUserCollection.rawValue), with: .automatic)
            }
        }
    }
}

// MARK: - 👉MasterTableViewCell
class MasterTableViewCell: UITableViewCell {
    static let cellIdentifier = "MasterTableViewCellIdentifier"
    
    private var firstImageView: UIImageView?
    private var albumTitleLabel: UILabel?
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        setupUI()
    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        updateUI()
    }
    
    private func updateUI() {
        let width = bounds.height
        firstImageView?.frame = CGRect(x: 0, y: 0, width: width, height: width)
        albumTitleLabel?.frame = CGRect(x: firstImageView!.frame.maxX + 5, y: 4, width: 200, height: width)
    }
    
    
    private func setupUI() {
        firstImageView = UIImageView()
        addSubview(firstImageView!)
        firstImageView?.clipsToBounds = true
        firstImageView?.contentMode = .scaleAspectFill
        
        albumTitleLabel = UILabel()
        albumTitleLabel?.font = UIFont.boldSystemFont(ofSize: 17)
        addSubview(albumTitleLabel!)
    }
    
    
    // 展示第一张图片和标题
    var asset: PHAsset? {
        willSet {
            
            if newValue == nil {
                firstImageView?.image = UIImage.init(named: "icon-60")
                return
            }
            let defaultSize = CGSize(width: UIScreen.main.scale + bounds.height, height: UIScreen.main.scale + bounds.height)
            PHCachingImageManager.default().requestImage(for: newValue!, targetSize: defaultSize, contentMode: .aspectFill, options: nil, resultHandler: { (img, _) in
                self.firstImageView?.image = img
            })
        }
    }
    
    var albumTitleAndCount: (String?, Int)? {
        willSet {
            if newValue == nil {
                return
            }
            self.albumTitleLabel?.text = (newValue!.0 ?? "") + " (\(String(describing: newValue!.1)))"
        }
    }
}

 

//
//  NAPublishAssetViewController.swift
////
//  Created by  on 2019/3/23.
//  Copyright © . All rights reserved.
//

/// 查看一个相册文件夹中的所有图片

import UIKit
import Photos

class NAPublishAssetViewController : UIViewController {
    // MARK: - 👉Properties
    fileprivate var collectionView: UICollectionView!
    fileprivate let imageManager = PHCachingImageManager()
    fileprivate var thumnailSize = CGSize()
    fileprivate var previousPreheatRect = CGRect.zero
    
    // 展示选择数量
    fileprivate var countView: UIView!
    fileprivate var countLabel: UILabel!
    fileprivate var countButton: UIButton!
    fileprivate let countViewHeight: CGFloat = 50
    fileprivate var isShowCountView = false
    
    
    // 是否只选择一张,如果是,则每个图片不显示选择图标
    fileprivate var isOnlyOne = true
    // 选择图片数
    fileprivate var count: Int = 0
    // 选择回调
    fileprivate var handlePhotos: HandlePhotos?
    // 回调Asset
    fileprivate var selectedAssets = [PHAsset]() {
        willSet {
            updateCountView(with: newValue.count)
        }
    }
    // 回调Image
    fileprivate var selectedImages = [UIImage]()
    
    // 选择标识
    fileprivate var flags = [Bool]()
    
    // itemSize
    fileprivate let shape: CGFloat = 3
    fileprivate let numbersInSingleLine: CGFloat = 4
    fileprivate var cellWidth: CGFloat? {
        return (UIScreen.main.bounds.width - (numbersInSingleLine - 1) * shape) / numbersInSingleLine
    }
    
    // MARK: - 👉Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        
        automaticallyAdjustsScrollViewInsets = false
        
        resetCachedAssets()
        PHPhotoLibrary.shared().register(self)
        
        // 设置回调
        count = HandleSelectionPhotosManager.share.maxCount
        handlePhotos = HandleSelectionPhotosManager.share.callbackPhotos
        isOnlyOne = count == 1 ? true : false
        
        setupUI()
        
        // 添加数量视图
        addCountView()
        
        // 监测数据源
        if fetchAllPhtos == nil {
            let allOptions = PHFetchOptions()
            allOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
            fetchAllPhtos = PHAsset.fetchAssets(with: allOptions)
            collectionView.reloadData()
        }
        
        (0 ..< fetchAllPhtos.count).forEach { _ in
            flags.append(false)
        }
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        // 定义缓存照片尺寸
        thumnailSize = CGSize(width: cellWidth! * UIScreen.main.scale, height: cellWidth! * UIScreen.main.scale)
        
        // collectionView 滑动到最底部
        guard fetchAllPhtos.count > 0 else { return }
        let indexPath = IndexPath(item: fetchAllPhtos.count - 1, section: 0)
        collectionView.scrollToItem(at: indexPath, at: .bottom, animated: false)
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        // 更新
        updateCachedAssets()
    }
    
    deinit {
        PHPhotoLibrary.shared().unregisterChangeObserver(self)
    }
    // MARK: - 👉Public
    // 所有图片
    internal var fetchAllPhtos: PHFetchResult<PHAsset>!
    // 单个相册
    internal var assetCollection: PHAssetCollection!
    
    // MARK: - 👉Private
    
    /// 展示
    private func setupUI() {
        let cvLayout = UICollectionViewFlowLayout()
        cvLayout.itemSize = CGSize(width: cellWidth!, height: cellWidth!)
        cvLayout.minimumLineSpacing = shape
        cvLayout.minimumInteritemSpacing = shape
        
        
        collectionView = UICollectionView(frame: CGRect(x: 0, y: 64, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height - 64), collectionViewLayout: cvLayout)
        view.addSubview(collectionView)
        collectionView.register(GridViewCell.self, forCellWithReuseIdentifier: GridViewCell.cellIdentifier)
        
        collectionView.dataSource = self
        collectionView.delegate = self
        collectionView.backgroundColor = .white
        view.addSubview(collectionView)
        
        addCancleItem()
    }
    
    /// count
    private func addCountView() {
        countView = UIView(frame: CGRect(x: 0, y: UIScreen.main.bounds.height, width: UIScreen.main.bounds.width, height: countViewHeight))
        countView.backgroundColor = UIColor(white: 0.85, alpha: 1)
        view.addSubview(countView)
        
        countLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 50, height: 35))
        countLabel.backgroundColor = .clear
        countLabel.textColor = .green
        countLabel.textAlignment = .center
        countLabel.text = "0/8"
        countLabel.font = UIFont.systemFont(ofSize: 17)
        countLabel.center = CGPoint(x: countView.bounds.width / 2, y: countView.bounds.height / 2)
        countView.addSubview(countLabel)
        
        countButton = UIButton(frame: CGRect(x: UIScreen.main.bounds.width - 68, y: 0, width: 50, height: countViewHeight))
        countButton.setTitle("完成", for: .normal)
        countButton.setTitleColor(newColor(153, 153, 153), for: .normal)
        countButton.addTarget(self, action: #selector(selectedOverAction), for: .touchUpInside)
        countView.addSubview(countButton)
    }
    
    
    /// 照片选择结束
    @objc func selectedOverAction() {
        handlePhotos?(selectedAssets, selectedImages)
        dismissAction()
    }
    
    
    /// 根据选择照片数量动态展示CountView
    ///
    /// - Parameter photoCount: photoCount description
    private func updateCountView(with photoCount: Int) {
        countLabel.text = "\(String(describing: photoCount))/8"
        
        if isShowCountView && photoCount != 0 {
            return
        }
        
        if photoCount == 0 {
            isShowCountView = false
            UIView.animate(withDuration: 0.3, animations: {
                self.countView.frame.origin = CGPoint(x: 0, y: UIScreen.main.bounds.height)
                self.collectionView.contentOffset = CGPoint(x: 0, y: self.collectionView.contentOffset.y - self.countViewHeight)
            })
        } else {
            isShowCountView = true
            UIView.animate(withDuration: 0.3, animations: {
                self.countView.frame.origin = CGPoint(x: 0, y: UIScreen.main.bounds.height - self.countViewHeight)
                self.collectionView.contentOffset = CGPoint(x: 0, y: self.collectionView.contentOffset.y + self.countViewHeight)
            })
        }
    }
    
    /// 添加取消按钮
    private func addCancleItem() {
        let barItem = UIBarButtonItem(title: "取消", style: .plain, target: self, action: #selector(dismissAction))
        navigationItem.rightBarButtonItem = barItem
    }
    @objc func dismissAction() {
        dismiss(animated: true, completion: nil)
    }
    
    // 展示选择数量的视图
    
    
    // MARK: PHAsset Caching
    
    /// 重置图片缓存
    private func resetCachedAssets() {
        imageManager.stopCachingImagesForAllAssets()
        previousPreheatRect = .zero
    }
    
    /// 更新图片缓存设置
    fileprivate func updateCachedAssets() {
        // 视图可访问时才更新
        guard isViewLoaded && view.window != nil else {
            return
        }
        
        // 预加载视图的高度是可见视图的两倍,这样滑动时才不会有阻塞
        let visibleRect = CGRect(origin: collectionView.contentOffset, size: collectionView.bounds.size)
        let preheatRect = visibleRect.insetBy(dx: 0, dy: -0.5 * visibleRect.height)
        
        // 只有可见视图与预加载视图有明显不同时,才会更新
        let delta = abs(preheatRect.maxY - previousPreheatRect.maxY)
        guard delta > view.bounds.height / 3 else {
            return
        }
        
        
        // 计算 assets 用来开始和结束缓存
        let (addedRects, removeRects) = differencesBetweenRects(previousPreheatRect, preheatRect)
        let addedAssets = addedRects
            .flatMap { rect in collectionView.indexPathsForElements(in: rect)}
            .map { indexPath in fetchAllPhtos.object(at: indexPath.item) }
        let removedAssets = removeRects
            .flatMap { rect in collectionView.indexPathsForElements(in: rect) }
            .map { indexPath in fetchAllPhtos.object(at: indexPath.item) }
        
        // 更新图片缓存
        imageManager.startCachingImages(for: addedAssets, targetSize: thumnailSize, contentMode: .aspectFill, options: nil)
        imageManager.stopCachingImages(for: removedAssets, targetSize: thumnailSize, contentMode: .aspectFill, options: nil)
        
        // 保存最新的预加载尺寸用来和后面的对比
        previousPreheatRect = preheatRect
    }
    
    
    /// 计算新旧位置的差值
    ///
    /// - Parameters:
    ///   - old: old description
    ///   - new: new description
    /// - Returns: return value description
    private func differencesBetweenRects(_ old: CGRect, _ new: CGRect) -> (added: [CGRect], removed: [CGRect]) {
        
        // 新旧有交集
        if old.intersects(new) {
            
            // 增加值
            var added = [CGRect]()
            if new.maxY > old.maxY {
                added += [CGRect(x: new.origin.x, y: old.maxY, width: new.width, height: new.maxY - old.maxY)]
            }
            if new.minY < old.minY {
                added += [CGRect(x: new.origin.x, y: new.minY, width: new.width, height: old.minY - new.minY)]
            }
            
            // 移除值
            var removed = [CGRect]()
            if new.maxY < old.maxY {
                removed += [CGRect(x: new.origin.x, y: new.maxY, width: new.width, height: old.maxY - new.maxY)]
            }
            if new.minY > old.minY {
                removed += [CGRect(x: new.origin.x, y: old.minY, width: new.width, height: new.minY - old.minY)]
            }
            
            return (added, removed)
        }
        
        // 没有交集
        return ([new], [old])
    }
    
}

extension NAPublishAssetViewController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return fetchAllPhtos.count
    }
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: GridViewCell.cellIdentifier, for: indexPath) as! GridViewCell
        
        let asset = fetchAllPhtos.object(at: indexPath.item)
        cell.representAssetIdentifier = asset.localIdentifier
        // 从缓存中取出图片
        imageManager.requestImage(for: asset, targetSize: thumnailSize, contentMode: .aspectFill, options: nil) { img, _ in
            
            // 代码执行到这里时cell可能已经被重用了,所以设置标识用来展示
            if cell.representAssetIdentifier == asset.localIdentifier {
                cell.thumbnailImage = img
            }
        }
        
        // 防止重复
        if isOnlyOne {
            cell.hiddenIcons()
        } else {
            cell.cellIsSelected = flags[indexPath.item]
            cell.handleSelectionAction = { isSelected in
                
                // 判断是否超过最大值
                if self.selectedAssets.count > self.count - 1 && !cell.cellIsSelected {
                    self.showAlert(with: "haha")
                    cell.selectedButton.isSelected = false
                    return
                }
                
                self.flags[indexPath.item] = isSelected
                cell.cellIsSelected = isSelected
                
                if isSelected {
                    self.selectedAssets.append(self.fetchAllPhtos.object(at: indexPath.item))
                    self.selectedImages.append(cell.thumbnailImage!)
                } else {
                    let deleteIndex1 = self.selectedAssets.index(of: self.fetchAllPhtos.object(at: indexPath.item))
                    self.selectedAssets.remove(at: deleteIndex1!)
                    
                    let deleteIndex2 = self.selectedImages.index(of: cell.thumbnailImage!)
                    self.selectedImages.remove(at: deleteIndex2!)
                }
            }
        }
        
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        guard isOnlyOne else {
            return
        }
        let currentCell = collectionView.cellForItem(at: indexPath) as! GridViewCell
        handlePhotos?([fetchAllPhtos.object(at: indexPath.item)], [currentCell.thumbnailImage!])
        dismissAction()
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        updateCachedAssets()
    }
    
    func showAlert(with title: String) {
        let alertVC = UIAlertController(title: "最多只能选择 \(count) 张图片", message: nil, preferredStyle: .alert)
        alertVC.addAction(UIAlertAction(title: "确定", style: .default, handler: nil))
        
        DispatchQueue.main.async {
            self.present(alertVC, animated: true, completion: nil)
        }
    }
}

// MARK: - 👉PHPhotoLibraryChangeObserver
extension NAPublishAssetViewController: PHPhotoLibraryChangeObserver {
    func photoLibraryDidChange(_ changeInstance: PHChange) {
        
    }
}

// MARK: - 👉UICollectionView Extension
private extension UICollectionView {
    
    /// 获取可见视图内的所有对象,用于更高效刷新
    ///
    /// - Parameter rect: rect description
    /// - Returns: return value description
    func indexPathsForElements(in rect: CGRect) -> [IndexPath] {
        let allLayoutAttributes = collectionViewLayout.layoutAttributesForElements(in: rect)!
        return allLayoutAttributes.map { $0.indexPath }
    }
}

// MARK: - 👉GridViewCell
class GridViewCell: UICollectionViewCell {
    
    // MARK: - 👉Properties
    private var cellImageView: UIImageView!
    private var selectionIcon: UIButton!
    var selectedButton: UIButton!
    
    private let slectionIconWidth: CGFloat = 20
    
    static let cellIdentifier = "GridViewCell-Asset"
    
    // MARK: - 👉LifeCycle
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        setupUI()
    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    
    // MARK: - 👉Public
    var representAssetIdentifier: String!
    var thumbnailImage: UIImage? {
        willSet {
            cellImageView?.image = newValue
        }
    }
    
    var cellIsSelected: Bool = false {
        willSet {
            selectionIcon.isSelected = newValue
        }
    }
    
    
    /// 隐藏选择按钮和图标
    func hiddenIcons() {
        selectionIcon.isHidden = true
        selectedButton.isHidden = true
    }
    
    // 点击选择回调
    var handleSelectionAction: ((Bool) -> Void)?
    
    // MARK: - 👉Private
    private func setupUI() {
        // 图片
        cellImageView = UIImageView(frame: bounds)
        cellImageView?.clipsToBounds = true
        cellImageView?.contentMode = .scaleAspectFill
        contentView.addSubview(cellImageView!)
        
        // 选择图标
        selectionIcon = UIButton(frame: CGRect(x: 0, y: 0, width: slectionIconWidth, height: slectionIconWidth))
        selectionIcon.center = CGPoint(x: bounds.width - 2 - selectionIcon.bounds.width / 2, y: selectionIcon.bounds.height / 2)
        selectionIcon.setImage(UIImage.init(named: "ic_select"), for: .normal)
        selectionIcon.setImage(UIImage.init(named: "ic_select"), for: .selected)
        
        contentView.addSubview(selectionIcon)
        
        // 选择按钮
        selectedButton = UIButton(frame: CGRect(x: 0, y: 0, width: bounds.width * 2 / 5, height: bounds.width * 2 / 5))
        selectedButton.center = CGPoint(x: bounds.width - selectedButton.bounds.width / 2, y: selectedButton.bounds.width / 2)
        selectedButton.backgroundColor = .clear
        contentView.addSubview(selectedButton)
        
        selectedButton.addTarget(self, action: #selector(selectionItemAction(btn:)), for: .touchUpInside)
    }
    
    @objc private func selectionItemAction(btn: UIButton) {
        btn.isSelected = !btn.isSelected
        handleSelectionAction?(btn.isSelected)
    }
}

  使用:

 @objc func tapAction(action:UITapGestureRecognizer) -> Void {
        
        let masterVC = NAPublishAlbumTableViewController ()
        let navi = UINavigationController(rootViewController: masterVC)
        masterVC.title = "图片"
        let gridVC = NAPublishAssetViewController()
        gridVC.title = "所有图片"
        navi.pushViewController(gridVC, animated: false)
        
        getCurrentVc()!.present(navi, animated: true)
        
        //多选最多8张
        HandleSelectionPhotosManager.share.getSelectedPhotos(with: 8) { (assets, images) in
            print("\(images)---------\(assets)")
            self.imagesArray = images
            self.reloadCollectionViewConstraints()
        }
        //单选1张
        HandleSelectionPhotosManager.share.getSelectedPhotos(with: 1) { (assets, images) in
            print("\(images)---------\(assets)")
            self.imagesArray = images
            self.reloadCollectionViewConstraints()
        }

效果图: