Neil Leon
Neil Leon

Reputation: 55

Index out of range error keeps crashing my app

I have a tableview loading data from firebase database. When i open my app the data does not populate. it crashes and throws the error index out of range. I am fairly new to xcode and would appreciate the help. i have been given recommendations on how to fix my code with regards to having multiple arrays but everyone that advices forget i'm new and does realize that i am pulling imageurls into my tableview too and dont know how to adopt their recommendations into my code. if i could get help getting passed this error that would be awesome.

import UIKit
import FirebaseAuth
import FirebaseDatabase

class EventsViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {



    @IBOutlet weak var tableView: UITableView!

    var eventsRef: DatabaseReference?
    var eventsDatabaseHandle:DatabaseHandle?


    var eventsTitles = [String]()
    var eventTimestamps = [String]()
    var eventsLocations = [String]()
    var eventsImages = [UIImage]()



    @IBOutlet weak var addEventsButton: UIBarButtonItem!


    override func viewDidLoad() {
        super.viewDidLoad()

    adminAuth()

    eventsRef = Database.database().reference()

    tableView.reloadData()

    tableView.transform = CGAffineTransform(rotationAngle: -CGFloat.pi)

    tableView.delegate = self
    tableView.dataSource = self

    eventsDatabaseHandle = eventsRef?.child("Church Events").observe(.childAdded, with: { (snaphot) in

    let eventPost = snaphot.value as! [String: Any]


    self.eventTimestamps.append(eventPost["eventdate"] as! String)


    self.eventsTitles.append(eventPost["eventtitle"] as! String)

    self.eventsLocations.append(eventPost["eventlocation"] as! String)

    let task = URLSession.shared.dataTask(with: URL(string: eventPost["ImageUrl"] as! String)!) {(data, response, error) in

    if let image: UIImage = UIImage(data: data!) {
    self.eventsImages.append(image)
            }

        }

        task.resume()
        self.tableView.reloadData()
        })


}


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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "events") as! EventsTableViewCell

       // let image = eventsImages[indexPath.row]

     cell.flyerImages.image? = eventsImages[indexPath.row] **<- index out of range**

        cell.eventTitle.text! = eventsTitles[indexPath.row]

        cell.eventDate.text! =  eventTimestamps[indexPath.row]

        cell.eventLocation.text! = eventsLocations[indexPath.row]


        cell.transform = CGAffineTransform(rotationAngle: CGFloat.pi)


        return cell
    }


    func adminAuth() {

        if (Auth.auth().currentUser!.displayName != "Neil Leon")  {
            self.addEventsButton.tintColor = UIColor.clear
            self.addEventsButton.isEnabled = false

        }
        else{

            self.addEventsButton.isEnabled = true
        }

    }

}``````

Upvotes: 0

Views: 324

Answers (1)

vadian
vadian

Reputation: 285069

At the moment reloadData is called the image array is empty and causes the crash

Use a custom struct and reload the table view after the image data has been received

struct Event {
    let title, timestamp, location : String
    var image : UIImage?
}

var events = [Event]()

...

eventsDatabaseHandle = eventsRef?.child("Church Events").observe(.childAdded, with: { (snaphot) in
let eventPost = snaphot.value as! [String: Any]
let event = Event(title: eventPost["eventtitle"] as! String,
                  timestamp: eventPost["eventdate"] as! String,
                  location: eventPost["eventlocation"] as! String,
                  image: nil)

let task = URLSession.shared.dataTask(with: URL(string: eventPost["ImageUrl"] as! String)!) { data, _, error in

    if let error = error {
        print(error)
    } else {
        event.image = UIImage(data: data!)
        DispatchQueue.main.async {
           self.events.append(event)
            self.tableView.reloadData()
        }
    }
}
task.resume()

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "events", for: indexPath) as! EventsTableViewCell
    let event = events[indexPath.row]
    cell.flyerImages.image = event.image
    cell.eventTitle.text = event.title
    cell.eventDate.text =  event.timestamp
    cell.eventLocation.text = event.location
    cell.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
    return cell
}

Upvotes: 1

Related Questions