Closed TilakMaddy closed 3 years ago
Here is the solution:
`import SwiftUI
struct ContentView : View {
@State private var showYPImagePickerView = true
var body: some View {
VStack {
Button(action: {
self.showYPImagePickerView.toggle()
}, label: { Text("Show Square").font(.title) })
if showYPImagePickerView {
YPImagePickerViewr()
}
}
}
}
struct YPImagePickerView: UIViewControllerRepresentable
{
func makeUIViewController(context: Context) -> YPImagePickerViewController {
let vc = YPImagePickerViewController()
print("\nmakeUIViewController \(vc)")
return vc
}
func updateUIViewController(_ uiViewController: YPImagePickerViewController, context: Context) {
print("updateUIViewController \(uiViewController)")
}
static func dismantleUIViewController(_ uiViewController: YPImagePickerViewController, coordinator: Self.Coordinator) {
print("dismantleUIViewController \(uiViewController)")
}
}
class YPImagePickerViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.green
print("viewDidLoad \(self)")
let picker = YPImagePicker()
picker.didFinishPicking { [unowned picker] items, _ in
if let photo = items.singlePhoto {
print(photo.fromCamera) // Image source (camera or library)
print(photo.image) // Final image selected by the user
print(photo.originalImage) // original image selected by the user, unfiltered
print(photo.modifiedImage) // Transformed image, can be nil
print(photo.exifMeta) // Print exif meta data of original image.
}
picker.dismiss(animated: true, completion: nil)
}
present(picker, animated: true, completion: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
print("viewWillDissapear \(self)")
}
deinit {
print("DEINIT \(self)")
}
}`
yeah but I figured out a much shorter solution. And I am not sure if what you are saying is correct , did you actually test it ?
Yes, I have tested. It works.
Yes, I have tested. It works.
Doesn't work for me. I am still getting the same warning in console. How I can fix it?
Please try the following one: "to call the struct (YummyView(image: Binding<Image?>#>)
`class YPImagePickerUIViewController: UIViewController {
var selectedItems = [YPMediaItem]()
let selectedImageV = UIImageView()
let pickButton = UIButton()
let resultsButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
print("viewDidLoad \(self)")
self.view.backgroundColor = .systemBackground
selectedImageV.contentMode = .scaleAspectFit
selectedImageV.frame = CGRect(x: 0,
y: 0,
width: UIScreen.main.bounds.width,
height: UIScreen.main.bounds.height * 0.45)
view.addSubview(selectedImageV)
pickButton.setTitle("Pick", for: .normal)
pickButton.setTitleColor(.label, for: .normal)
pickButton.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
pickButton.addTarget(self, action: #selector(showPicker), for: .touchUpInside)
view.addSubview(pickButton)
pickButton.center = view.center
resultsButton.setTitle("Show selected", for: .normal)
resultsButton.setTitleColor(.label, for: .normal)
resultsButton.frame = CGRect(x: 0,
y: UIScreen.main.bounds.height - 100,
width: UIScreen.main.bounds.width,
height: 100)
resultsButton.addTarget(self, action: #selector(showResults), for: .touchUpInside)
view.addSubview(resultsButton)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
showPicker()
}
@objc func showResults() {
if selectedItems.count > 0 {
let gallery = YPSelectionsGalleryVC(items: selectedItems) { g, _ in
g.dismiss(animated: true, completion: nil)
}
let navC = UINavigationController(rootViewController: gallery)
self.present(navC, animated: true, completion: nil)
} else {
print("No items selected yet.")
}
}
@objc func showPicker() {
var config = YPImagePickerConfiguration()
config.library.mediaType = .photoAndVideo
config.shouldSaveNewPicturesToAlbum = false
/* Choose the videoCompression. Defaults to AVAssetExportPresetHighestQuality */
config.video.compression = AVAssetExportPresetMediumQuality
config.startOnScreen = .library
/* Defines which screens are shown at launch, and their order.
Default value is `[.library, .photo]` */
config.screens = [.library, .photo]
config.video.libraryTimeLimit = 500.0
/* Adds a Crop step in the photo taking process, after filters. Defaults to .none */
config.showsCrop = .rectangle(ratio: (1/1))
config.wordings.libraryTitle = "Galeri"
/* Defines if the status bar should be hidden when showing the picker. Default is true */
config.hidesStatusBar = false
/* Defines if the bottom bar should be hidden when showing the picker. Default is false */
config.hidesBottomBar = false
config.maxCameraZoomFactor = 2.0
config.library.maxNumberOfItems = 5
config.gallery.hidesRemoveButton = false
//config.library.options = options
config.library.preselectedItems = selectedItems
let picker = YPImagePicker(configuration: config)
/* Change configuration directly */
// YPImagePickerConfiguration.shared.wordings.libraryTitle = "Gallery2"
/* Single Photo implementation. */
picker.didFinishPicking { [unowned picker] items, _ in
self.selectedItems = items
self.selectedImageV.image = items.singlePhoto?.image
picker.dismiss(animated: true, completion: nil)
}
present(picker, animated: true, completion: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
print("viewWillDissapear \(self)")
}
deinit {
print("DEINIT \(self)")
}
}
`
Thank you! It worked
Please try the following one: "to call the struct (YummyView(image: Binding<Image?>#>)
`class YPImagePickerUIViewController: UIViewController {
var selectedItems = [YPMediaItem]() let selectedImageV = UIImageView() let pickButton = UIButton() let resultsButton = UIButton() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground print("viewDidLoad \(self)") self.view.backgroundColor = .systemBackground selectedImageV.contentMode = .scaleAspectFit selectedImageV.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height * 0.45) view.addSubview(selectedImageV) pickButton.setTitle("Pick", for: .normal) pickButton.setTitleColor(.label, for: .normal) pickButton.frame = CGRect(x: 0, y: 0, width: 100, height: 100) pickButton.addTarget(self, action: #selector(showPicker), for: .touchUpInside) view.addSubview(pickButton) pickButton.center = view.center resultsButton.setTitle("Show selected", for: .normal) resultsButton.setTitleColor(.label, for: .normal) resultsButton.frame = CGRect(x: 0, y: UIScreen.main.bounds.height - 100, width: UIScreen.main.bounds.width, height: 100) resultsButton.addTarget(self, action: #selector(showResults), for: .touchUpInside) view.addSubview(resultsButton) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) showPicker() } @objc func showResults() { if selectedItems.count > 0 { let gallery = YPSelectionsGalleryVC(items: selectedItems) { g, _ in g.dismiss(animated: true, completion: nil) } let navC = UINavigationController(rootViewController: gallery) self.present(navC, animated: true, completion: nil) } else { print("No items selected yet.") } } @objc func showPicker() { var config = YPImagePickerConfiguration() config.library.mediaType = .photoAndVideo config.shouldSaveNewPicturesToAlbum = false /* Choose the videoCompression. Defaults to AVAssetExportPresetHighestQuality */ config.video.compression = AVAssetExportPresetMediumQuality config.startOnScreen = .library /* Defines which screens are shown at launch, and their order. Default value is `[.library, .photo]` */ config.screens = [.library, .photo] config.video.libraryTimeLimit = 500.0 /* Adds a Crop step in the photo taking process, after filters. Defaults to .none */ config.showsCrop = .rectangle(ratio: (1/1)) config.wordings.libraryTitle = "Galeri" /* Defines if the status bar should be hidden when showing the picker. Default is true */ config.hidesStatusBar = false /* Defines if the bottom bar should be hidden when showing the picker. Default is false */ config.hidesBottomBar = false config.maxCameraZoomFactor = 2.0 config.library.maxNumberOfItems = 5 config.gallery.hidesRemoveButton = false //config.library.options = options config.library.preselectedItems = selectedItems let picker = YPImagePicker(configuration: config) /* Change configuration directly */ // YPImagePickerConfiguration.shared.wordings.libraryTitle = "Gallery2" /* Single Photo implementation. */ picker.didFinishPicking { [unowned picker] items, _ in self.selectedItems = items self.selectedImageV.image = items.singlePhoto?.image picker.dismiss(animated: true, completion: nil) } present(picker, animated: true, completion: nil) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) print("viewWillDissapear \(self)") } deinit { print("DEINIT \(self)") }
}
`
Without use of a coordinator how do you go about passing back data to the swiftUI View/Navigate to other swiftUI views on completion?
Please try the following one: "to call the struct (YummyView(image: Binding<Image?>#>) `class YPImagePickerUIViewController: UIViewController {
var selectedItems = [YPMediaItem]() let selectedImageV = UIImageView() let pickButton = UIButton() let resultsButton = UIButton() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground print("viewDidLoad \(self)") self.view.backgroundColor = .systemBackground selectedImageV.contentMode = .scaleAspectFit selectedImageV.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height * 0.45) view.addSubview(selectedImageV) pickButton.setTitle("Pick", for: .normal) pickButton.setTitleColor(.label, for: .normal) pickButton.frame = CGRect(x: 0, y: 0, width: 100, height: 100) pickButton.addTarget(self, action: #selector(showPicker), for: .touchUpInside) view.addSubview(pickButton) pickButton.center = view.center resultsButton.setTitle("Show selected", for: .normal) resultsButton.setTitleColor(.label, for: .normal) resultsButton.frame = CGRect(x: 0, y: UIScreen.main.bounds.height - 100, width: UIScreen.main.bounds.width, height: 100) resultsButton.addTarget(self, action: #selector(showResults), for: .touchUpInside) view.addSubview(resultsButton) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) showPicker() } @objc func showResults() { if selectedItems.count > 0 { let gallery = YPSelectionsGalleryVC(items: selectedItems) { g, _ in g.dismiss(animated: true, completion: nil) } let navC = UINavigationController(rootViewController: gallery) self.present(navC, animated: true, completion: nil) } else { print("No items selected yet.") } } @objc func showPicker() { var config = YPImagePickerConfiguration() config.library.mediaType = .photoAndVideo config.shouldSaveNewPicturesToAlbum = false /* Choose the videoCompression. Defaults to AVAssetExportPresetHighestQuality */ config.video.compression = AVAssetExportPresetMediumQuality config.startOnScreen = .library /* Defines which screens are shown at launch, and their order. Default value is `[.library, .photo]` */ config.screens = [.library, .photo] config.video.libraryTimeLimit = 500.0 /* Adds a Crop step in the photo taking process, after filters. Defaults to .none */ config.showsCrop = .rectangle(ratio: (1/1)) config.wordings.libraryTitle = "Galeri" /* Defines if the status bar should be hidden when showing the picker. Default is true */ config.hidesStatusBar = false /* Defines if the bottom bar should be hidden when showing the picker. Default is false */ config.hidesBottomBar = false config.maxCameraZoomFactor = 2.0 config.library.maxNumberOfItems = 5 config.gallery.hidesRemoveButton = false //config.library.options = options config.library.preselectedItems = selectedItems let picker = YPImagePicker(configuration: config) /* Change configuration directly */ // YPImagePickerConfiguration.shared.wordings.libraryTitle = "Gallery2" /* Single Photo implementation. */ picker.didFinishPicking { [unowned picker] items, _ in self.selectedItems = items self.selectedImageV.image = items.singlePhoto?.image picker.dismiss(animated: true, completion: nil) } present(picker, animated: true, completion: nil) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) print("viewWillDissapear \(self)") } deinit { print("DEINIT \(self)") }
} `
Without use of a coordinator how do you go about passing back data to the swiftUI View/Navigate to other swiftUI views on completion?
@Binding is one of SwiftUI’s less used property wrappers, it lets us declare that one value actually comes from elsewhere, and should be shared in both places.
Hello, Thank you all for the informations. I managed to get it working, but when I click on cancel button, the YPImagepicker always reappears as I suppose the Button toggle is still on true. How can I change the toggle state back in my contentView? Thanks a lot!
@TeeAche You have to remove the showPicker()
from viewDidAppear
I believe it is there for testing purposes.
This is my solution. Doesn't produce a blank VC in the background as in the other suggested answers.
struct MediaPicker: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> YPImagePicker {
let config = YPImagePickerConfiguration()
let picker = YPImagePicker(configuration: config)
picker.didFinishPicking { [unowned picker] items, _ in
if let photo = items.singlePhoto {
print(photo.fromCamera) // Image source (camera or library)
print(photo.image) // Final image selected by the user
print(photo.originalImage) // original image selected by the user, unfiltered
print(photo.modifiedImage ?? "not modified !") // Transformed image, can be nil
print(photo.exifMeta ?? "no exif metadata") // Print exif meta data of original image."
}
picker.dismiss(animated: true, completion: nil)
}
return picker
}
func updateUIViewController(_ uiViewController: YPImagePicker, context: Context) {}
typealias UIViewControllerType = YPImagePicker
}
This is my solution. Doesn't produce a blank VC in the background as in the other suggested answers.
struct MediaPicker: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> YPImagePicker { let config = YPImagePickerConfiguration() let picker = YPImagePicker(configuration: config) picker.didFinishPicking { [unowned picker] items, _ in if let photo = items.singlePhoto { print(photo.fromCamera) // Image source (camera or library) print(photo.image) // Final image selected by the user print(photo.originalImage) // original image selected by the user, unfiltered print(photo.modifiedImage ?? "not modified !") // Transformed image, can be nil print(photo.exifMeta ?? "no exif metadata") // Print exif meta data of original image." } picker.dismiss(animated: true, completion: nil) } return picker } func updateUIViewController(_ uiViewController: YPImagePicker, context: Context) {} typealias UIViewControllerType = YPImagePicker }
Good solution, thanks! Do you know how to show my custom 'next' screen after user taps "Next" for MediaPicker (like in Instagram, create new post screen is shown after image selected)?
This is my solution. Doesn't produce a blank VC in the background as in the other suggested answers.
struct MediaPicker: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> YPImagePicker { let config = YPImagePickerConfiguration() let picker = YPImagePicker(configuration: config) picker.didFinishPicking { [unowned picker] items, _ in if let photo = items.singlePhoto { print(photo.fromCamera) // Image source (camera or library) print(photo.image) // Final image selected by the user print(photo.originalImage) // original image selected by the user, unfiltered print(photo.modifiedImage ?? "not modified !") // Transformed image, can be nil print(photo.exifMeta ?? "no exif metadata") // Print exif meta data of original image." } picker.dismiss(animated: true, completion: nil) } return picker } func updateUIViewController(_ uiViewController: YPImagePicker, context: Context) {} typealias UIViewControllerType = YPImagePicker }
Good solution, thanks! Do you know how to show my custom 'next' screen after user taps "Next" for MediaPicker (like in Instagram, create new post screen is shown after image selected)?
Do you mind sharing the rest of your SwiftUI code. I am trying to figure out the following:
Thank you
SwiftUI
struct SampleView: View {
@State private var showMediaPicker: Bool = false
@State private var image: UIImage?
var body: some View {
ZStack {
Button {
showMediaPicker = true
} label: {
Text("Select Picture")
}
.sheet(isPresented: $showMediaPicker) {
MediaPicker(image: $image)
}
if let image = self.image {
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxHeight: 100)
}
}
}
}
MediaPicker.swift
import SwiftUI
import YPImagePicker
struct MediaPicker: UIViewControllerRepresentable {
class Coordinator: NSObject, UINavigationControllerDelegate {
let parent: MediaPicker
init(_ parent: MediaPicker) {
self.parent = parent
}
}
typealias UIViewControllerType = YPImagePicker
@Binding var image: UIImage?
func makeUIViewController(context: Context) -> YPImagePicker {
var config = YPImagePickerConfiguration()
//Common
config.shouldSaveNewPicturesToAlbum = true
config.albumName = "Coding Challenge"
config.showsPhotoFilters = false
config.showsCrop = .none
config.screens = [.library]
config.startOnScreen = .library
config.hidesStatusBar = true
config.hidesBottomBar = true
//library
config.library.mediaType = .photo
config.library.maxNumberOfItems = 1
config.wordings.libraryTitle = "Gallery"
config.library.skipSelectionsGallery = true
config.targetImageSize = .cappedTo(size: 1080)
let picker = YPImagePicker(configuration: config)
picker.didFinishPicking { [unowned picker] items, _ in
if let photo = items.singlePhoto {
self.image = photo.image
}
picker.dismiss(animated: true, completion: nil)
}
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: YPImagePicker, context: Context) {
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
}
References: https://www.hackingwithswift.com/books/ios-swiftui/using-coordinators-to-manage-swiftui-view-controllers https://stackoverflow.com/questions/70962237/use-ypimagepikcer-in-swiftui
Below is an attempt to integrate YPImagePicker into SwiftUI. So when I call
YummyViewController
inside aVStack
in the main body ofContentView
I get the error described belowCONSOLE MESSAGE