I have a simple form with textfields and image picker, user can upload it to Firebase.
How to let @DocumentID = ...
in Storage section?
Purpose: I need the image to be saved as a link in one document. At the moment the image is saved only in Storage. How to do it correctly?
All attempts led me to the fact that pic
is created as a separate document in the database, and not inside same document.
Button: Done -[AddItemView]
@ObservedObject var viewModel = NewItemView()
func handleDoneTapped() {
self.viewModel.handleDoneTapped()
self.uploadImage()
self.dismiss()
}
Storage section -[AddItemView]
@ObservedObject var viewModel = NewItemView()
func uploadImage() {
let storage = Storage.storage().reference()
let picData: Data = pickedImages[0].jpegData(compressionQuality: 0.5)!
// let userId = Auth.auth().currentUser?.uid
let path = "itemImages/\(UUID().uuidString).jpg"
let ref = storage.child(path)
let metadata = StorageMetadata()
metadata.contentType = "image/jpg"
let uploadTask = ref.putData(picData, metadata: metadata, completion: { (storageMetaData, error) in
if error != nil {
print(error?.localizedDescription as Any)
return
}
})
}
All var
s -[SingleItem]
struct SingleItem: Identifiable, Codable {
@DocumentID var id: String? // How I can use it in Storage section?
var title : String
var author : String
var description : String
@ServerTimestamp var createdTime: Timestamp?
var userId : String?
var pic : String
}
enum CodingKeys: String, CodingKey {
case id
case title
case author
case description = ""
case pic
}
Firestore -[NewItemView]
class NewItemView: ObservableObject {
// MARK: - Public properties
@Published var singleitem: SingleItem
@Published var modified = false
// MARK: - Internal properties
private var cancellables = Set<AnyCancellable>()
// MARK: - Constructors
init(singleitem: SingleItem = SingleItem(title: "", author: "", description: "", pic: "")) {
self.singleitem = singleitem
self.$singleitem
.dropFirst()
.sink { [weak self] singleitem in
self?.modified = true
}
.store(in: &self.cancellables)
}
// MARK: - Firestore
private var db = Firestore.firestore()
private func addItem(_ singleitem: SingleItem) {
do {
var addedItem = singleitem
addedItem.userId = Auth.auth().currentUser?.uid
_ = try db.collection("items").addDocument(from: addedItem)
}
catch {
print(error)
}
}
private func updateItem(_ singleitem: SingleItem) {
if let documentID = singleitem.id {
do {
try db.collection("items").document(documentID).setData(from: singleitem)
}
catch {
print(error)
}
}
}
private func updateOrAddItem() {
if singleitem.id != nil {
self.updateItem(self.singleitem)
}
else {
addItem(singleitem)
}
}
func handleDoneTapped() { // And this func I call in Done button
self.updateOrAddItem()
}
}
CodePudding user response:
You created your path
in uploadImage
. You just need to update your object with that path that you statically created.
// You make the path to the image here
let path = "itemImages/\(UUID().uuidString).jpg"
You can do this multiple ways, but you need something like
func uploadImage() {
let storage = Storage.storage().reference()
let picData: Data = pickedImages[0].jpegData(compressionQuality: 0.5)!
let path = "itemImages/\(UUID().uuidString).jpg"
let ref = storage.child(path)
let metadata = StorageMetadata()
metadata.contentType = "image/jpg"
let uploadTask = ref.putData(picData, metadata: metadata, completion: { (storageMetaData, error) in
if error != nil {
print(error?.localizedDescription as Any)
return
} else {
// Upload succeeded with the path you added
// So set the pic variable to the path
self.viewModel.singleItem.pic = path
// Then update the item
self.viewModel.updateOrAddItem()
}
})
}