I have tried uploading a video to firebase but I am running into a error trying to create my post
Cannot convert value of type ‘UIImage.Type’ to expected argument type ‘String’
Button("Post") {
Task {
try await viewModel.uploadPost(text: captionText, videoUrlString: UIImage)
I need help rewriting my code to upload my user post to firebase, How do I use UIImage the selected image as a string to remove this error
The Full Create View Code
struct CreateView: View {
enum LoadState {
case unknown, loading, loaded(Movie), failed
}
@State private var loadState = LoadState.unknown
@State private var selectedPhoto: PhotosPickerItem?
@State private var image: Image?
@State var captionText = ""
@State var imagePickerPresented = false
@StateObject var viewModel = UploadPostViewModel()
@Environment(\.dismiss) var dismiss
@State var uiImage: UIImage?
@Binding var tabIndex: Int
private var user: Userss? {
return ThirdUserService.shared.currentUser
}
var body: some View {
NavigationStack {
VStack {
HStack(alignment: .top) {
RectangularImageSize( size: .small)
VStack(alignment: .leading, spacing: 4) {
Text(user?.username ?? "")
.fontWeight(.semibold)
TextField("Type Something", text: $viewModel.text, axis: .vertical)
Spacer()
}
.font(.footnote)
if !viewModel.text.isEmpty {
Button {
viewModel.text = ""
} label: {
Image(systemName: "xmark")
.resizable()
.frame(width: 12, height: 12)
.foregroundColor(.gray)
Button(action: {
viewModel.selectedImage = nil
}, label: {
Image(systemName: "xmark")
.resizable()
.scaledToFit()
.frame(width: 10, height: 10)
.padding(8)
})
.background(Color(.gray))
.foregroundColor(.white)
.clipShape(Circle())
}
.padding(8)
Spacer()
} else {
if viewModel.text.isEmpty {
PhotosPicker(
selection: $viewModel.selectedImage,
matching: .any(of: [.images,.videos, .not(.livePhotos)]),
photoLibrary: .shared()) {
Image(systemName: "photo")
}
}
}
Spacer()
}
.padding()
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("Cancel") {
dismiss()
}
.font(.subheadline)
.foregroundStyle(Color.black)
}
ToolbarItem(placement: .navigationBarTrailing) {
Button("Post") {
Task {
try await viewModel.uploadPost(text: captionText, videoUrlString: UIImage)
dismiss()
}
}
The UploadViewModel
class UploadPostViewModel: ObservableObject {
@Published var didUploadPost = false
@Published var isLoading = false
@Published var error: Error?
@Published var text = ""
@Published var videos = [Video]()
@Published var mediaPreview: Movie?
@Published var profileImage: Image?
@Published var selectedImage: PhotosPickerItem? {
didSet { Task { await loadImage(fromItem: selectedImage)
Task { await uploadVideo(fromItem: selectedImage) }
} }
}
private var uiImage: UIImage?
func uploadPost(text: String, videoUrlString: String) async throws {
guard let uid = Auth.auth().currentUser?.uid else { return }
var imageUrl: String? = nil
if let image = uiImage {
imageUrl = try await ImageUploader.uploadImage(image: image , type: .post)
guard let url = URL(string: videoUrlString) else { return }
guard let videoUrl = try await VideoUploader.uploadVideoToStorage(withUrl: url) else { return }
let post = Post(
ownerUid: uid,
text: text,
videoUrl: videoUrl, likes: 0,replyCount: 23, imageUrl:imageUrl,
timestamp: Timestamp()
)
try await PostService.uploadPost(post)
self.didUploadPost = true
}
}
func uploadVideo(fromItem item: PhotosPickerItem?) async {
guard let item = item else { return }
do {
guard let movie = try await item.loadTransferable(type: Movie.self) else { return }
self.mediaPreview = movie
} catch {
print("DEBUG: Failed with error \(error.localizedDescription)")
}
}
func fetchVideos() async throws {
let snapshot = try await Firestore.firestore().collection("videos").getDocuments()
self.videos = snapshot.documents.compactMap({ try? $0.data(as: Video.self) })
}
PostService
import Foundation
import Firebase
import FirebaseFirestoreSwift
struct PostService {
static func uploadPost(_ post: Post) async throws {
guard let postData = try? Firestore.Encoder().encode(post) else { return }
do{
let ref = try await FirestoreConstants.PostsCollection.addDocument(data: postData)
try await updateUserFeedsAfterPost(postId: ref.documentID)
} catch {
print("---> \(error)")
}
}
static func fetchPost(withId id: String) async throws -> Post {
let postSnapshot = try await FirestoreConstants.PostsCollection.document(id).getDocument()
let post = try postSnapshot.data(as: Post.self)
return post
}
static func fetchUserPosts(user: Userss) async throws -> [Post] {
let snapshot = try await FirestoreConstants.PostsCollection.whereField("ownerUid", isEqualTo: user.id).getDocuments()
var posts = snapshot.documents.compactMap({try? $0.data(as: Post.self )})
for i in 0 ..< posts.count {
posts[i].user = user
}
return posts
}
}
extension PostService {
static func likePost(_ post: Post) async throws {
guard let uid = Auth.auth().currentUser?.uid else { return }
guard let postId = post.id else { return }
async let _ = try await FirestoreConstants.PostsCollection.document(postId).collection("post-likes").document(uid).setData([:])
async let _ = try await FirestoreConstants.PostsCollection.document(postId).updateData(["likes": post.likes + 1])
async let _ = try await FirestoreConstants.UserCollection.document(uid).collection("user-likes").document(postId).setData([:])
}
static func unlikePost(_ post: Post) async throws {
guard post.likes > 0 else { return }
guard let uid = Auth.auth().currentUser?.uid else { return }
guard let postId = post.id else { return }
async let _ = try await FirestoreConstants.PostsCollection.document(postId).collection("post-likes").document(uid).delete()
async let _ = try await FirestoreConstants.UserCollection.document(uid).collection("user-likes").document(postId).delete()
async let _ = try await FirestoreConstants.PostsCollection.document(postId).updateData(["likes": post.likes - 1])
}
static func checkIfUserLikedPost(_ post: Post) async throws -> Bool {
guard let uid = Auth.auth().currentUser?.uid else { return false }
guard let postId = post.id else { return false }
let snapshot = try await FirestoreConstants.UserCollection.document(uid).collection("user-likes").document(postId).getDocument()
return snapshot.exists
}
}
// MARK: - Feed Updates
extension PostService {
private static func updateUserFeedsAfterPost(postId: String) async throws {
guard let uid = Auth.auth().currentUser?.uid else { return }
let followersSnapshot = try await FirestoreConstants.FollowersCollection.document(uid).collection("user-followers").getDocuments()
for document in followersSnapshot.documents {
try await FirestoreConstants
.UserCollection
.document(document.documentID)
.collection("user-feed")
.document(postId).setData([:])
}
try await FirestoreConstants.UserCollection.document(uid).collection("user-feed").document(postId).setData([:])
}
}
FirestoreConstants
import Firebase
struct FirestoreConstants {
private static let Root = Firestore.firestore()
static let UserCollection = Root.collection("users")
static let PostsCollection = Root.collection("posts")
static let ThreadsCollection = Root.collection("threads")
static let FollowersCollection = Root.collection("followers")
static let FollowingCollection = Root.collection("following")
static let RepliesCollection = Root.collection("replies")
static let ActivityCollection = Root.collection("activity")
static let MessagesCollection = Root.collection("messages")
}
Post
import FirebaseFirestoreSwift
import Firebase
struct Post: Identifiable, Hashable, Codable {
@DocumentID var id: String?
let ownerUid: String
let text: String
let videoUrl: String
var likes: Int
var replyCount: Int
let imageUrl: String?
let timestamp: Timestamp
var user: Userss?
var didLike: Bool? = false
}