PHPhotoLibrary showing all photos not only selected - ios

Trying to write a picker for the avatar in my app and when PHAuthorizationStatus is .limited and the user already selected some photos in LimitedLibraryPicker, I'm trying to open the picker in this way
private func openPHPicker() {
DispatchQueue.main.async { [weak self] in
var phPickerConfig = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
phPickerConfig.selectionLimit = 1
let phPickerVC = PHPickerViewController(configuration: phPickerConfig)
phPickerVC.delegate = self
self?.present(phPickerVC, animated: true)
}
}
And the result is that PHPickerViewController opens and shows all of the photos not only accessible.
I want to open picker with only selected at LimitedLibraryPicker photos, only that for which I have access.

Related

iOS PHPickerViewController does not provide Exif/Meta-Data

I am trying to read out some metadata from images which I fetched with the PHPickerViewController.
var config = PHPickerConfiguration()
self.phPicker = PHPickerViewController(configuration: config)
if let picker = self.phPicker {
self.phPicker?.delegate = self
self.present(picker, animated: true) {
self.phPicker = nil
}
}
But the PHPickerResult.assetIdentifier to access those data is always nil.
extension ChatViewController: PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
dismiss(animated: true) {
if results.isEmpty {
return
}
assert(results.first!.assetIdentifier != nil) // fails
}
}
}
The trick is the correct configuration of the PHPickerViewController.
var config = PHPickerConfiguration() // WRONG!
let picker = PHPickerViewController(configuration: config)
According to documentation you have to use the PHPhotoLibrary.
A PHPhotoLibrary provides access to the metadata and image data for
the photos, videos and related content in the user's photo library,
including content from the Camera Roll, iCloud Shared, Photo Stream,
imported, and synced from iTunes.
So just use PHPhotoLibrary in the constructor and everything works fine.
var config = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared()) // CORRECT!
let picker = PHPickerViewController(configuration: config)

Identifying a selection on share sheet?

I am using share sheet to open some of the native apps - i.e. Mail, Reminders, Notes, Messages. Below is my code to open share sheet after clicking on the share button.
I am looking for a way to identify a user click on share sheet i.e. an API that gets called when user selects an option on the share sheet. I searched and couldn't find anything, so not sure if there is a way to identify user selection?
func presentShareSheet(content: String, subject: String = "", shareButton: UIView? = nil, presentingVC: UIViewController? = nil) -> Guarantee<Void> {
return Guarantee { seal in
let itemsToShare: [Any] = [someItems]
let activityViewController = UIActivityViewController(activityItems: itemsToShare, applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView = shareButton
activityViewController.completionWithItemsHandler = { activityType, completed, items, error in
// update color of navigation bar
seal(())
}
if let vc = presentingVC ?? UIApplication.shared.topMostViewController() {
vc.present(activityViewController, animated: true)
} else {
seal(())
}
}
}

How to get all playlist available on apple music to my project

How to get all playlist available on apple music to my project . I want to access all apple music playlist ,Currently I am using MPMediaLibrary get playlist method but not getting any data or error?
`func getUserPlaylist()
{
MPMediaLibrary.requestAuthorization { (status) in
print(status)
}
let lib = MPMediaLibrary()
// let name = "playlist name"
// let id:NSUUID = NSUUID()
// let metadata = MPMediaPlaylistCreationMetadata.init(name: name)
// metadata.authorDisplayName = "author"
// metadata.descriptionText = "description"
lib.getPlaylist(with:id as UUID, creationMetadata: nil) { (playlist, error) in
guard error == nil
else
{
print(error.debugDescription)
return
}
if let currentPlaylist = playlist
{
print(currentPlaylist.name)
}
}
} `
To access Apple's music library, you will need to add the "Privacy - Media Library Usage Description" to your info.plist. Then you need to make your class conform to MPMediaPickerControllerDelegate. To display the Apple Music library, you present the MPMediaPickerController. To add the songs to an array, you implement the didPickMediaItems method of MPMediaPickerControllerDelegate.
class MusicPicker:UIViewController, MPMediaPickerControllerDelegate {
//the songs the user will select
var selectedSongs: [URL]!
//this method is to display the music library. You might call it when a user taps a button to add songs to their playlist
func getSongs() {
var mediaPicker: MPMediaPickerController?
mediaPicker = MPMediaPickerController(mediaTypes: .music)
mediaPicker?.delegate = self
mediaPicker?.allowsPickingMultipleItems = true
mediaPicker?.showsCloudItems = false
//present the music library
present(mediaPicker!, animated: true, completion: nil)
}
//this is called when the user selects songs from the library
func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
//these are the songs that were selected. We are looping over the choices
for mpMediaItem in mediaItemCollection.items {
//the song url, add it to an array
let songUrl = mpMediaItem.assetURL
selectedSongs.append(songURL)
}
//dismiss the Apple Music Library after the user has selected their songs
dismiss(animated: true, completion: nil)
}
//if the user clicks done or cancel, dismiss the Apple Music library
func mediaPickerDidCancel(mediaPicker: MPMediaPickerController) {
dismiss(animated: true, completion: nil)
}
}
I got all the playlist using the below code, I used MPMediaQuery class.
let query: MPMediaQuery = MPMediaQuery.playlists()
let playlists = query.collections
guard playlists != nil else{
return
}
for collection in playlists!{
print(playlists?.description)
}

How to detect user has clicked Don't Allow access to camera

I am using a UIImagePicker to present the users with camera to take photos which will be used in the app.
My problem is that on the first time a user opens the image picker they are presented with a prompt saying: '"my App" Would like to Access your Camera' with two options, Don't allow and OK.
My requirement is that when the user clicks Don't Allow, the Image picker gets dismissed leaving a black view. Is there a way to detect that the user has chosen Don't allow?
Here is my code to present UIImagePicker:
var PhotoPicker:UIImagePickerController = UIImagePickerController()
PhotoPicker.delegate = self
PhotoPicker.sourceType = .Camera
PhotoPicker.cameraFlashMode = .Off
PhotoPicker.showsCameraControls = false
PhotoPicker.cameraDevice = .Rear
self.presentViewController(PhotoPicker, animated: false, completion: nil)
To detect access to your library:
You need to use AssetsLibrary for that. First, import assets library framework:
import AssetsLibrary
Then, request authorization status, and if it is not determined, use blocks to catch those events, like this:
if ALAssetsLibrary.authorizationStatus() == ALAuthorizationStatus.NotDetermined {
let library = ALAssetsLibrary()
library.enumerateGroupsWithTypes(.All, usingBlock: { (group, stop) -> Void in
// User clicked ok
}, failureBlock: { (error) -> Void in
// User clicked don't allow
imagePickerController.dismissViewControllerAnimated(true, completion: nil)
})
}
To detect access to camera:
You need to use AVFoundation for that. First, import avfoundation framework:
import AVFoundation
Then, as previously, request user permission when you go to imagepicker and catch the event.
if AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) == AVAuthorizationStatus.NotDetermined {
AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: { (videoGranted: Bool) -> Void in
// User clicked ok
if (videoGranted) {
// User clicked don't allow
} else {
imagePickerController.dismissViewControllerAnimated(true, completion: nil)
}
})
}
Hope it helps!
In iOS 10, use:
import Photos
let authStatus = PHPhotoLibrary.authorizationStatus()
if authStatus == .notDetermined || authStatus == .denied {
PHPhotoLibrary.requestAuthorization({ (status) in
if status == PHAuthorizationStatus.authorized {
} else {
imagePickerController.dismissViewControllerAnimated(true, completion: nil)
}
})
}
Check out this for detecting camera permission
Presenting camera permission dialog in iOS 8
Use this when user picks Don't Allow.
PhotoPicker.dismissViewControllerAnimated(false, completion: nil)

Select Multiple Images (UIImagePickerController or Photos.app Share UI)

In iPhone OS 3.0, Apple added the ability to share multiple pictures at once using the "Share" button and selecting multiple images (where a checkmark is used).
I'd love to have a UIImagePickerController which lets the user select multiple images at once, rather than having to go one by one. Is there a way to do this, or do I have to wait until they add this feature?
If you are supporting only iOS 14 and up, you can use Apple's PHPickerViewController. It allows multiple image selection (while UIImagePickerController does not).
An additional benefit to using PHPickerViewController vs other libraries listed above is that the user will not need to grant permission to access your photo library.
Try this wonderful API in swift: ImagePicker. As all other image APIs, it is simple to use and it is very well updated.
1.install pod - pod "BSImagePicker", "~> 2.8"
inside info plist add row Privacy - Photo Library Usage Description
3.paste below code inside a .swift file-
import UIKit
import BSImagePicker
import Photos
class MultipleImgViC: UIViewController {
#IBOutlet weak var imageView: UIImageView!
var SelectedAssets = [PHAsset]()
var photoArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func selectImages(_ sender: Any) {
let vc = BSImagePickerViewController()
self.bs_presentImagePickerController(vc, animated: true, select: { (assest: PHAsset) -> Void in
},
deselect: { (assest: PHAsset) -> Void in
}, cancel: { (assest: [PHAsset]) -> Void in
}, finish: { (assest: [PHAsset]) -> Void in
for i in 0..<assest.count
{
self.SelectedAssets.append(assest[i])
}
self.convertAssetToImages()
}, completion: nil)
}
#IBAction func dismissview(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
}
extension MultipleImgViC{
func convertAssetToImages() -> Void {
if SelectedAssets.count != 0{
for i in 0..<SelectedAssets.count{
let manager = PHImageManager.default()
let option = PHImageRequestOptions()
var thumbnail = UIImage()
option.isSynchronous = true
manager.requestImage(for: SelectedAssets[i], targetSize: CGSize(width: 200, height: 200), contentMode: .aspectFill, options: option, resultHandler: {(result,info) -> Void in
thumbnail = result!
})
let data = thumbnail.jpegData(compressionQuality: 0.7)
let newImage = UIImage(data: data!)
self.photoArray.append(newImage! as UIImage)
}
self.imageView.animationImages = self.photoArray
self.imageView.animationDuration = 3.0
self.imageView.startAnimating()
}
}
}
Note :- if pod file give "How to fix “SWIFT_VERSION '3.0' is unsupported, supported versions are: 4.0, 4.2, 5.0” error in Xcode 10.2?
" this error then solve it from this link:- https://stackoverflow.com/a/55901964/8537648
video reference: - https://youtu.be/B1DelPi1L0U
sample image:-
AssetLibrary + UICollectionView ^^
Basically, with StoryBoard, you import aUINavigationController, you change the root controller to anUICollectionViewController (will be your Album list), end add anotherUICollectionViewController (will be your photos list).
Then with Assetlibrary you retrieve user albums and user album content.
I will make a such component as soon as i have some time.
You can use this OpalImagePicker like this (Swift 4):
var imagePicker: OpalImagePickerController!
imagePicker = OpalImagePickerController()
imagePicker.imagePickerDelegate = self
imagePicker.selectionImage = UIImage(named: "aCheckImg")
imagePicker.maximumSelectionsAllowed = 3 // Number of selected images
present(imagePicker, animated: true, completion: nil)
And then implement its delegate:
func imagePickerDidCancel(_ picker: OpalImagePickerController) {
//Cancel action
}
func imagePicker(_ picker: OpalImagePickerController, didFinishPickingImages images: [UIImage]) {
}
No need for a 3rd party library. You can use PHPickerViewController.
https://developer.apple.com/documentation/photokit/phpickerviewcontroller
private func showImagePicker() {
var configuration = PHPickerConfiguration()
configuration.selectionLimit = 5 // Selection limit. Set to 0 for unlimited.
configuration.filter = .images // he types of media that can be get.
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
present(picker, animated: true)
}
Apple introduced PHPickerViewController in iOS14.
Advantages
No additional permission need to be implemented (its private by default)
Supports Multi-selection (limit can also be specified)
Zooming and previewing the selection
Documentation - https://developer.apple.com/documentation/photokit/phpickerviewcontroller
Video - https://developer.apple.com/videos/play/wwdc2020/10652/
Hope this helps!
How about this way:
Open "photos.app" first, select multiple photos , and copy them ;
In your own app, try to retrieve those copies photos;
I knew that there are some apps did like this, but do not know how can achieve step 2.

Resources