Skip to content
Protocol-Oriented PickerViewController
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Demo
Pick.xcodeproj
Pick.xcworkspace
Pick
Sources
.gitignore
.swift-version
LICENSE
Pick.podspec
README.md

README.md

Pick

Protocol-Oriented PickerViewController. You can pick whatever you want from defined data source by you.

GitHub release Language Carthage Compatible CocoaPods CocoaPodsDL

Feature

  • Can pick single(multiple) item(s).
  • Can use flexible DataSource.
  • Automatic register/dequeue cell inside picker view.
  • Support Pre-fetching.
  • Can customize using options.

How to use

Define Cell

Create Cell that inherit PickableCell.

final class AssetCell: PickableCell {
    private lazy var imageView: UIImageView = {
        let view = UIImageView(frame: .zero)
        view.contentMode = .scaleAspectFill
        view.clipsToBounds = true
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        contentView.addSubview(imageView)
        imageView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
        imageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
        imageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
        imageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private static let fetchOption: PHImageRequestOptions = {
        let options = PHImageRequestOptions()
        options.isSynchronous = true
        options.resizeMode = .exact
        return options
    }()

    private var asset: PHAsset?
    func configure(with asset: PHAsset) {
        self.asset = asset
        PHImageManager.default().requestImage(for: asset, targetSize: CGSize(width: 300, height: 300), contentMode: .aspectFill, options: type(of: self).fetchOption) { [weak self] (image, _) in
            if self?.asset?.localIdentifier == asset.localIdentifier {
                self?.imageView.image = image
            }
        }
    }
}

NOTE: If you want to use custom cell using xib, add code below.

final class AssetCell: PickableCell {
    override class var registerMode: RegisterMode {
        return .nib(defaultNib)
    }

    // or

    override class var registerMode: RegisterMode {
        return .nib(UINib(nibName: "AssetCell", bundle: nil))
    }
}

Define DataSource

Create DataSource that adapts PickableDataSource. You have to implement:

  • typealias Cell
  • typealias Item
  • configure(cell: Cell, at indexPath: IndexPath)
  • var numberOfItems: Int
  • pickItems(indexes: [Int]) -> [Item]
extension PHAsset: Pickable {
    static func ==(lhs: PHAsset, rhs: PHAsset) -> Bool {
        return rhs.localIdentifier == lhs.localIdentifier
    }
}

final class AssetDataSource: NSObject, PickableDataSource {
    typealias Cell = AssetCell
    typealias Item = PHAsset

    var items: [PHAsset]
    var selectedItems: [PHAsset]

    init(selectedItems: [PHAsset] = []) {
        self.selectedItems = selectedItems
        self.items = []
        super.init()
        fetchCameraroll()
        PHPhotoLibrary.shared().register(self)
    }

    func fetchCameraroll() {
        guard let cameraroll = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumUserLibrary, options: nil).firstObject else {
            return
        }
        let assets = PHAsset.fetchAssets(in: cameraroll, options: nil)
        items = assets.objects(at: IndexSet(0..<assets.count))
    }

    func configure(cell: Cell, at indexPath: IndexPath) {
        cell.configure(with: items[indexPath.item])
    }

    var numberOfItems: Int {
        return items.count
    }

    func pickItems(indexes: [Int]) -> [Item] {
        return indexes.map { items[$0] }
    }

    deinit {
        PHPhotoLibrary.shared().unregisterChangeObserver(self)
    }
}

extension AssetDataSource: PHPhotoLibraryChangeObserver {
    func photoLibraryDidChange(_ changeInstance: PHChange) {
        DispatchQueue.main.sync { [weak self] in
            guard let `self` = self else {
                return
            }

            self.fetchCameraroll()
            self.notifyUpdate()
        }
    }
}

In order to update picker view after updating datasource, call notifyUpdate()

final class SomeDataSource: NSObject, PickableDataSource {
    var items: [Int] = []

    func update() {
        items = ...
        notifyUpdate()
    }
}

Setup ViewController

Set data source to PickerViewController(PickerNavigationController). Also you can customize using PickerOptions.

let nav = PickerNavigationController(dataSource: AssetDataSource())
nav.options = {
    let options = PickerOptions()
    options.limitOfSelection = 3
    options.selectedBorderColor = .red
    options.viewTitle = "Camera Roll"
    return options
}()

nav.pickItemsHandler = { assets in
    print(assets)
}

viewController.present(nav, animated: true, completion: nil)

enjoy 😄

Todo

  • Document comment.

Requirements

  • iOS 10.0+
  • Xcode 9+
  • Swift 4+

Installation

Carthage

  • Add the following to your Cartfile:
github "sgr-ksmt/Pick" ~> 0.3
  • Run carthage update
  • Add the framework as described.
    Details: Carthage Readme

CocoaPods

Pick is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'Pick', '~> 0.3'

and run pod install

Manually Install

Download all *.swift files and put your project.

Change log

Change log is here.

Special Thanks 🎉

  • miuP [Core Contributor]

Communication

  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.💪

License

Pick is under MIT license. See the LICENSE file for more info.

You can’t perform that action at this time.