Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Limit number of image or video #307

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions Example/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17125"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
Expand All @@ -19,7 +20,7 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GFw-cP-rmQ">
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GFw-cP-rmQ">
<rect key="frame" x="143.5" y="318.5" width="88" height="30"/>
<state key="normal" title="Image picker">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
Expand All @@ -28,7 +29,7 @@
<action selector="showImagePicker:" destination="BYZ-38-t0r" eventType="touchUpInside" id="LaC-Tl-d1J"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DzO-ex-PdY">
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DzO-ex-PdY">
<rect key="frame" x="114.5" y="356.5" width="146" height="30"/>
<constraints>
<constraint firstAttribute="width" constant="146" id="Cd2-rJ-ekE"/>
Expand All @@ -41,7 +42,7 @@
<action selector="showCustomImagePicker:" destination="BYZ-38-t0r" eventType="touchUpInside" id="GKA-nS-l2H"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="zgs-tU-5p9">
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="zgs-tU-5p9">
<rect key="frame" x="71.5" y="394.5" width="232" height="30"/>
<constraints>
<constraint firstAttribute="width" constant="232" id="IRj-9r-lbP"/>
Expand All @@ -52,12 +53,21 @@
<action selector="showImagePickerWithSelectedAssets:" destination="BYZ-38-t0r" eventType="touchUpInside" id="m00-0a-bkf"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ywf-iF-6QR">
<rect key="frame" x="66" y="432.5" width="243" height="30"/>
<state key="normal" title="Image picker limit 2 images, 1 video"/>
<connections>
<action selector="showImagePickerWithLimit:" destination="BYZ-38-t0r" eventType="touchUpInside" id="chb-F8-vjn"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="zgs-tU-5p9" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="0A6-aX-1jb"/>
<constraint firstAttribute="centerX" secondItem="DzO-ex-PdY" secondAttribute="centerX" id="EZn-Ed-pHh"/>
<constraint firstItem="zgs-tU-5p9" firstAttribute="top" secondItem="DzO-ex-PdY" secondAttribute="bottom" constant="8" id="GUE-MX-lLP"/>
<constraint firstItem="Ywf-iF-6QR" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="JYd-Ph-njS"/>
<constraint firstItem="Ywf-iF-6QR" firstAttribute="top" secondItem="zgs-tU-5p9" secondAttribute="bottom" constant="8" id="VjK-Iu-ymf"/>
<constraint firstAttribute="centerY" secondItem="GFw-cP-rmQ" secondAttribute="centerY" id="XmI-RH-XSN"/>
<constraint firstItem="DzO-ex-PdY" firstAttribute="top" secondItem="GFw-cP-rmQ" secondAttribute="bottom" constant="8" id="j2M-qn-wIK"/>
<constraint firstAttribute="centerX" secondItem="GFw-cP-rmQ" secondAttribute="centerX" id="vJT-bW-R2W"/>
Expand All @@ -69,4 +79,9 @@
<point key="canvasLocation" x="138" y="134"/>
</scene>
</scenes>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
58 changes: 55 additions & 3 deletions Example/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class ViewController: UIViewController {
let imagePicker = ImagePickerController()
imagePicker.settings.selection.max = 5
imagePicker.settings.theme.selectionStyle = .numbered
imagePicker.settings.fetch.assets.supportedMediaTypes = [.image, .video]
imagePicker.settings.fetch.assets.supportedMediaTypes = [.image(), .video()]
imagePicker.settings.selection.unselectOnReachingMax = true

let start = Date()
Expand All @@ -52,7 +52,7 @@ class ViewController: UIViewController {
let imagePicker = ImagePickerController()
imagePicker.settings.selection.max = 1
imagePicker.settings.selection.unselectOnReachingMax = true
imagePicker.settings.fetch.assets.supportedMediaTypes = [.image, .video]
imagePicker.settings.fetch.assets.supportedMediaTypes = [.image(), .video()]
imagePicker.albumButton.tintColor = UIColor.green
imagePicker.cancelButton.tintColor = UIColor.red
imagePicker.doneButton.tintColor = UIColor.purple
Expand Down Expand Up @@ -99,7 +99,7 @@ class ViewController: UIViewController {
})

let imagePicker = ImagePickerController(selectedAssets: evenAssets)
imagePicker.settings.fetch.assets.supportedMediaTypes = [.image]
imagePicker.settings.fetch.assets.supportedMediaTypes = [.image()]

self.presentImagePicker(imagePicker, select: { (asset) in
print("Selected: \(asset)")
Expand All @@ -111,5 +111,57 @@ class ViewController: UIViewController {
print("Finished with selections: \(assets)")
})
}

@IBAction func showImagePickerWithLimit(_ sender: Any) {
let imagePicker = ImagePickerController()
imagePicker.settings.selection.max = 5
imagePicker.settings.theme.selectionStyle = .numbered
imagePicker.settings.fetch.assets.supportedMediaTypes = [
.image(max: 2),
.video(max: 1)
]

let start = Date()
imagePicker.imagePickerDelegate = self
self.presentImagePicker(imagePicker, select: { (asset) in
huylv-teko marked this conversation as resolved.
Show resolved Hide resolved
print("Selected: \(asset)")
}, deselect: { (asset) in
print("Deselected: \(asset)")
}, cancel: { (assets) in
print("Canceled with selections: \(assets)")
}, finish: { (assets) in
print("Finished with selections: \(assets)")
}, completion: {
let finish = Date()
print(finish.timeIntervalSince(start))
})

}
}

extension ViewController: ImagePickerControllerDelegate {
func imagePicker(_ imagePicker: ImagePickerController, didSelectAsset asset: PHAsset) {
print("Selected: \(asset)")
}

func imagePicker(_ imagePicker: ImagePickerController, didDeselectAsset asset: PHAsset) {
print("Deselected: \(asset)")
}

func imagePicker(_ imagePicker: ImagePickerController, didFinishWithAssets assets: [PHAsset]) {
print("Canceled with selections: \(assets)")
}

func imagePicker(_ imagePicker: ImagePickerController, didCancelWithAssets assets: [PHAsset]) {
print("Finished with selections: \(assets)")
}

func imagePicker(_ imagePicker: ImagePickerController, didReachSelectionLimit count: Int) {
print("didReachSelectionLimit with count: ", count)
}

func imagePicker(_ imagePicker: ImagePickerController, didReachSelectionLimitForType type: PHAssetMediaType) {
print("didReachSelectionLimitForType: ", type.rawValue)
}
}

4 changes: 4 additions & 0 deletions Sources/Controller/ImagePickerController+Assets.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,8 @@ extension ImagePickerController: AssetsViewControllerDelegate {

pushViewController(previewViewController, animated: true)
}

func assetsViewController(_ assetsViewController: AssetsViewController, didReachSelectionLimit asset: PHAsset) {
imagePickerDelegate?.imagePicker(self, didReachSelectionLimitForType: asset.mediaType)
}
}
26 changes: 0 additions & 26 deletions Sources/Controller/ImagePickerController+Closure.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ import Photos
imagePicker.onCancel = cancel
imagePicker.onFinish = finish

// And since we are using the blocks api. Set ourselfs as delegate
imagePicker.imagePickerDelegate = imagePicker
huylv-teko marked this conversation as resolved.
Show resolved Hide resolved

// Present
self.present(imagePicker, animated: animated, completion: completion)
}
Expand All @@ -70,26 +67,3 @@ extension ImagePickerController {
return PHPhotoLibrary.authorizationStatus()
}
}

/// ImagePickerControllerDelegate closure wrapper
extension ImagePickerController: ImagePickerControllerDelegate {
huylv-teko marked this conversation as resolved.
Show resolved Hide resolved
public func imagePicker(_ imagePicker: ImagePickerController, didSelectAsset asset: PHAsset) {
onSelection?(asset)
}

public func imagePicker(_ imagePicker: ImagePickerController, didDeselectAsset asset: PHAsset) {
onDeselection?(asset)
}

public func imagePicker(_ imagePicker: ImagePickerController, didFinishWithAssets assets: [PHAsset]) {
onFinish?(assets)
}

public func imagePicker(_ imagePicker: ImagePickerController, didCancelWithAssets assets: [PHAsset]) {
onCancel?(assets)
}

public func imagePicker(_ imagePicker: ImagePickerController, didReachSelectionLimit count: Int) {

}
}
5 changes: 5 additions & 0 deletions Sources/Controller/ImagePickerControllerDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,9 @@ public protocol ImagePickerControllerDelegate: class {
/// - Parameter imagePicker: The image picker that selection limit was reached in.
/// - Parameter count: Number of selected assets.
func imagePicker(_ imagePicker: ImagePickerController, didReachSelectionLimit count: Int)

/// Selection limit reach by type
/// - Parameter imagePicker: The image picker that selection limit was reached in.
/// - Parameter type: Type of media which reaches limit.
func imagePicker(_ imagePicker: ImagePickerController, didReachSelectionLimitForType type: PHAssetMediaType)
}
4 changes: 4 additions & 0 deletions Sources/Model/AssetStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,8 @@ import Photos
func index(of asset: PHAsset) -> Int? {
return assets.firstIndex(of: asset)
}

func getCountByType(_ type: PHAssetMediaType) -> Int {
return assets.filter { $0.mediaType == type }.count
}
}
10 changes: 5 additions & 5 deletions Sources/Model/Settings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,11 @@ import Photos
/// Fetch options for assets

/// Simple wrapper around PHAssetMediaType to ensure we only expose the supported types.
public enum MediaTypes {
case image
case video
public enum MediaTypes: Hashable {
case image(max: Int = Int.max)
case video(max: Int = Int.max)

fileprivate var assetMediaType: PHAssetMediaType {
var assetMediaType: PHAssetMediaType {
switch self {
case .image:
return .image
Expand All @@ -137,7 +137,7 @@ import Photos
}
}
}
public lazy var supportedMediaTypes: Set<MediaTypes> = [.image]
public lazy var supportedMediaTypes: Set<MediaTypes> = [.image()]

public lazy var options: PHFetchOptions = {
let fetchOptions = PHFetchOptions()
Expand Down
18 changes: 17 additions & 1 deletion Sources/Scene/Assets/AssetsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ protocol AssetsViewControllerDelegate: class {
func assetsViewController(_ assetsViewController: AssetsViewController, didSelectAsset asset: PHAsset)
func assetsViewController(_ assetsViewController: AssetsViewController, didDeselectAsset asset: PHAsset)
func assetsViewController(_ assetsViewController: AssetsViewController, didLongPressCell cell: AssetCollectionViewCell, displayingAsset asset: PHAsset)
func assetsViewController(_ assetsViewController: AssetsViewController, didReachSelectionLimit asset: PHAsset)
}

class AssetsViewController: UIViewController {
Expand Down Expand Up @@ -195,7 +196,22 @@ extension AssetsViewController: UICollectionViewDelegate {
}

func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
guard store.count < settings.selection.max || settings.selection.unselectOnReachingMax else { return false }
let asset = fetchResult.object(at: indexPath.row)
for type in settings.fetch.assets.supportedMediaTypes {
switch type {
case .image(let max), .video(let max):
if asset.mediaType == type.assetMediaType {
if max <= store.getCountByType(type.assetMediaType) {
self.delegate?.assetsViewController(self, didReachSelectionLimit: asset)
return false
}
}
}
}

guard store.count < settings.selection.max || settings.selection.unselectOnReachingMax else {
return false
}
selectionFeedback.prepare()

return true
Expand Down