{"id":27771722,"url":"https://github.com/dragoncherry/assetspickerviewcontroller","last_synced_at":"2025-04-29T23:00:09.564Z","repository":{"id":49051730,"uuid":"91521666","full_name":"DragonCherry/AssetsPickerViewController","owner":"DragonCherry","description":"Powerfully Customizable - Multiple Photo \u0026 Video Picker Controller","archived":false,"fork":false,"pushed_at":"2022-09-21T03:05:44.000Z","size":3356,"stargazers_count":387,"open_issues_count":21,"forks_count":137,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-04-29T23:00:04.787Z","etag":null,"topics":["assets","customize","image","multiple","photo","picker","swift","video"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DragonCherry.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-05-17T01:46:11.000Z","updated_at":"2025-03-04T12:24:35.000Z","dependencies_parsed_at":"2022-09-10T19:22:24.746Z","dependency_job_id":null,"html_url":"https://github.com/DragonCherry/AssetsPickerViewController","commit_stats":null,"previous_names":[],"tags_count":76,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DragonCherry%2FAssetsPickerViewController","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DragonCherry%2FAssetsPickerViewController/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DragonCherry%2FAssetsPickerViewController/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DragonCherry%2FAssetsPickerViewController/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DragonCherry","download_url":"https://codeload.github.com/DragonCherry/AssetsPickerViewController/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251596666,"owners_count":21615017,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["assets","customize","image","multiple","photo","picker","swift","video"],"created_at":"2025-04-29T23:00:08.202Z","updated_at":"2025-04-29T23:00:09.514Z","avatar_url":"https://github.com/DragonCherry.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Now iOS 14 supports multiple asset picker by default. I recommend use PHPickerViewController from iOS 14 instead of this, it's a much better solution.\n\n## AssetsPickerViewController\n\n[![Version](https://img.shields.io/cocoapods/v/AssetsPickerViewController.svg?style=flat)](http://cocoapods.org/pods/AssetsPickerViewController)\n[![License](https://img.shields.io/cocoapods/l/AssetsPickerViewController.svg?style=flat)](http://cocoapods.org/pods/AssetsPickerViewController)\n[![Platform](https://img.shields.io/cocoapods/p/AssetsPickerViewController.svg?style=flat)](http://cocoapods.org/pods/AssetsPickerViewController)\n\nCustomizable assets picker controller that supports selecting multiple photos and videos, fully written in Swift.\n\n\n## Comment\n\nAssetsPickerViewController acts like Photos App in iOS.\n\nIf you found any bugs - even in develop branch, do not hesitate raise an issue for it.\n\nAny advice, suggestions, and pull requests for new feature will be greatly appreciated.\n\n\n## Just try it in web simulator, don't waste your time\n\nhttps://appetize.io/app/752b6azuj3d3varvmu1hkwuuqm\n\n\n## Screenshots\n\niOS friendly UI for Album \u0026 Asset\n\n![albums_portrait](https://cloud.githubusercontent.com/assets/20486591/26525542/43036a42-4395-11e7-98f0-5bf3f40f923d.PNG)\n![photos_portrait](https://user-images.githubusercontent.com/20486591/66302122-50d12b00-e933-11e9-8594-cf3d9e36d582.png)\n![photos_portrait](https://user-images.githubusercontent.com/20486591/66302136-56c70c00-e933-11e9-910f-9e97cb882d31.png)\n\n\niPad Support\n\n![ipad_landscape](https://user-images.githubusercontent.com/20486591/26968848-89474890-4d3e-11e7-9277-c949511eb491.png)\n\n\nKeeps focusing indexes during orientation change.\n\n![photos_landscape](https://cloud.githubusercontent.com/assets/20486591/26525541/42f44f4e-4395-11e7-80e2-e1dd890a4d16.PNG)\n\n\nHandles empty or no permisson cases.\n\n![no_photos](https://cloud.githubusercontent.com/assets/20486591/26525540/42f25e82-4395-11e7-9dc2-73e04bcc9f00.PNG)\n![no_permission](https://cloud.githubusercontent.com/assets/20486591/26525539/42e6759a-4395-11e7-9bae-1b90f6d3ec44.PNG)\n\n\nCustomizable Album \u0026 Asset Layout\n\n![customize_album](https://cloud.githubusercontent.com/assets/20486591/26616647/1d343c24-460b-11e7-94cf-3b46a0f2e0a2.png)\n![customize_asset](https://cloud.githubusercontent.com/assets/20486591/26616648/1d385746-460b-11e7-9324-62ea634e2fcb.png)\n\n\n3D Touch to Preview\n\n![3d_touch](https://user-images.githubusercontent.com/20486591/27173588-2d2d5a94-51f4-11e7-961e-4ca4759a97c5.PNG)\n\n\n\n## Features Done\n\n- iOS friendly UI for album \u0026 photo controllers\n\n- select album\n\n- select multiple photos and videos\n\n- realtime synchronization for library change in albums \u0026 photos\n\n- option to show/hide empty albums\n\n- option to show/hide \"Hidden\" album\n\n- customizable album cell\n\n- customizable album sorting by PHFetchOptions or filter block\n\n- customizable album filtering by PHFetchOptions or filter block\n\n- customizable asset cell\n\n- customizable asset sorting by PHFetchOptions\n\n- customizable asset filtering by PHFetchOptions\n\n- iPad support\n\n- force(3D) touch to preview - (still, live photo, and video)\n\n- support many languages(German, French, Spanish, Chinese, Japanese, Arabic, Spanish, Korean, Indonesian, Russian, Turkish, Italian, etc)\n\n- set selected assets before present picker controller\n\n- supports dark mode from iOS 13\n\n- takes and auto-selects photo or video took inside picker\n\n- multiple selection by dragging cells (from iOS 13)\n\n- SPM(Swift Package Manager) support\n\n\n## Features To-do\n\n- Cropping image before select\n\n## Basic Usage\n\nTo run the example project, clone the repo, and run `pod install` from the Example directory first.\n\n```swift\n// to show\nlet picker = AssetsPickerViewController()\npicker.pickerDelegate = self\npresent(picker, animated: true, completion: nil)\n\n// to handle\nextension SimpleExampleController: AssetsPickerViewControllerDelegate {\n    \n    func assetsPickerCannotAccessPhotoLibrary(controller: AssetsPickerViewController) {}\n    func assetsPickerDidCancel(controller: AssetsPickerViewController) {}\n    func assetsPicker(controller: AssetsPickerViewController, selected assets: [PHAsset]) {\n        // do your job with selected assets\n    }\n    func assetsPicker(controller: AssetsPickerViewController, shouldSelect asset: PHAsset, at indexPath: IndexPath) -\u003e Bool {\n        return true\n    }\n    func assetsPicker(controller: AssetsPickerViewController, didSelect asset: PHAsset, at indexPath: IndexPath) {}\n    func assetsPicker(controller: AssetsPickerViewController, shouldDeselect asset: PHAsset, at indexPath: IndexPath) -\u003e Bool {\n        return true\n    }\n    func assetsPicker(controller: AssetsPickerViewController, didDeselect asset: PHAsset, at indexPath: IndexPath) {}\n}\n```\n\n## Bonus\n\n### Basic\n\nTo hide empty albums,\n```swift\npickerConfig.albumIsShowEmptyAlbum = false\n```\n\nTo show \"Hidden\" albums,\n```swift\npickerConfig.albumIsShowHiddenAlbum = true\n```\n\nTo set pre-selected assets before present picker,\n```swift\npickerConfig.selectedAssets = self.assets\n```\n\nTo limit selected assets count,\n```swift\nfunc assetsPicker(controller: AssetsPickerViewController, shouldSelect asset: PHAsset, at indexPath: IndexPath) -\u003e Bool {   \n    if controller.selectedAssets.count \u003e 3 {\n        // do your job here\n        return false\n    }\n    return true\n}\n```\n\nTo enable single image select mode, deselect all items when the limit has reached,\n```swift\nfunc assetsPicker(controller: AssetsPickerViewController, shouldSelect asset: PHAsset, at indexPath: IndexPath) -\u003e Bool {   \n    if controller.selectedAssets.count \u003e 0 {\n        controller.photoViewController.deselectAll()\n    }\n    return true\n}\n```\n\nTo automatically deselect oldest selected asset for limited selection count,\n```swift\npickerConfig.assetsMaximumSelectionCount = 5\n```\n\n### Appearence\n\nTo apply custom album cell,\n```swift\npickerConfig.albumCellType = CustomAlbumCell.classForCoder()\n// and implement your own UICollectionViewCell which conforms to AssetsAlbumCellProtocol\n```\n\nTo apply custom asset cell,\n```swift\npickerConfig.assetCellType = CustomAssetCell.classForCoder()\n// and implement your own UICollectionViewCell which conforms to AssetsPhotoCellProtocol\n```\n\n### Sorting\n\nTo sort albums by PHFetchOptions,\n```swift\nlet options = PHFetchOptions()\noptions.sortDescriptors = [NSSortDescriptor(key: \"estimatedAssetCount\", ascending: true)]\n        \npickerConfig.albumFetchOptions = [\n    .smartAlbum: options\n]\n```\n\nTo sort by block for a certain reason,\n```swift\npickerConfig.albumComparator = { (albumType, leftEntry, rightEntry) -\u003e Bool in\n    // return: Is leftEntry ordered before the rightEntry?\n    switch albumType {\n    case .smartAlbum:\n        return leftEntry.album.assetCollectionSubtype.rawValue \u003c rightEntry.album.assetCollectionSubtype.rawValue\n    case .album:\n        return leftEntry.result.count \u003c rightEntry.result.count     // ascending order by asset count\n    case .moment:\n        return true\n    }\n}\n```\n\nTo sort assets by PHFetchOptions,\n```swift\nlet options = PHFetchOptions()\noptions.sortDescriptors = [\n    NSSortDescriptor(key: \"pixelWidth\", ascending: true),\n    NSSortDescriptor(key: \"pixelHeight\", ascending: true)\n]\n\npickerConfig.assetFetchOptions = [\n    .smartAlbum: options\n]\n```\n\n### Filtering\n\nTo filter albums by PHFetchOptions,\n```swift\nlet options = PHFetchOptions()\noptions.predicate = NSPredicate(format: \"estimatedAssetCount = 0\")\npickerConfig.albumFetchOptions = [.smartAlbum: options]\n```\n\nTo filter albums by block for a certain reason,\n```swift\n// return true to include, false to discard.\nlet smartAlbumFilter: ((PHAssetCollection, PHFetchResult\u003cPHAsset\u003e) -\u003e Bool) = { (album, fetchResult) in\n    // filter by album object\n    if album.assetCollectionSubtype == .smartAlbumBursts { return false }\n    if album.assetCollectionSubtype == .smartAlbumTimelapses { return false }\n    if album.assetCollectionSubtype == .smartAlbumFavorites { return false }\n            \n    // filter by fetch result\n    if fetchResult.count \u003e 50 {\n        return true     // only shows albums that contains more than 50 assets\n    } else {\n        return false    //\n    }\n}\npickerConfig.albumFilter = [\n    .smartAlbum: smartAlbumFilter\n]\n```\n\nTo filter assets by PHFetchOptions,\n```swift\nlet options = PHFetchOptions()\noptions.predicate = NSPredicate(format: \"mediaType = %d\", PHAssetMediaType.video.rawValue)\noptions.sortDescriptors = [NSSortDescriptor(key: \"duration\", ascending: true)]\n        \npickerConfig.assetFetchOptions = [\n    .smartAlbum: options,\n    .album: options\n]\n```\n\n### Custom Localization Support\n\nTo set your own custom strings just use the static `customStringConfig` property of  `AssetsPickerConfig` which is of type `AssetsPickerCustomStringConfig`.\n\nOverriding every string\n```swift\nAssetsPickerConfig.customStringConfig = [\n    .cancel: \"Cancel\",\n    .done: \"Done\",\n    .titleAlbums: \"Albums\",\n    .titleSectionMyAlbums: \"My Albums\",\n    .footerPhotos: \"%@ Photos\",\n    .footerVideos: \"%@ Videos\",\n    .footerItems: \"%@ Photos, %@ Videos\",\n    .titleSelectedPhoto: \"%@ Photo Selected\",\n    .titleSelectedPhotos: \"%@ Photos Selected\",\n    .titleSelectedVideo: \"%@ Video Selected\",\n    .titleSelectedVideos: \"%@ Videos Selected\",\n    .titleSelectedItems: \"%@ Items Selected\",\n    .titleNoItems: \"No Photos or Videos\",\n    .messageNoItems: \"You can take photos and videos using the camera, or sync photos and videos onto your %@ using iTunes.\",\n    .messageNoItemsCamera: \"You can sync photos and videos onto your %@ using iTunes.\",\n    .titleNoPermission: \"This app does not have access to your photos or videos.\",\n    .messageNoPermission: \"You can enable access in Privacy Settings.\",\n]\n```\n\nOverriding specific strings\n```swift\nAssetsPickerConfig.customStringConfig = [\n    .titleNoItems: \"No Photos or Videos\",\n    .messageNoItems: \"You can take photos and videos using the camera, or sync photos and videos onto your %@ using iTunes.\",\n    .messageNoItemsCamera: \"You can sync photos and videos onto your %@ using iTunes.\",\n    .titleNoPermission: \"This app does not have access to your photos or videos.\",\n    .messageNoPermission: \"You can enable access in Privacy Settings.\",\n]\n```\n\nTake note: If you don't set the strings correctly these can cause problems.\n\n## Requirements \u0026 Dependency\n\nXcode10.2, Swift 5, iOS 10.0\n\nUses [SnapKit](https://github.com/SnapKit/SnapKit) for creating UI inside library. Thanks to SnapKit development team for doing such a beautiful job.\n\nif your app's deployment target is greater than or equal to 11.0, you can use up-to-date version of SnapKit, otherwise you have to fix SnapKit's version to 5.0.0\n\n\n## Installation\n\nAssetsPickerViewController is available through [CocoaPods](http://cocoapods.org). To install\nit, simply add the following line to your Podfile:\n\n```ruby\npod 'AssetsPickerViewController', '~\u003e 2.0'\n```\n\nSwift 4 is not supported anymore.\n\n## Author\n\nDragonCherry, dragoncherry@naver.com\n\n\n## License\n\nAssetsPickerViewController is available under the MIT license. See the LICENSE file for more info.\n\nMIT License\n\nCopyright (c) 2017 DragonCherry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdragoncherry%2Fassetspickerviewcontroller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdragoncherry%2Fassetspickerviewcontroller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdragoncherry%2Fassetspickerviewcontroller/lists"}