Home > database >  Can someone explain what "extra trailing closure passed in call" means?
Can someone explain what "extra trailing closure passed in call" means?

Time:01-16

I'm receiving the error "Extra trailing closure passed in call" on the authViewModel.fetchUser() function. From what I've gathered researching online this means that fetchuser can't have the trailing closure (the brackets), I am confused about what in my fetchuser function says that it cannot have the {} after the call. Or maybe I'm not understanding the error at all. Thank you in advance!

FeedCellViewModel

import Foundation

class FeedCellViewModel: ObservableObject {
    @Published var posts = [Post]()
    let service = PostService()
    let authViewModel = AuthViewModel()
    
    init() {
        fetchPosts()
    }
    
    func fetchPosts() {
        service.fetchPosts { posts in
            self.posts = posts
            
            for i in 0 ..< posts.count {
                let uid = posts[i].uid
                
                self.authViewModel.fetchUser() { user in
                    self.posts[i].user = user
               }
            }
        }
    }
} 

AuthViewModel

import SwiftUI
import FirebaseAuth
import FirebaseCore
import FirebaseStorage
import FirebaseFirestore
import FirebaseFirestoreSwift

class AuthViewModel: NSObject, ObservableObject {
    @Published var userSession: FirebaseAuth.User?
    @Published var currentUser: User?
    @Published var selectedImage: UIImage?
    @Published var didAuthenticateUser = false
    private var tempUserSession: FirebaseAuth.User?

    
    private let service = UserService()
        
    static let shared = AuthViewModel()
    
    override init() {
        super.init()
        userSession = Auth.auth().currentUser
        
        fetchUser()
    }
    
    func login(withEmail email: String, password: String) {
        Auth.auth().signIn(withEmail: email, password: password) { result, error in
            if let error = error {
                print("DEBUG: Failed to sign in with error \(error.localizedDescription)")
                return
            }
            
            self.userSession = result?.user
            self.fetchUser()
        }
    }
    
    func register(withEmail email: String, password: String, fullname: String) {
        Auth.auth().createUser(withEmail: email, password: password) { result, error in
            if let error = error {
                print("DEBUG: Failed to register with error \(error.localizedDescription)")
                return
            }
            
            guard let user = result?.user else { return }
            self.tempUserSession = user

            
            let data = ["email": email,
                        "fullname": fullname,
                        "uid": user.uid]
            
            COLLECTION_USERS
                .document(user.uid)
                .setData(data) { _ in
                    self.didAuthenticateUser = true
                }
            
            self.uploadProfileImage(self.selectedImage)
            self.fetchUser()
        }
    }
    
    func signOut() {
        // sets user session to nil so we show login view
        self.userSession = nil
        
        // signs user out on server
        try? Auth.auth().signOut()
    }
    
    func uploadProfileImage(_ image: UIImage?) {
        guard let uid = tempUserSession?.uid else { return }

        ImageUploader.uploadImage(image: image) { profileImageUrl in
            Firestore.firestore().collection("users")
                .document(uid)
                .updateData(["profileImageUrl": profileImageUrl]) { _ in
                 self.userSession = self.tempUserSession
                }
        }
    }
    
    func fetchUser() {
        guard let uid = userSession?.uid else { return }
        
        COLLECTION_USERS.document(uid).getDocument { snapshot, _ in
            guard let user = try? snapshot?.data(as: User.self) else { return }
            self.currentUser = user
        }
    }
}

CodePudding user response:

You're seeing this error because your fetchUser() function doesn't take a closure parameter (or any parameters for that matter).

A trailing closure is just a nicer way of passing a closure as a parameter, given it's the last parameter to a method. Try running this example in a playground to get a feel for this:

func hello(closure: () -> Void) {
  print("calling closure")
  closure()
  print("finished")
}

// these are the same
hello(closure: { print("hello!!") })
hello { print("hello!!") }

If you want to provide the user in a closure to the caller, return the user as a parameter to the closure in addition to setting the currentUser.

func fetchUser(finishedFetching: @escaping (User) -> Void) {
  guard let uid = userSession?.uid else { return }
        
  COLLECTION_USERS.document(uid).getDocument { snapshot, _ in
    guard let user = try? snapshot?.data(as: User.self) else { return }
    self.currentUser = user
    finishedFetching(user)
  }
}

Read more about closures in the Swift language guide. They are essentially unnamed functions that you can store and pass around. You'll learn there why I marked the our closure as @escaping.

  • Related