Protocol-Oriented PickerViewController. You can pick whatever you want from defined data source by you.
- Can pick single(multiple) item(s).
- Can use flexible DataSource.
- Automatic register/dequeue cell inside picker view.
- Support Pre-fetching.
- Can customize using options.
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))
}
}
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()
}
}
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 😄
- Document comment.
- iOS 10.0+
- Xcode 9+
- Swift 4+
- Add the following to your Cartfile:
github "sgr-ksmt/Pick" ~> 0.3
- Run
carthage update
- Add the framework as described.
Details: Carthage Readme
Pick is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'Pick', '~> 0.3'
and run pod install
Download all *.swift
files and put your project.
Change log is here.
- miuP [Core Contributor]
- 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.:muscle:
Pick is under MIT license. See the LICENSE file for more info.