【问题标题】:Swift 4 - Display Image from Firebase Storage in TableViewCell/ImageViewSwift 4 - 在 TableViewCell/ImageView 中显示来自 Firebase 存储的图像
【发布时间】:2018-04-30 16:15:20
【问题描述】:

我无法看到来自 Firebase 存储的图片,我只能看到未填充的 UIImageView。在 Databse 中,图像显示正确,但它只是没有显示在我的 TableViewcell 中

这是 PostCell 的代码:

import UIKit
import Firebase


class PostCell: UITableViewCell {


@IBOutlet weak var postImageView: UIImageView!
@IBOutlet weak var shadowBackgroundView: UIView!
@IBOutlet weak var captionLabel: UILabel!


var post: Post! {
    didSet {
        self.updateUI()
    }
}

func updateUI() {
    // Set shadow background view
    shadowBackgroundView.layer.shadowPath = UIBezierPath(rect: shadowBackgroundView.bounds).cgPath
    shadowBackgroundView.layer.shadowColor = UIColor.black.cgColor
    shadowBackgroundView.layer.shadowOpacity = 0.1
    shadowBackgroundView.layer.shadowOffset = CGSize(width: 2, height: 2)
    shadowBackgroundView.layer.shadowRadius = 2
    shadowBackgroundView.layer.masksToBounds = false
    shadowBackgroundView.layer.cornerRadius = 3.0

    // caption
    self.captionLabel.text = post.caption



    // download image
    if let imageDownloadURL = post.downloadURL {
        let imageStorageRef = Storage.storage().reference(forURL: imageDownloadURL)
        imageStorageRef.getData(maxSize: 2 * 1024 * 1024) { [weak self] (data, error) in
            if let error = error {
                print("******** \(error)")
            } else {
                if let imageData = data {
                    let image = UIImage(data: imageData)
                    DispatchQueue.main.async {
                        self?.postImageView.image = image
                    }
                }
            }
        }
    }
 }
}

这就是 NewsfeedTableViewController 的代码:

 import UIKit
 import Firebase
 import SwiftyJSON
 import SDWebImage

 class NewsfeedTableViewController: UITableViewController {

var posts = [Post]()
var imageURLs = [String]()

override func viewDidLoad() {
    super.viewDidLoad()

    // download posts
    Database.database().reference().child("posts").observe(.childAdded) { (snapshot) in
        // snapshot is now a dictionary
        let newPost = Post(snapshot: snapshot)
        DispatchQueue.main.async {
            self.posts.insert(newPost, at: 0)
            let indexPath = IndexPath(row: 0, section: 0)
            self.tableView.insertRows(at: [indexPath], with: .top)
        }
    }


}

// MARK: - Table view data source

override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return posts.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "PhotoCell", for: indexPath) as! PostCell
    let post = self.posts[indexPath.row]

    cell.post = post

    return cell
 }
}

这是 Post.swift:

import UIKit
import Firebase
import SwiftyJSON

class Post {
private var image: UIImage!
var caption: String!
var downloadURL: String?

init(image: UIImage, caption: String) {
    self.image = image
    self.caption = caption
}

init(snapshot: DataSnapshot) {
    let json = JSON(snapshot.value)
    self.caption = json["caption"].stringValue
    self.downloadURL = json["imageDownloadURL"].string
}

func save() {
    let newPostRef = Database.database().reference().child("images").childByAutoId()
    let newPostKey = newPostRef.key

    // 1. save image
    if let imageData = UIImageJPEGRepresentation(image, 0.5) {
        let storage = Storage.storage().reference().child("photoPosts/\(newPostKey)")

        storage.putData(imageData).observe(.success, handler: { (snapshot) in
            self.downloadURL = snapshot.metadata?.downloadURL()?.absoluteString
            let postDictionary = [
                "imageDownloadURL" : self.downloadURL,
                "caption" : self.caption
            ]
            newPostRef.setValue(postDictionary)
        })
    }
 }
}

这是我的 AddViewController:

import UIKit
import Firebase


class AddJobViewController: UIViewController,       UIImagePickerControllerDelegate, UINavigationControllerDelegate,   UITextViewDelegate{

@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var captionTextView: RoundText!

var textViewPlaceholderText = "What about the Job?"
var takenImage: UIImage!
var imagePicker = UIImagePickerController()
let picker = UIImagePickerController()
var userStorage: StorageReference!
var ref: DatabaseReference!
var selectedImage = false

override func viewDidLoad() {
    super.viewDidLoad()

    picker.delegate = self
    captionTextView.text = textViewPlaceholderText
    captionTextView.textColor = .lightGray

}


@IBAction func selectImagePressed(_ sender: Any) {
    if UIImagePickerController.isSourceTypeAvailable(.savedPhotosAlbum) {
        self.imagePicker.delegate = self
        self.imagePicker.sourceType = .savedPhotosAlbum
        self.imagePicker.allowsEditing = true
        self.present(self.imagePicker, animated: true, completion: nil)
    }
}


func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    if let image = info[UIImagePickerControllerEditedImage] as? UIImage {
        imageView.image = image
        selectedImage = true
    } else {
        print("A valid image wasn't selected")
    }
    imagePicker.dismiss(animated: true, completion: nil)
}

@IBAction func shareDidTap(_ sender: Any) {
    //close keyboard
    self.view.endEditing(true)

    guard let caption = captionTextView.text, caption != "Please enter text!" else {
        print("Caption must be entered")
        return
    }

    guard let img = imageView.image, selectedImage == true else {
        print("An image must be selected")
        return
    }

    // compressing the post image for Firebase storage
    if let imgData = UIImageJPEGRepresentation(img, 0.2) {
        // setting a unique identifier
        let imgUid = NSUUID().uuidString
        // letting it know itll be a jpeg for safety
        let metaData = StorageMetadata()
        metaData.contentType = "image/jpeg"
        // Referencing Firebase storage child with the unique identifier, and updating with the image from the picker
        DatabaseManager.shared.REF_POSTS_IMAGES.child(imgUid).putData(imgData, metadata: metaData, completion: { (metadata, error) in
            if error != nil {
                print("Unable to upload image Firebase storage")
            } else {
                print("Successfully uploaded image to Firebase storage")
                let downloadUrl = metadata?.downloadURL()?.absoluteString
                if let url = downloadUrl {
                    //once the image is uploaded to firebase stoarge, its then posted to the database
                    self.postToFirebase(imgUrl: url)
                }
            }
        })
    }
}

func postToFirebase(imgUrl: String) {
    let post: Dictionary<String, AnyObject> = [
        "caption" : captionTextView.text as AnyObject,
        "imageURL" : imgUrl as AnyObject,
        "likes" : 0 as AnyObject
    ]

    // setting the value with whatever is passed into this function
    let firebasePost = DatabaseManager.shared.REF_POSTS.childByAutoId()
    firebasePost.setValue(post)

    // resetting the inputs for the post
    captionTextView.text = ""
    selectedImage = false
    imageView.image = UIImage(named: "add-image")

 }

}

我想我几乎看过任何 YT 视频或看到任何属于此 Tread 的 StackOverflow 条目,但没有任何东西对我有用。 也许我只是对此感到愚蠢,因为我是这门语言的初学者,或者是一般的 Coding 初学者。

【问题讨论】:

    标签: image firebase swift4 firebase-storage


    【解决方案1】:

    我认为您需要对变量进行类型转换

    let imageStorageRef = Storage.storage().reference(forURL: imageDownloadURL)
        imageStorageRef.downloadURL(completion: { (url, error) in
                let data = Data(contentsOf: url!)
                let image = UIImage(data: data! as Data)
    

    【讨论】:

      【解决方案2】:

      您可能还需要刷新视图,因为这是异步的。而且您可能应该观察到成功/失败等。这是我的一些有效代码

      func getLocationPhotos(coordinate:CLLocationCoordinate2D){
          dbHandler.getImageFileNames(coordinateIn: coordinate) { (filenames) in
      
              if filenames.isEmpty {
                  log.debug(String.warningGet + "filenames is empty")
                  return
              }//if filenames.isEmpty
      
              self.imageFiles = filenames.filter { $0 != "none" }
      
              if self.imageFiles.isEmpty {
                  log.error(String.errorGet + "imageFiles array is empty")
                  return
              }//if imageFiles.isEmpty
      
              for file in self.imageFiles {
                  let reference = self.storageHandler.imageReference.child(file)
      
                  let download = self.imageView.sd_setImage(with: reference)
      
                  if let i = self.imageView.image {
                              self.imageArray.append(i)
                              self.collectionView.reloadData()
                          }//let i
      
                      download?.observe(.progress, handler: { (snapshot) in
                              guard let p = snapshot.progress else {
                                  return
                              }//let p
                          self.progressView.progress = Float(p.fractionCompleted)
                          if self.progressView.progress == Float(1) {
                              self.progressView.isHidden = true
                          }
                          })//progress
      
                      download?.observe(.success, handler: { (snapshot) in
                              self.progressView.progress = 1
                              self.progressView.isHidden = true
                              self.collectionView.setNeedsLayout()
                          })//success
      
                      download?.observe(.failure, handler: { (snapshot) in
                              log.error(String.errorGet + "Error occured getting data from snapshot")
                          })//failure
          }//for file
      }//dbHandler
          self.activityIndicator.stopAnimating()
          self.activityIndicator.hidesWhenStopped = true
      }//getLocationPhotos
      

      对于集合视图,请注意这一行 self.collectionView.setNeedsLayout()

      【讨论】:

      • 所以我需要添加一个活动指示器?
      • 如果你愿意。我的经验是,我的事情发生得如此之快,以至于活动指示器从未出现过。为什么不首先查看您的代码是否正常工作,然后再决定是否需要。
      猜你喜欢
      • 2022-01-04
      • 1970-01-01
      • 2016-11-05
      • 1970-01-01
      • 2018-02-09
      • 2016-09-28
      • 2022-01-19
      • 2018-08-13
      • 2016-11-22
      相关资源
      最近更新 更多