Image recognition CoreMl + SwiftUi…. Issue with view

I’m experiencing an issue with my SwiftUI project that uses Firebase and a CoreML model for image recognition. Despite adding various debug print statements, the process doesn’t proceed beyond the validation step. Below are the details of my setup and the relevant code:

Problem Description
When I attempt to create a new post, the console logs “Post button tapped” and “Fields validated”, but nothing happens afterward. The post is not created, and there are no further console logs to indicate what went wrong. Additionally, I’m getting several CoreGraphics and constraint-related warnings in the console.

Console Output

Model loaded successfully
Loading posts...
User document does not exist or no following data
Loaded 8 fallback posts
> > <0x13de085e0> Gesture: System gesture gate timed out.
> > <0x13de085e0> Gesture: System gesture gate timed out.
Error: this application, or a library it uses, has passed an invalid numeric value (NaN, or not-a-number) to CoreGraphics API and this value is being ignored. Please fix this problem.
If you want to see the backtrace, please set CG_NUMERICS_SHOW_BACKTRACE environmental variable.
Error: this application, or a library it uses, has passed an invalid numeric value (NaN, or not-a-number) to CoreGraphics API and this value is being ignored. Please fix this problem.
If you want to see the backtrace, please set CG_NUMERICS_SHOW_BACKTRACE environmental variable.
Post button tapped
Fields validated

`NewPostAlertState.swift`
import Foundation
import SwiftUI

enum NewPostAlertState: Identifiable {
    case error(String)
    case success(String)
    case confirmation(() -> Void)
    
    var id: String {
        switch self {
        case .error(let message):
            return message
        case .success(let message):
            return message
        case .confirmation:
            return "confirmation"
        }
    }
    
    var alert: Alert {
        switch self {
        case .error(let message):
            return Alert(title: Text("Error"), message: Text(message), dismissButton: .default(Text("OK")))
        case .success(let message):
            return Alert(title: Text("Success"), message: Text(message), dismissButton: .default(Text("OK")))
        case .confirmation(let action):
            return Alert(
                title: Text("Confirmation"),
                message: Text("Are you sure?"),
                primaryButton: .destructive(Text("Delete"), action: action),
                secondaryButton: .cancel()
            )
        }
    }
}

NewPostView.swift


import SwiftUI
import Firebase
import FirebaseFirestore
import FirebaseStorage
import CoreLocation
import Vision
import CoreML

struct NewPostView: View {
    u/EnvironmentObject var userSession: UserSession
    u/EnvironmentObject var viewRouter: ViewRouter
    u/State private var showImagePicker: Bool = false
    u/State private var usingCamera: Bool = false
    u/State private var postImage: UIImage?
    u/State private var postDescription: String = ""
    u/State private var postHashtags: String = ""
    u/State private var postLocation: String = ""
    u/State private var sneakerModel: String = ""
    u/State private var additionalDetails: String = ""
    u/State private var locationManager = CLLocationManager()
    u/State private var activeAlert: NewPostAlertState?
    u/State private var isUploading: Bool = false
    u/State private var showConfirmationAlert: Bool = false
    u/State private var showInvalidImageAlert: Bool = false 

    u/State private var modelLoaded: Bool = false

    var body: some View {
        NavigationView {
            VStack {
                if !modelLoaded {
                    Text("Failed to load the model. Please check your MLModel file.")
                        .foregroundColor(.red)
                        .padding()
                } else {
                    ScrollView {
                        VStack(spacing: 10) {
                            Text("Add Image")
                                .font(.headline)
                                .padding(.top)
                            
                            imageSection
                                .frame(height: 250)
                                .padding(.horizontal)
                            
                            Text("Post Details")
                                .font(.headline)
                                .padding(.top)

                            postDetailsSection
                                .padding(.horizontal)
                        }
                        .padding(.horizontal, 16)
                    }

                    Spacer()

                    postButton
                        .padding()
                        .background(
                            LinearGradient(gradient: Gradient(colors: [Color.white, Color.brown.opacity(0.3)]), startPoint: .top, endPoint: .bottom)
                                .edgesIgnoringSafeArea(.bottom)
                        )
                }
            }
            .navigationTitle("New Post")
            .navigationBarItems(leading: Button(action: {
                viewRouter.goToMain()
            }) {
                HStack {
                    Image(systemName: "chevron.backward")
                    Text("Back")
                }
            })
            .background(
                LinearGradient(gradient: Gradient(colors: [Color.white, Color.brown.opacity(0.3)]), startPoint: .top, endPoint: .bottom)
                    .edgesIgnoringSafeArea(.all)
            )
            .onAppear {
                loadModel()
            }
            .sheet(isPresented: $showImagePicker) {
                ImagePicker(image: $postImage, sourceType: usingCamera ? .camera : .photoLibrary)
            }
            .alert(item: $activeAlert) { alertState in
                alertState.alert
            }
            .alert(isPresented: $showConfirmationAlert) {
                Alert(
                    title: Text("Is this a sneaker image?"),
                    message: Text(""),
                    primaryButton: .default(Text("Yes"), action: validateAndUploadImage),
                    secondaryButton: .cancel(Text("No"), action: {
                        print("Image rejected by user")
                        activeAlert = .error("The selected image is not recognized as a sneaker.")
                    })
                )
            }
            .alert(isPresented: $showInvalidImageAlert) { // Alerta para imagen inválida
                Alert(
                    title: Text("Invalid Image"),
                    message: Text("The selected image is not recognized as a sneaker. Please select another image."),
                    dismissButton: .default(Text("OK"))
                )
            }
        }
    }

    private func loadModel() {
        if let _ = try? VNCoreMLModel(for: SneakerClassifier().model) {
            print("Model loaded successfully")
            modelLoaded = true
        } else {
            print("Failed to load the model")
            modelLoaded = false
        }
    }

    private var imageSection: some View {
        Button(action: {
            showImagePicker = true
            usingCamera = false
        }) {
            ZStack {
                RoundedRectangle(cornerRadius: 15)
                    .fill(Color.gray.opacity(0.2))
                    .frame(maxWidth: .infinity)
                    .overlay(RoundedRectangle(cornerRadius: 15).stroke(Color.gray, lineWidth: 2))

                if let image = postImage {
                    Image(uiImage: image)
                        .resizable()
                        .scaledToFit()
                        .clipShape(RoundedRectangle(cornerRadius: 15))
                } else {
                    VStack {
                        Image(systemName: "camera.fill")
                            .resizable()
                            .scaledToFit()
                            .frame(width: 80, height: 80)
                            .foregroundColor(.gray)
                            .shadow(radius: 10)
                        Text("Tap to add image")
                            .foregroundColor(.gray)
                    }
                }
            }
        }
        .padding()
    }

    private var postDetailsSection: some View {
        VStack(spacing: 10) {
            inputField("Write Description", text: $postDescription, icon: "pencil")
            inputField("Sneaker Model", text: $sneakerModel, icon: "tag")
            inputField("Additional Details", text: $additionalDetails, icon: "info.circle")
            
            VStack(alignment: .leading, spacing: 8) {
                HStack {
                    Image(systemName: "number")
                        .foregroundColor(.gray)
                    TextField("Add hashtags", text: $postHashtags, onCommit: addHashtag)
                        .textFieldStyle(RoundedBorderTextFieldStyle())
                        .padding(.leading, 5)
                        .frame(height: 30)
                }
                .padding()
                .background(Color.white)
                .cornerRadius(10)
                .shadow(radius: 5)
                
                Text("Hashtags: (formattedHashtags)")
                    .font(.caption)
                    .foregroundColor(.gray)
                    .padding(.leading)
            }

            locationField
                .padding()
        }
    }

    private func inputField(_ placeholder: String, text: Binding<String>, icon: String) -> some View {
        HStack {
            Image(systemName: icon)
                .foregroundColor(.gray)
            TextField(placeholder, text: text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .frame(height: 30)
        }
        .padding()
        .background(Color.white)
        .cornerRadius(10)
        .shadow(radius: 5)
    }

    private var locationField: some View {
        Button(action: fetchLocation) {
            HStack {
                Image(systemName: "location.fill")
                Text(postLocation.isEmpty ? "Add Location" : postLocation)
            }
            .padding()
            .foregroundColor(.primary)
            .background(Color.blue.opacity(0.2))
            .cornerRadius(10)
            .shadow(radius: 5)
            .animation(.easeInOut)


        }
    }

    private var postButton: some View {
        Button(action: {
            print("Post button tapped")
            guard validateFields() else {
                print("Validation failed")
                activeAlert = .error("Please fill in all fields.")
                return
            }
            print("Fields validated")
            showConfirmationAlert = true
        }) {
            if isUploading {
                ProgressView()
                    .progressViewStyle(CircularProgressViewStyle(tint: .white))
                    .frame(width: 20, height: 20)
            } else {
                Text("Post")
                    .frame(maxWidth: .infinity)
            }
        }
        .buttonStyle(GradientButtonStyle())
        .padding()
    }

    private func fetchLocation() {
        locationManager.requestWhenInUseAuthorization()
        if let location = locationManager.location {
            let geocoder = CLGeocoder()
            geocoder.reverseGeocodeLocation(location) { places, _ in
                postLocation = places?.first?.locality ?? "Unknown location"
            }
        }
    }

    private func validateAndUploadImage() {
        guard let image = postImage else {
            print("No image to validate")
            activeAlert = .error("Please select an image.")
            return
        }

        print("Validating image")
        // Validar la imagen con el modelo
        validateSneakerImage(image: image) { isValid in
            if isValid {
                print("Image is valid")
                uploadImageAndPost()
            } else {
                print("Image is invalid")
                showInvalidImageAlert = true // Mostrar alerta si la imagen no es válida
            }
        }
    }

    private func validateSneakerImage(image: UIImage, completion: u/escaping (Bool) -> Void) {
        guard let model = try? VNCoreMLModel(for: SneakerClassifier().model) else {
            print("Failed to load model for validation")
            completion(false)
            return
        }

        let request = VNCoreMLRequest(model: model) { request, error in
            guard let results = request.results as? [VNClassificationObservation],
                  let firstResult = results.first else {
                print("No valid results from model")
                completion(false)
                return
            }
            print("Validation result: (firstResult.identifier) with confidence (firstResult.confidence)")
            completion(firstResult.identifier == "sneaker" && firstResult.confidence > 0.8)
        }

        guard let ciImage = CIImage(image: image) else {
            print("Failed to convert UIImage to CIImage")
            completion(false)
            return
        }

        let handler = VNImageRequestHandler(ciImage: ciImage, options: [:])
        DispatchQueue.global(qos: .userInitiated).async {
            do {
                try handler.perform([request])
                print("Image classification request performed")
            } catch {
                print("Failed to perform classification: (error.localizedDescription)")
                completion(false)
            }
        }
    }

    private func uploadImageAndPost() {
        guard let image = postImage, let imageData = image.jpegData(compressionQuality: 0.8) else {
            print("Failed to prepare image for upload")
            activeAlert = .error("Failed to prepare image.")
            return
        }

        print("Uploading image...")
        isUploading = true

        let storageRef = Storage.storage().reference().child("sneaker_images/(UUID().uuidString).jpg")
        storageRef.putData(imageData, metadata: nil) { metadata, error in
            if let error = error {
                print("Error uploading image: (error.localizedDescription)")
                activeAlert = .error("Error uploading image.")
                isUploading = false
                return
            }

            print("Image uploaded, fetching download URL...")
            storageRef.downloadURL { url, error in
                if let error = error {
                    print("Error retrieving image URL: (error.localizedDescription)")
                    activeAlert = .error("Error retrieving image URL.")
                    isUploading = false
                    return
                }

                guard let downloadURL = url else {
                    print("No download URL found")
                    activeAlert = .error("No download URL found.")
                    isUploading = false
                    return
                }
                print("Image download URL retrieved: (downloadURL.absoluteString)")
                createPost(imageUrl: downloadURL.absoluteString)
            }
        }
    }

    private func createPost(imageUrl: String) {
        guard let user = userSession.user else {
            print("User session not found")
            activeAlert = .error("User session not found.")
            isUploading = false
            return
        }

        let hashtagsArray = postHashtags.split(separator: " ").map { String($0).trimmingCharacters(in: .whitespacesAndNewlines) }
        let newPost = SneakerPost(
            imageUrl: imageUrl,
            uploader: user.nickname,
            nickname: user.nickname,
            sneakerModel: sneakerModel,
            description: postDescription,
            hashtags: hashtagsArray,
            uploadDate: Date(),
            replies: [],
            additionalDetails: additionalDetails,
            likes: [],
            comments: []
        )

        print("Creating post...")
        userSession.addNewPost(newPost) { success in
            isUploading = false
            if success {
                print("Post created successfully")
                viewRouter.goToMain()
            } else {
                print("Failed to save post")
                activeAlert = .error("Failed to save post.")
            }
        }
    }

    private func addHashtag() {
        let trimmedHashtag = postHashtags.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !trimmedHashtag.isEmpty else { return }

        var hashtags = postHashtags.split(separator: " ").map(String.init)

        if !trimmedHashtag.hasPrefix("#") {
            hashtags.append("#" + trimmedHashtag)
        } else {
            hashtags.append(trimmedHashtag)
        }

        postHashtags = hashtags.filter { !$0.isEmpty }.joined(separator: " ")
    }

    private func validateFields() -> Bool {
        return !postDescription.isEmpty &&
            !postHashtags.isEmpty &&
            !postLocation.isEmpty &&
            !sneakerModel.isEmpty &&
            !additionalDetails.isEmpty &&
            postImage != nil
    }

    private var formattedHashtags: String {
        postHashtags.split(separator: " ").map { $0.hasPrefix("#") ? $0 : "#($0)" }.joined(separator: " ")
    }
}

struct NewPostView_Previews: PreviewProvider {
    static var previews: some View {
        NewPostView().environmentObject(UserSession()).environmentObject(ViewRouter())
    }
}

Model Loading: The model seems to load correctly based on the console output “Model loaded successfully”. Is there any additional configuration or verification required for the model?

Post Creation Flow: Despite reaching the validation step (“Fields validated”), the post creation process does not proceed. What could be causing the blockage, and how can I debug this further?

CoreGraphics Warnings: There are several warnings about passing an invalid numeric value to CoreGraphics. Could this be related to my issue, and how can I resolve these warnings?

Firebase Setup: Are there any specific Firebase configurations or permissions that might be preventing the post creation from succeeding?

Any help or insights would be greatly appreciated. Thank you!

New contributor

user102623 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật