Swift 4 - 在TableViewCell / ImageView中显示来自Firebase存储的图像

时间:2018-04-30 16:15:21

标签: image firebase swift4 firebase-storage

我无法看到来自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-Video或看到任何StackOverflow Entry都属于这个Tread,对我来说没什么用。 也许我只是为了这个而愚蠢,因为我是这种语言的初学者,或者一般的Coding。

2 个答案:

答案 0 :(得分:0)

我认为您需要输入变量

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)

答案 1 :(得分:0)

您也可能需要刷新视图,因为这是asych。你可能应该观察成功/失败等。这是我的一些代码

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()