Skip to content

Instantly share code, notes, and snippets.

@kaishin
Created June 10, 2022 07:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kaishin/b338d91db69eeb143319250f64010485 to your computer and use it in GitHub Desktop.
Save kaishin/b338d91db69eeb143319250f64010485 to your computer and use it in GitHub Desktop.
PhotosPicker WWDC Sample
import PhotosUI
import CoreTransferable
import SwiftUI
struct ContentView: View {
@ObservedObject var viewModel: FilterModel = .shared
var body: some View {
NavigationStack {
Gallery()
.navigationTitle("Birthday Filter")
.toolbar {
PhotosPicker(
selection: $viewModel.imageSelection,
matching: .images
) {
Label("Pick a photo", systemImage: "plus.app")
}
Button {
viewModel.applyFilter()
} label: {
Label("Apply Filter", systemImage: "camera.filters")
}
}
}
}
}
struct Gallery: View {
@ObservedObject var viewModel: FilterModel = .shared
var body: some View {
VStack {
switch viewModel.imageState {
case .success(let image):
image
.resizable()
.aspectRatio(contentMode: .fill)
.draggable(image)
case .loading:
ProgressView()
case .empty:
Text("No Photo \(Image(systemName: "photo"))")
.font(.title2)
.fontWeight(.semibold)
Text("Drag and drop a photo or press\n \(Image(systemName: "plus.app")) to choose a photo manually.")
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
case .failure:
Image(systemName: "exclamationmark.triangle.fill")
.font(.system(size: 40))
.foregroundColor(.white)
}
}
.padding()
}
}
@MainActor
class FilterModel: ObservableObject {
static let shared = FilterModel()
enum ImageState {
case empty, loading(Progress), success(Image), failure(Error)
}
@Published private(set) var processedImage: Image?
@Published var imageState: ImageState = .empty
@Published var imageSelection: PhotosPickerItem? = nil {
didSet {
if let imageSelection = imageSelection {
let progress = loadTransferable(from: imageSelection)
imageState = .loading(progress)
} else {
imageState = .empty
}
}
}
func applyFilter() { /* Apply your filter */ }
private func loadTransferable(from imageSelection: PhotosPickerItem) -> Progress {
return imageSelection.loadTransferable(type: Image.self) { result in
DispatchQueue.main.async {
guard imageSelection == self.imageSelection else { return }
switch result {
case .success(let image?):
self.imageState = .success(image)
case .success(nil):
self.imageState = .empty
case .failure(let error):
self.imageState = .failure(error)
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment