❸❶ iOS SDK View Controller & Delegate for Picking Up Selections
These are protocols for user selections.
UIImagePickerControllerDelegate & UINavigationControllerDelegate
For UIImagePickerControllerDelegate will show the library window popped up, for taking photos we need UINavigationControllerDelegate. It allows the view controller to respond to navigation-related events if needed, providing a more complete and adaptable implemention.
Privacy — Camera Usage Description
The take photo function can only run on actual simulation.
// Created on 2024/1/16.
import UIKit
import AVKit
// ViewController class conforms to three protocols: UIViewController, UIImagePickerControllerDelegate, and UINavigationControllerDelegate
class ViewController: UIViewController & UIImagePickerControllerDelegate & UINavigationControllerDelegate {
// IBOutlet to connect with the UIImageView in the storyboard
@IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
// IBAction function triggered when the "Select Picture" button is pressed
@IBAction func SelectPixture(_ sender: UIButton) {
// Create an instance of UIImagePickerController
let controller = UIImagePickerController()
// Set the source type to photo library
controller.sourceType = .photoLibrary
// Set the delegate to self, so this view controller will handle image picker events
controller.delegate = self
// Present the image picker controller
present(controller, animated: true)
}
// Function called when the user picks an image from the photo library or camera
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
// Uncomment the following line for testing purposes
// print("selected")
// Extract the selected image from the dictionary
let image = info[.originalImage] as? UIImage
// Set the selected image to the UIImageView
imageView.image = image
// Dismiss the image picker controller
dismiss(animated: true)
}
// IBAction function triggered when the "Camera" button is pressed
@IBAction func pressedCamera(_ sender: Any) {
// Create an instance of UIImagePickerController
let controller = UIImagePickerController()
PHPickerViewControllerDelegate
For picking one or multiple photo selections.
Select Single Photo
Add 2 imageView 1 button.
When segue the imageView choose the Outlet Collection
class ViewController: UIViewController {
@IBOutlet var ImagesArea: [UIImageView]!
Segue Button Action
@IBAction func pressedShot(_ sender: Any) {
}
Add FrameWork
import PhotosUI
Add delegate
class ViewController: UIViewController & PHPickerViewControllerDelegate {
Define the DidFinishPicking Function
extension ViewController: PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true)
let itemProviders = results.map(\.itemProvider)
if let itemProvider = itemProviders.first, itemProvider.canLoadObject(ofClass: UIImage.self) {
let previousImage = self.imageViews.first?.image
itemProvider.loadObject(ofClass: UIImage.self) {[weak self] (image, error) in
DispatchQueue.main.async {
guard let self = self, let image = image as? UIImage, self.imageViews.first?.image == previousImage else { return }
self.imageViews.first?.image = image
}
}
}
}
}
Select Multiple Photo
Add another button and also set the IBAction.
Set selection limits
@IBAction func MultiplePhotos(_ sender: UIButton) {
var configuration = PHPickerConfiguration()
configuration.filter = .images
configuration.selectionLimit = 2
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
present(picker, animated: true)
}
Set Function
extension ViewController: PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true)
let itemProviders = results.map(\.itemProvider)
for (i, itemProvider) in itemProviders.enumerated() where itemProvider.canLoadObject(ofClass: UIImage.self) {
let previousImage = self.imageViews[i].image
itemProvider.loadObject(ofClass: UIImage.self) {[weak self] (image, error) in
DispatchQueue.main.async {
guard let self = self, let image = image as? UIImage, self.imageViews[i].image == previousImage else { return }
self.imageViews[i].image = image
}
}
}
}
}
import UIKit
import PhotosUI
class ViewController: UIViewController & PHPickerViewControllerDelegate {
@IBOutlet var ImagesArea: [UIImageView]!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBAction func pressedShot(_ sender: Any) {
var configuration = PHPickerConfiguration()
configuration.filter = .images
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
present(picker, animated: true)
}
// this function for only 1 photo selection
// func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
// picker.dismiss(animated: true)
//
// let itemProviders = results.map(\.itemProvider)
// if let itemProvider = itemProviders.first, itemProvider.canLoadObject(ofClass: UIImage.self) {
// let previousImage = self.ImagesArea.first?.image
// itemProvider.loadObject(ofClass: UIImage.self) {[weak self] (image, error) in
// DispatchQueue.main.async {
// guard let self = self, let image = image as? UIImage, self.ImagesArea.first?.image == previousImage else { return }
// self.ImagesArea.first?.image = image
// }
// }
// }
// }
@IBAction func MultiplePhotos(_ sender: UIButton) {
var configuration = PHPickerConfiguration()
configuration.filter = .images
configuration.selectionLimit = 2
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
present(picker, animated: true)
}
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true)
let itemProviders = results.map(\.itemProvider)
for (i, itemProvider) in itemProviders.enumerated() where itemProvider.canLoadObject(ofClass: UIImage.self) {
let previousImage = self.ImagesArea[i].image
itemProvider.loadObject(ofClass: UIImage.self) { [weak self] (image, error) in
DispatchQueue.main.async {
guard let self = self, let image = image as? UIImage, self.ImagesArea[i].image == previousImage else { return }
self.ImagesArea[i].image = image
}
}
}
}
}
UIColorPickerViewController
Select Color Button
@IBAction func selectColor(_ sender: UIButton) {
let controller = UIColorPickerViewController()
controller.delegate = self
present(controller, animated: true)
}
Set the Background Color
func colorPickerViewController(_ viewController: UIColorPickerViewController, didSelect color: UIColor, continuously: Bool) {
view.backgroundColor = color
}
UIDocumentPickerViewController
import UniformTypeIdentifiers.
Add new button and IBAction + type shorter and quicker. Also segue an IBOulet for single photo display using.
Display the controller as UIDocumentPickerViewController.
When creating UIDocumentPickerViewController, the Parameter forOpeningContentTypes control the file type hence we assign in [.png, .jpg]. The parameter asCopy we assign true allow us storage the file in the app.
@IBOutlet weak var imageView: UIImageView!
@IBAction func selectFile(_ sender: UIButton) {
let controller = UIDocumentPickerViewController(forOpeningContentTypes: [.png, .jpeg], asCopy: true)
controller.delegate = self
present(controller, animated: true)
}
documentPicker (_ controller: didPickDocumentsAT: )
Set the url for the path selecting photo, after select photo, set the IBOutlet imageView photo.
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
if let url = urls.first,
let image = UIImage(contentsOfFile: url.path) {
imageView.image = image // reconnect the IBOutlet for 1 imageView
}
}
MPMediaPickerController
This can only test in iphone. Can load in Music App puchased music or Applse music if you are a subscriber.
Import MediaPlayer
import MediaPlayer
Add Delegate
+Privacy — Media Library Usage Description
- Get the selected music and play.
func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
let musicPlayer = MPMusicPlayerController.systemMusicPlayer
musicPlayer.setQueue(with: mediaItemCollection)
musicPlayer.play()
mediaPicker.dismiss(animated: true)
}
}
UIFontPickerViewController
extension ViewController: UIFontPickerViewControllerDelegate {
}
Set a outlet Label & Action
@IBOutlet weak var textLabel: UILabel!
@IBAction func selectFont(_ sender: Any) {
let fontConfig = UIFontPickerViewController.Configuration()
fontConfig.includeFaces = true
let fontPicker = UIFontPickerViewController(configuration: fontConfig)
fontPicker.delegate = self
present(fontPicker, animated: true)
}
Set Function for acquiring the Font of Outlet Label.
func fontPickerViewControllerDidPickFont(_ viewController: UIFontPickerViewController) {
if let selectedFontDescriptor = viewController.selectedFontDescriptor {
textLabel.font = UIFont(descriptor: selectedFontDescriptor, size: textLabel.font.pointSize)
}
dismiss(animated: true)
}
CNContactPickerViewController
Based this protocol CNContactPickerDelegate, imoprt ContactsUI
import ContactsUI
extension ViewController: CNContactViewControllerDelegate{
}
Link the button into IBAction, show the CNContactPickerViewController.
@IBAction func selectContact(_ sender: Any) {
let controller = CNContactViewController()
controller.delegate = self
present(controller, animated: true)
}
To Retrieve the name and number of the contact.
extension ViewController: CNContactPickerDelegate{
func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact)
textView.text = contact.givenName
if let phoneNumber = contact.phoneNumbers.first?.value {
textView.text.append(" \(phoneNumber.stringValue)")
}
}
}
UIVideoEditorController
import AVFoundation
extension ViewController: UIVideoEditorControllerDelegate, UINavigationControllerDelegate{
}
Show the UIVideoEditor on IBAction
Put video in the Navigator area.
Back to extension, videoEditorController(_:didSaveEditedVideoToPath:) to acquire the edited video and diaplay on screen.
func videoEditorController(_ editor: UIVideoEditorController, didSaveEditedVideoToPath editedVideoPath: String) {
let player = AVPlayer(url: URL(filePath: editedVideoPath))
let playerLayer = AVPlayerLayer()
playerLayer.frame = CGRect(x: 50, y: 50, width: 200, height: 250)
playerLayer.videoGravity = .resizeAspectFill //videoDisplayMode
playerLayer.player = player //make player with this playLayer CONNECT
view.layer.addSublayer(playerLayer) //let the player on the view layer
player.play() //play the vid
dismiss(animated: true)
}
}
This controller can only be simulated on iPhone.
//
// ViewController.swift
// Practice_UIVideoEditorController
//
// Created by yucian huang on 2024/1/26.
//
import UIKit
import AVFoundation
class ViewController: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func editVideo(_ sender: Any) {
if let path = Bundle.main.path(forResource: "333", ofType: "mp4"),
UIVideoEditorController.canEditVideo(atPath: path) {
let controller = UIVideoEditorController()
controller.videoPath = path
controller.delegate = self
present(controller, animated: true)
}
}
}
extension ViewController: UIVideoEditorControllerDelegate, UINavigationControllerDelegate{
func videoEditorController(_ editor: UIVideoEditorController, didSaveEditedVideoToPath editedVideoPath: String) {
let player = AVPlayer(url: URL(filePath: editedVideoPath))
let playerLayer = AVPlayerLayer()
playerLayer.frame = CGRect(x: 50, y: 50, width: 200, height: 250)
playerLayer.videoGravity = .resizeAspectFill //videoDisplayMode
playerLayer.player = player //make player with this playLayer CONNECT
view.layer.addSublayer(playerLayer) //let the player on the view layer
player.play() //play the vid
dismiss(animated: true)
}
}
Reference: