{"id":1869,"date":"2020-12-27T19:38:43","date_gmt":"2020-12-27T19:38:43","guid":{"rendered":"https:\/\/sezeromer.com\/?p=1869"},"modified":"2023-03-04T13:26:24","modified_gmt":"2023-03-04T10:26:24","slug":"swiftui-camera-gallery","status":"publish","type":"post","link":"https:\/\/sezeromer.com\/en\/swiftui-camera-gallery\/","title":{"rendered":"SwiftUI Camera &#038; Gallery"},"content":{"rendered":"<p>Hello friends, in this article, we will look at topics such as how to take photos with SwiftUI and choose photos from the gallery. There is currently no control on SwiftUI side for these processes, which we use in almost many projects. That&#8217;s why we need to do this with UIKit. When we want to use an element from UIKit, we need to use the <strong>UIViewControllerRepresentable<\/strong> protocol.<\/p>\n<p>First, let&#8217;s make a simple screen design. There will be a design with 2 buttons above. One of them is to take a photo from the camera and the other is to choose a photo from the gallery. Below these buttons, there will be a photo from the camera or gallery.<\/p>\n<p>We define 3 different States on this screen. One of these states is whether the page is opened to take photos and select photos from the gallery. We keep it with the isImagePickerPresenting State. The other one is the last to keep the selected or taken photo, and it will be the option to take a photo from the camera or choose a photo from the gallery. Then we added a simple design.<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;swift&quot;,&quot;mime&quot;:&quot;text\/x-swift&quot;,&quot;theme&quot;:&quot;default&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:true,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">\/\/\r\n\/\/  ContentView.swift\r\n\/\/  swiftui_camera_gallery\r\n\/\/\r\n\/\/  Created by Omer Sezer on 27.12.2020.\r\n\/\/\r\n\r\nimport SwiftUI\r\n\r\nstruct ContentView: View {\r\n    @State var isImagePickerPresenting: Bool = false\r\n    @State var selectedPhoto: UIImage?\r\n    @State var sourceType: UIImagePickerController.SourceType = .photoLibrary\r\n    \r\n    var body: some View {\r\n        VStack {\r\n            HStack {\r\n                if UIImagePickerController.isSourceTypeAvailable(.camera) {\r\n                    Button(action: {\r\n                        sourceType = .camera\r\n                        isImagePickerPresenting = true\r\n                    }, label: {\r\n                        Text(\"Camera\")\r\n                            .foregroundColor(.black)\r\n                    })\r\n                    Spacer()\r\n                }\r\n                \r\n                Button(action: {\r\n                    sourceType = .photoLibrary\r\n                    isImagePickerPresenting = true\r\n                }, label: {\r\n                    Text(\"Gallery\")\r\n                        .foregroundColor(.black)\r\n                })\r\n            }\r\n            .padding()\r\n            Spacer()\r\n            if let selectedPhoto = selectedPhoto {\r\n                Image(uiImage: selectedPhoto)\r\n                    .resizable()\r\n            }\r\n        }\r\n        .sheet(isPresented: $isImagePickerPresenting, content: {\r\n            ImagePicker(sourceType: sourceType, selectedPhoto: $selectedPhoto)\r\n        })\r\n    }\r\n}\r\n\r\nstruct ContentView_Previews: PreviewProvider {\r\n    static var previews: some View {\r\n        ContentView()\r\n    }\r\n}<\/pre>\n<\/div>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1934\" src=\"https:\/\/sezeromer.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-27-at-22.23.27.png\" alt=\"\" width=\"465\" height=\"864\" srcset=\"https:\/\/sezeromer.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-27-at-22.23.27.png 465w, https:\/\/sezeromer.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-27-at-22.23.27-161x300.png 161w\" sizes=\"(max-width: 465px) 100vw, 465px\" \/><\/p>\n<h3><strong>UIViewControllerRepresentable<\/strong><\/h3>\n<p>The most important thing is to create a control by UIKit and communicate it with SwiftUI. I&#8217;m creating an ImagePicker control for this. This structure will take 2 variables. One of them is whether the photo or the gallery will open. The other is the variable created to transfer the captured or captured photo to SwiftUI. <strong>UIViewControllerRepresentable<\/strong> protocol requires 2 functions. Of these, makeUIViewController function, to create a control from UIKit. The other is to update that control. For me, it is enough to just create control here. Then I create a coordinator to connect its delegate. After taking or selecting a photo with this coordinator, I assign it to the selectedPhoto variable.<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;swift&quot;,&quot;mime&quot;:&quot;text\/x-swift&quot;,&quot;theme&quot;:&quot;default&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:true,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">\/\/\r\n\/\/  ImagePicker.swift\r\n\/\/  swiftui_camera_gallery\r\n\/\/\r\n\/\/  Created by Omer Sezer on 27.12.2020.\r\n\/\/\r\n\r\nimport UIKit\r\nimport SwiftUI\r\n\r\nstruct ImagePicker {\r\n    var sourceType: UIImagePickerController.SourceType = .photoLibrary\r\n    @Binding var selectedPhoto: UIImage?\r\n}\r\n\r\nextension ImagePicker: UIViewControllerRepresentable {\r\n    \r\n    func makeUIViewController(context: Context) -&gt; some UIViewController {\r\n        let imagePicker = UIImagePickerController()\r\n        imagePicker.allowsEditing = true\r\n        imagePicker.sourceType = sourceType\r\n        imagePicker.delegate = context.coordinator\r\n        return imagePicker\r\n    }\r\n    \r\n    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {\r\n        \r\n    }\r\n    \r\n    func makeCoordinator() -&gt; ImagePickerCoordinater {\r\n        ImagePickerCoordinater(self)\r\n    }\r\n}\r\n\r\nclass ImagePickerCoordinater: NSObject  {\r\n    var imagePicker: ImagePicker\r\n    \r\n    init(_ picker: ImagePicker) {\r\n        self.imagePicker = picker\r\n        super.init()\r\n    }\r\n}\r\n\r\nextension ImagePickerCoordinater: UIImagePickerControllerDelegate {\r\n    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {\r\n        if let selectedPhoto = info[.editedImage] as? UIImage ?? info[.originalImage] as? UIImage {\r\n            imagePicker.selectedPhoto = selectedPhoto\r\n        } else {\r\n            imagePicker.selectedPhoto = nil\r\n        }\r\n        \r\n        picker.dismiss(animated: true, completion: nil)\r\n    }\r\n}\r\n\r\nextension ImagePickerCoordinater: UINavigationControllerDelegate { }<\/pre>\n<\/div>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1935\" src=\"https:\/\/sezeromer.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-27-at-22.23.36.png\" alt=\"\" width=\"465\" height=\"864\" srcset=\"https:\/\/sezeromer.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-27-at-22.23.36.png 465w, https:\/\/sezeromer.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-27-at-22.23.36-161x300.png 161w\" sizes=\"(max-width: 465px) 100vw, 465px\" \/><\/p>\n<p>You can reach the project <a href=\"https:\/\/github.com\/omersezer\/swiftui-projects\">here<\/a>. If you have questions, you can reach it by e-mail or comment. Good work.<\/p>","protected":false},"excerpt":{"rendered":"<p>Hello friends, in this article, we will look at topics such as how to take photos with SwiftUI and choose photos from the gallery. There is currently no control on SwiftUI side for these processes, which we use in almost many projects. That&#8217;s why we need to do this with UIKit. When we want to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1935,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[327,706],"tags":[159,758,152,759,148,328,707,760],"class_list":["post-1869","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-swift","category-swiftui","tag-camera","tag-gallery","tag-image","tag-imagepicker","tag-picker","tag-swift","tag-swiftui","tag-uiviewcontrollerrepresentable"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/sezeromer.com\/en\/wp-json\/wp\/v2\/posts\/1869"}],"collection":[{"href":"https:\/\/sezeromer.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sezeromer.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sezeromer.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sezeromer.com\/en\/wp-json\/wp\/v2\/comments?post=1869"}],"version-history":[{"count":6,"href":"https:\/\/sezeromer.com\/en\/wp-json\/wp\/v2\/posts\/1869\/revisions"}],"predecessor-version":[{"id":2661,"href":"https:\/\/sezeromer.com\/en\/wp-json\/wp\/v2\/posts\/1869\/revisions\/2661"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sezeromer.com\/en\/wp-json\/wp\/v2\/media\/1935"}],"wp:attachment":[{"href":"https:\/\/sezeromer.com\/en\/wp-json\/wp\/v2\/media?parent=1869"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sezeromer.com\/en\/wp-json\/wp\/v2\/categories?post=1869"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sezeromer.com\/en\/wp-json\/wp\/v2\/tags?post=1869"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}