0

would you please help me to solve this error .I'am trying to download an Image From Firebase Database, this is my code and I put a snapshot for the error . ThanksThis is a snapshot for the error in Xcode

  import UIKit
  import FirebaseDatabase

  class ViewController: UIViewController , UITableViewDataSource , UITableViewDelegate {

   @IBOutlet weak var tableView: UITableView!

   var ref:FIRDatabaseReference?
   var Handle:FIRDatabaseHandle?
   var myClass = [Post]() 

   override func viewDidLoad() {
    super.viewDidLoad()

    tableView.delegate = self
    tableView.dataSource = self

    ref=FIRDatabase.database().reference()

    Handle = ref?.child("Posts").observe(.childAdded, with: { (snapshot) in
          let post = snapshot.valueInExportFormat()

          for url in post! as! [Post] {        // Error Here
             self.myClass.append(url)
            self.tableView.reloadData()
          }

          override func didReceiveMemoryWarning() {
          super.didReceiveMemoryWarning()
          // Dispose of any resources that can be recreated.
    }

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

   public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        if  let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)as? TableViewCell{

       cell.MyImage.alpha = 0
       cell.textLabel?.text = PostData[indexPath.row]

       DispatchQueue.main.async(execute: {

       let imgurl = URL(string : self.myClass [(indexPath as       NSIndexPath).row].url)
       let imgdata = NSData(contentsOf: imgurl!)
       cell.MyImage.image = UIImage(data: imgdata as! Data)

       UIView.animate(withDuration: 0.5, animations: {
            cell.MyImage.alpha = 1
       })
   })

    return cell

    } else {

        let cell = TableViewCell()
        DispatchQueue.main.async(execute: {

            let imgurl = URL(string : self.myClass [(indexPath as NSIndexPath).row].url)
            let imgdata = NSData(contentsOf: imgurl!)
            cell.MyImage.image = UIImage(data: imgdata as! Data)
        })
        return cell
    }

 }





     }


    })


}
Jay
  • 34,438
  • 18
  • 52
  • 81
  • Instead of adding screenshots of your code, please add the actual code to the question. To capture the error message, right click on the red indicator and "Reveal in Issue Navigator". – Frank van Puffelen Dec 13 '16 at 15:52
  • There are a significant number of issues with this code and it's way overly complex. It's unclear why Handle = is being used and the DispatchQueue will certainly get you into trouble if not used correctly. The .valueInExportFormat appears to be unneeded as well. The main issue is that you are reading in a single node/url via .childAdded event, which I assume is a string and assigning to an array with [Post] which results in the error cannot convert NSString to NSArray. – Jay Dec 13 '16 at 19:08
  • you need to get the data from `snapshot` variable and parse it to your type `Post`, there's no free conversion there. So I suggest you read carefully this part https://firebase.google.com/docs/database/ios/read-and-write – Wilson Dec 22 '16 at 11:56

2 Answers2

0

Maybe you want:

for url in post! {
    var wrappedPost = Post()
    wrappedPost.url = url
    ... use wrappedPost for whatever you need a Post object for
}
Jeremy Gurr
  • 1,613
  • 8
  • 11
  • When I use your code this error appears ( Type 'Any' does not conform to protocol 'Sequence'). – Zaid Mustafa Dec 13 '16 at 16:40
  • That means your snapshot.valueInExportFormat function has a return type of Any. In that case you can declare your post variable differently: let post : [String] = snapshot.valueInExportFormat() – Jeremy Gurr Dec 13 '16 at 16:58
  • Now I have another error in URL ( cannot convert value of type 'string' to argument type 'Post' . Thanks for your help – Zaid Mustafa Dec 13 '16 at 17:30
  • I need to know where that's happening. Where are you trying to convert a string to a Post? – Jeremy Gurr Dec 13 '16 at 17:39
  • You can't use url there because url is a String. Instead use the wrappedPost variable I was describing above: self.myClass.append(wrappedPost) – Jeremy Gurr Dec 13 '16 at 19:42
  • Also I have error when I use [self.myClass.append(wrappedPost)] . Constant 'wrappedPost' used before being initialized – Zaid Mustafa Dec 13 '16 at 20:14
  • Oh I made a mistake there. Corrected. – Jeremy Gurr Dec 13 '16 at 20:18
  • I still have another error in this code --> for url in post! { ( Type 'Any?' does not conform to protocol 'Sequence') the error pointing on (post!) – Zaid Mustafa Dec 13 '16 at 20:30
  • That means post is not an array at all. We need to know exactly what snapshot.valueInExportFormat() is returning. You will need to learn to use a debugger or log the class of the instance created to find out. We can't help without further info. – Jeremy Gurr Dec 13 '16 at 23:15
0

Sometimes simple is the way to go.

assume you have a Firebase structure

Planets
  planet_4
    some_text = "My post about Mars"
    image_url = "images/mars.jpg"
  planet_2
    some_text = "My post about Venus"
    image_url = "images/venus.jpg"

and suppose we want to load each text and image and display in a tableview. We can do it one of two ways, one at a time with .childAdded or all at once with .value. In this example, we'll walk through them one at a time.

let planetsRef = myRootRef.child("Planets")

planetsRef.observe(.childAdded, with: { snapshot in
     let dict = snapshot.value as! [String: AnyObject]

     let text = dict["text"]
     let imageUrl = dict["image_url"]

     // Create a reference to the file you want to download
     let planetRef = storageRef.child(imageUrl) //storageRef is defined elsewhere

     // Download in memory with a maximum allowed size
     //   of 1MB (1 * 1024 * 1024 bytes)
     planetRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in
         if (error != nil) {
             // Got an error so handle it
         } else {
             // Data for "images/some planet.jpg" is returned
             // let planetImage: UIImage! = UIImage(data: data!)
             // then add the text and the image to your dataSource array
             // and reload your tableview.
         }
     })
})

This is not tested but will provide the general idea

Jay
  • 34,438
  • 18
  • 52
  • 81
  • I'am not using the Storage in my code , I just use it to upload Image and copy its url and pest it in my console on database ,So I'am trying to download my Image from RealtimeDatabase . thanks for you help – Zaid Mustafa Dec 13 '16 at 20:47
  • @ZaidMustafa You should not really be storing images in the database; that's what storage is for. See [this answer](http://stackoverflow.com/questions/13955813/how-can-i-view-and-store-images-in-firebase/13957446#13957446) for all the details on how to work with images. Also, see my answer [here](http://stackoverflow.com/questions/33644560/swift2-retrieving-images-from-firebase/34044446#34044446) for working with encoding. – Jay Dec 13 '16 at 21:18