问题
Please help, it is driving me nuts. I have a constant in ProfileViewModel (let user: UserModel) The UserModel is Identifiable in UserModel file I also initiate the user: UserModel in ProfileViewModel.
In HomeView I added the (let profileVM: ProfileViewModel) constant This allows me to retrieve a user profile image through "profileVM.user.profileImageURL.
In my MainView I load the HomeView() based on being logged in or not I am asked to pass the profileVM and user let constants within HomeView() giving me an error to run the App.
Please see my code:
MainView.Swift (this is where I am asked for the arguments)
import UIKit
import SwiftUI
import Firebase
struct MainView: View {
@EnvironmentObject var authViewModel: AuthViewModel
@AppStorage("current_status") var profileRegistered = false
var body: some View {
ZStack{
if authViewModel.session != nil && authViewModel.profileRegistered == false {
RegisterView()
} else {
HomeView()
}
if authViewModel.session == nil {
NavigationView{
Login()
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
}
}
}
}
}
HomeView.swift (just the top)
import SwiftUI
import Firebase
import Kingfisher
struct HomeView: View {
@State var showProfile: Bool = false
@State var userSearch: Bool = false
@EnvironmentObject var authViewModel: AuthViewModel
let profileVM: ProfileViewModel
var body: some View {
VStack {
HStack(alignment: .top) {
//BUTTON TO SHOW FOLLOWER SCREEN AND FIND PEOPLE IN THE COMMUNITY
Button(action: { self.userSearch.toggle() }) {
Image(systemName: "person.crop.circle.badge.plus")
.font(.system(size: 30))
.foregroundColor(.black)
}.fullScreenCover(isPresented: $userSearch) {
UserSearch()}
Spacer()
//BUTTON TO OPEN UP PROFILE
Button(action: { self.showProfile.toggle() }) {
KFImage(URL(string: profileVM.user.profileImageURL))
.renderingMode(.original)
.resizable()
.frame(width: 36, height: 36)
.clipShape(Circle())
}.fullScreenCover(isPresented: $showProfile) {
MyProfileView()}
}
.padding(.horizontal)
.padding(.top, 15)
Button(action: {
// logging out...
authViewModel.signOut()
}, label: {
Text("LogOut")
.fontWeight(.heavy)
})
Spacer()
}
}
}
var body: some View {
ProfileViewModel.swift
import SwiftUI
class ProfileViewModel: ObservableObject {
// MARK: - @PROPERTIES
//∆..............................
@Published var isFollowed: Bool = false
let user: UserModel
//∆..............................
// MARK: -∆ Initializer
///∆.................................
init(user: UserModel) {
self.user = user
/// ∆ Will persist if following or not even when you close the app
checkIfUserIsFollowed()
}
///∆.................................
///∆ ........... Class Methods ...........
// MARK: -∆ follow •••••••••
func follow() -> Void {
//∆..........
/// ∆ The current user logged in ID
guard let currentUid = FIREBASE_AUTH.currentUser?.uid else { return }
let followingRef = COLLECTION_FOLLOWING_FIRESTORE.document(currentUid).collection("user-following")
let followersRef = COLLECTION_FOLLOWERS_FIRESTORE.document(currentUid).collection("user-followers")
/// ∆ Updates the following structure when following someone
followingRef.document(user.id).setData([ : ]) { _ in
//∆..........
/// ∆ Updates the followers structure when following someone with the currentUid
followersRef.document(currentUid).setData([ : ]) { _ in
//∆..........
self.isFollowed = true
print("DEBUG: Followed: @\(self.user.lastname)...")
}
}
}/// ∆ END OF: follow
// MARK: -∆ unFollow •••••••••
func unFollow() -> Void {
//∆..........
/// ∆ The current user logged in ID
guard let currentUid = FIREBASE_AUTH.currentUser?.uid else { return }
let followingRef = COLLECTION_FOLLOWING_FIRESTORE.document(currentUid).collection("user-following")
let followersRef = COLLECTION_FOLLOWERS_FIRESTORE.document(currentUid).collection("user-followers")
followingRef.document(user.id).delete { _ in
//∆..........
followersRef.document(currentUid).delete { _ in
//∆..........
self.isFollowed = false
print("DEBUG: UnFollowed: @\(self.user.lastname)...")
}
}
}/// ∆ END OF: unFollow
}
//∆.....................................................
extension ProfileViewModel {
// MARK: -∆ checkIfUserIsFollowed •••••••••
func checkIfUserIsFollowed() -> Void {
//∆..........
guard let currentUid = FIREBASE_AUTH.currentUser?.uid else { return }
let followingRef = COLLECTION_FOLLOWING_FIRESTORE.document(currentUid).collection("user-following")
followingRef.document(user.id).getDocument { snapShot, _ in
//∆..........
guard let isFollowed = snapShot?.exists else { return }
self.isFollowed = isFollowed
}
}
}
UserModel.swift
import SwiftUI
import Firebase
struct UserModel: Identifiable {
// MARK: - ∆@PROPERTIES
//∆..............................
var id = UUID().uuidString
let headline: String
let profileImageURL: String
let firstname: String
let lastname: String
let email: String
let bio: String
var isCurrentUser: Bool {
Auth.auth().currentUser?.uid == self.id
}
//∆..............................
//∆.....................................................
///∆ ........... Initializer ...........
init(dictionary: [String : Any]) {
typealias k = RegistrationKeys
//∆..........
id = dictionary[k.uidKey] as? String ?? ""
headline = dictionary[k.headline] as? String ?? ""
profileImageURL = dictionary[k.profileImageURLKey] as? String ?? ""
firstname = dictionary[k.firstname] as? String ?? ""
lastname = dictionary[k.lastname] as? String ?? ""
email = dictionary[k.emailKey] as? String ?? ""
bio = dictionary[k.bioKey] as? String ?? ""
}
}
RegistrationKeys.swift
import Foundation
struct RegistrationKeys: Hashable {
static let emailKey = "email"
static let headline = "headline"
static let firstname = "firstname"
static let lastname = "lastname"
static let profileImageURLKey = "profileImageURL"
static let bioKey = "bio"
static let uidKey = "uid"
}
Registration function that uses the UserModel data to store in Firebase
// MARK: -∆ registerUser •••••••••
func registerUser(firstname: String, lastname: String, headline: String, bio: String, profileImage: UIImage) -> Void {
//∆..........
// MARK: -∆ (1) Upload Image •••••••••
guard let imageData = profileImage.jpegData(compressionQuality: 0.3) else { return }
/// ∆ Unique identifier for the image being uploaded
let filename = NSUUID().uuidString
let storageRef = Storage.storage().reference().child(filename)
storageRef.putData(imageData, metadata: nil) { _, error in
//∆..........
if let error = error {
print("\nDEBUG: {!!!} [ERROR] Failed to upload image: \(error.localizedDescription) {!!!}")
return
}
/// ∆ Should print out before user is created
print("DEBUG: Successfully uploaded user photo...")
/// ∆ Accessing the image `URL` &
storageRef.downloadURL { url, _ in
//∆..........
guard let profileImageURL = url?.absoluteString else { return }
let uid = FIREBASE_AUTH.currentUser!.uid
// MARK: -∆ (4) Creating our document dictionary with keys & values •••••••••
typealias k = RegistrationKeys
let data: [String : String] = [
k.uidKey: uid,
k.headline : headline,
k.firstname : firstname,
k.lastname : lastname,
k.bioKey : bio,
k.profileImageURLKey : profileImageURL
]
self.uploadCollectionToFirestore(
data: data,
uid: uid,
firstname: firstname,
lastname: lastname,
headline: headline,
bio: bio)
withAnimation{self.profileRegistered = true}
}// ∆ END createUser into firebase
}// ∆ END storageRef.downloadURL
}
}/// ∆ END OF: RegisterView Class
extension AuthViewModel {
// MARK: -∆ ••••••••• registerUser •••••••••
fileprivate func uploadCollectionToFirestore(data: [String : String], uid: String,
firstname: String, lastname: String, headline: String,
bio: String) {
isLoading = true
//∆..........
COLLECTION_USERS_FIRESTORE.document(uid).setData(data) { (err) in
if err != nil{
self.isLoading = false
return
}
print("DEBUG: Successfully signed up user\n")
}
}
回答1:
HomeView as written demands a ProfileViewModel:
let profileVM: ProfileViewModel
MainView as written instantiates HomeView, but doesn't provide that object. Xcode is complaining, perhaps in an ambiguous way without a helpful autocomplete suggestion.
HomeView()
To create a ProfileViewModel, you must provide it a UserModel according to the init you have coded.
init(user: UserModel) {
self.user = user
/// ∆ Will persist if following or not even when you close the app
checkIfUserIsFollowed()
}
So, in MainView, you need to know how to make the correct UserModel or provide some sort of default case that will trigger some reaction.
Based on the comment in the code, you have a persistence service that will spit that user data out for you.
HomeView(profileVM: ProfileVM(user: userObjectFromPersistence)
来源:https://stackoverflow.com/questions/65720362/missing-argument-for-parameter-user-in-call-swiftui