Hi, I'm doing a practise project about Image Filter. I would like to show a horizontal scrollView at the bottom of screen which showing all filtered images, but it displayed an error when using ForEach.
Error: Referencing initializer 'init(_:content:)' on 'ForEach' requires that 'Image' conform to 'Identifiable'
Can someone help me out before Christmas?
Happy holiday! Wish all of you have a wonderful Christmas!
ContentView
import CoreImage
import CoreImage.CIFilterBuiltins
import SwiftUI
struct ContentView: View {
@State private var showingImagePicker = false
@State private var image: Image?
@State private var inputImage: UIImage?
@State private var showingFilterView = false
@State private var filterAmount = 0.5
@State private var filters: [CIFilter] = [
CIFilter.sepiaTone(),
CIFilter.vignette(),
CIFilter.discBlur(),
CIFilter.pixellate(),
CIFilter.crystallize(),
CIFilter.twirlDistortion()
]
let context = CIContext()
var body: some View {
ZStack {
Image("background")
.resizable()
.scaledToFill()
.ignoresSafeArea(.all)
VStack {
Button {
showingImagePicker = true
} label: {
VStack {
Image(systemName: "plus.square.fill.on.square.fill")
.resizable()
.frame(width: 40, height: 40)
Text("Add photo")
.font(.title3)
}
.foregroundColor(.white)
}
}
}
.preferredColorScheme(.dark)
.sheet(isPresented: $showingImagePicker) {
ImagePicker(image: $inputImage)
}
.onChange(of: inputImage) { _ in loadImage();loadFilter()}
.navigate(to: FilterView(image: image), when: $showingFilterView)
}
func loadImage() {
guard let inputImage = inputImage else {return}
image = Image(uiImage: inputImage)
showingFilterView = true
}
func loadFilter() {
filters.forEach { (filters) in
guard let inputImage = inputImage else { return }
let beginImage = CIImage(image: inputImage)
filters.setValue(beginImage, forKey: kCIInputImageKey)
guard let outputImage = filters.outputImage else {return}
let cgimg = context.createCGImage(outputImage, from: outputImage.extent)
let uiImage = UIImage(cgImage: cgimg!)
let filteredImage = Image(uiImage: uiImage)
let filterView = FilterView()
filterView.filteredImage.append(filteredImage)
}
}
}
extension View {
/// Navigate to a new view.
/// - Parameters:
/// - view: View to navigate to.
/// - binding: Only navigates when this condition is `true`.
func navigate<NewView: View>(to view: NewView, when binding: Binding<Bool>) -> some View {
NavigationView {
ZStack {
self
//.navigationBarTitle("")
//.navigationBarHidden(true)
NavigationLink(
destination: view,
//.navigationBarTitle(""),
//.navigationBarHidden(true),
isActive: binding
) {
EmptyView()
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
FilterView
import SwiftUI
struct FilterView: View{
@State var image: Image?
@State var filteredImage: [Image] = []
var body: some View {
NavigationView{
ZStack{
Image("background")
.resizable()
.scaledToFill()
.ignoresSafeArea(.all)
VStack {
image?
.resizable()
.scaledToFit()
ScrollView(.horizontal, showsIndicators: false) {
HStack{
ForEach(filteredImage) { image in
Button {
} label: {
image
}
}
}
}
}
}
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button {
save()
} label: {
Image(systemName: "square.and.arrow.down")
}
}
}
}
func save() {
}
}
struct FilterView_Previews: PreviewProvider {
static var previews: some View {
FilterView()
}
}