I cannot get the data from the Sqlite database - ios

I cannot get the data from the Sqlite database.
It doesn't print anything for me. I checked the connection to the db is made and the database contains the data.
It gives no error but does not print anything.
When I start the app the tableView contains no records.
In console print this:
API call with NULL database connection pointer
misuse at line 139466 of [d24547a13b]
prepare: out of memory
// AppDelegate.swift
import UIKit
import SQLite3
#main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
DataManager.dataManager.dbOpaquePointer = DataManager.dataManager.openDatabase(dbName: "DB.sqlite")
return true
}
}
// TableWord.swift
import Foundation
class TableWord{
var idword: Int = 0
var word: String = ""
var features: String = ""
var number: Int = 0
init(idword: Int, word: String, features: String, number: Int) {
self.idword = idword
self.word = word
self.features = features
self.number = number
}
}
// DataManager.swift
import UIKit
import SQLite3
class DataManager {
static let dataManager = DataManager()
var dbOpaquePointer: OpaquePointer?
// OPEN
func openDatabase(dbName: String) -> OpaquePointer? {
let documentDirectory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let fileUrl = documentDirectory?.appendingPathComponent(dbName).relativePath
guard let part1DbPath = fileUrl else {
print("part1DbPath is nil.")
return nil
}
if sqlite3_open(part1DbPath, &dbOpaquePointer) == SQLITE_OK {
print(“Open database in \(part1DbPath)")
return dbOpaquePointer
} else {
print("\(Errors.SQLiteError.openDatabase)")
}
return dbOpaquePointer
}
// SELECT
func selectTableWord() -> [TableWord] {
let querySelectTableWord = "SELECT * FROM tableword;"
var dbOpaquePointer2: OpaquePointer? = nil
var dataTableWord: [TableWord] = []
if sqlite3_prepare_v2(dbOpaquePointer, querySelectTableWord, -1, &dbOpaquePointer2, nil) == SQLITE_OK {
while (sqlite3_step(dbOpaquePointer2) == SQLITE_ROW) {
let idword = sqlite3_column_int(dbOpaquePointer2, 0)
guard let queryResultCol1 = sqlite3_column_text(dbOpaquePointer2, 1) else {
print("\(Errors.SQLiteError.queryNil)")
return dataTableWord
}
let word = String(cString: queryResultCol1)
guard let queryResultCol2 = sqlite3_column_text(dbOpaquePointer2, 2) else {
print("\(Errors.SQLiteError.queryNil)")
return dataTableWord
}
let features = String(cString: queryResultCol2)
let number = sqlite3_column_int(dbOpaquePointer2, 3)
dataTableWord.append(TableWord(idword: Int(idword), word: word, features: features, number: Int(number)))
}
} else {
let errorMessage = String(cString: sqlite3_errmsg(dbOpaquePointer2))
print("\(Errors.SQLiteError.prepare): \(errorMessage)")
}
sqlite3_finalize(dbOpaquePointer2)
return dataTableWord
}
}
// ViewController.swift
import UIKit
import SQLite3
class ViewController: UIViewController, UITextViewDelegate, UITableViewDataSource {
#IBOutlet weak var resultTableView: UITableView!
var db: DataManager = DataManager()
var dataTableWord: [TableWord] = []
override func viewDidLoad() {
super.viewDidLoad()
dataTableWord = db.selectTableWord()
searchTextView.delegate = self
resultTableView.dataSource = self
}
//MARK: - UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataTableWord.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "idCell1Main1", for: indexPath) as! TableViewCell
cell.cellLabelNumber.text = String(dataTableWord[indexPath.row].idword)
cell.cellLabelTitle.text = dataTableWord[indexPath.row].word
cell.cellLabelSubtitle.text = dataTableWord[indexPath.row].features
return cell
}
}

In viewDidLoad you call
var db: DataManager = DataManager()
Which means you are creating a new instance of DataManager instead of using the instance you created in your app delegate and that has an open database connection
You should always access your database using the static property you have created
let db = DataManager.databaseManager
To avoid mistakes like this you can add a private init to your class
private init() {}
this way you can only access it via DataManager.databaseManager

Related

Error: Cannot assign value of type 'String?' to type 'String?.Type'

I've got a couple a problem with this code. Here's my code and I don't understand why there is an error line 61 with cell.userID = self.user[indexPath.row].userID it says : Cannot assign value of type String? to type String?.Type. It's probably because in line 36 : if let uid = value["profilepicture.userID"] as? String. userID is in Firebase a child of profile picture but I don't know how to write that inside of value[]. Thanks for your answers.
// TableViewCell.swift
import UIKit
class FriendsTableViewCell: UITableViewCell {
#IBOutlet weak var userImage: UIImageView!
#IBOutlet weak var nameLabel: UILabel!
var userID = String?.self
}
// ViewController.swift
import UIKit
import Firebase
class FriendsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableview: UITableView!
var user = [User]()
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func retrieveUsers() {
let ref = Database.database().reference()
ref.child("users").queryOrderedByKey().observeSingleEvent(of: .value, with: { DataSnapshot in
let users = DataSnapshot.value as! [String: AnyObject]
self.user.removeAll()
for (_, value) in users{
//let uid = Auth.auth().currentUser!.uid
if let uid = value["profilepicture.userID"] as? String{
if uid != Auth.auth().currentUser!.uid {
let userToShow = User()
if let fullName = value["username"] as? String , let imagePath = value["profilepicture.photoURL"] as? String {
userToShow.username = fullName
userToShow.imagePath = imagePath
userToShow.userID = uid
self.user.append(userToShow)
}
}
}
}
})
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableview.dequeueReusableCell(withIdentifier: "FriendsTableViewCell", for: indexPath) as! FriendsTableViewCell
cell.nameLabel.text = self.user[indexPath.row].username
cell.userID = self.user[indexPath.row].userID
cell.userImage.downloadImage(from: self.user[indexPath.row].imagePath!)
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return user.count ?? 0
}
}
extension UIImageView{
func downloadImage(from imgURL: String!) {
let url = URLRequest(url: URL(string: imgURL)!)
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil{
print(error)
return
}
DispatchQueue.main.async {
self.image = UIImage(data: data!)
}
}
task.resume()
}
}
Cannot assign value of type String? to type String?.Type.
Change
var userID = String?.self
To
var userID : String?

fetching images from firebase in swift 3

I am using Firebase as a backend for my project.I need to display text and image from Firebase database in tableview. It displays only text in my tableview and shows error while retrieving image as "cannot convert value of type 'UIImage?' to expected argument type 'String'".Please anyone, who can correct me. My code is given below:
//App Delegate
import UIKit
import CoreData
import Firebase
import FirebaseDatabase
import FirebaseStorage
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FIRApp.configure()
return true
}
//View Controller
import UIKit
import Firebase
import FirebaseDatabase
import FirebaseStorage
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var ref: FIRDatabaseReference? = nil
var refHandle: UInt? = nil
var userList = [User]()
#IBOutlet var tblHome: UITableView!
let textCellIdentifier = "TextCell"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tblHome.delegate = self
tblHome.dataSource = self
self.ref = FIRDatabase.database().reference()
print("ref = ",ref)
fetchUsers()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("userList is", userList.count)
return userList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: textCellIdentifier, for: indexPath) as! HomeCell
cell.profname.text = userList[indexPath.row].imageName
if let url = URL.init(string: userList[indexPath.row].imageUrl) { // Error: cannot convert value of type 'UIImage?' to expected argument type 'String'
cell.profImage.image.downloadedFrom(url: url)
}
return cell
}
func fetchUsers() {
refHandle = ref?.child("Users").observe(.childAdded, with: { (snapshot) in
print("refHandle =", self.refHandle)
if let dictionary = snapshot.value as? [String: AnyObject] {
print("dictionary =", dictionary)
let user = User()
user.setValuesForKeys(dictionary)
self.userList.append(user)
print("userlist is", user)
DispatchQueue.main.async(execute: {
self.tblHome.reloadData()
})
}
})
}
}
extension UIImageView {
func downloadedFrom(url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() { () -> Void in
self.image = image
}
}.resume()
}
// func downloadedFrom(link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) {
// guard let url = URL(string: link) else { return }
// downloadedFrom(url: url, contentMode: mode)
// }
}
//Home Cell
import UIKit
class HomeCell: UITableViewCell {
#IBOutlet var profImage: UIImageView!
#IBOutlet var profname: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}
//User
import UIKit
class User: NSObject {
var imageName: String?
var imageUrl: UIImage?
}
According to the documentation, URL() takes a String and you are passing a UIImage to it.
Inside your User class, imageUrl is of type UIImage? and you are passing it into the URL constructor even though it is expecting a String.
You can solve this by changing your User class to this:
class User: NSObject
{
var imageName: String?
var imageUrl: String? // pass this to the URL constructor
var image: UIImage? // this stores the actual image
}

Read data from firebase and populate TableViewCell

Hello I have a tableviewcell where i can populate it with custom data from my pc, but i can't use my firebase data on the cell that i have made. I want to fill my cell with String and Int, not only Strings. My code is:
PlacesTableViewController Class
import UIKit
import FirebaseDatabase
class PlacesTableViewController: UITableViewController {
//MARK: Properties
#IBOutlet weak var placesTableView: UITableView!
//database reference
var dbRef:FIRDatabaseReference?
var places = [Places]()
var myList:[String] = []
//handler
var handle:FIRDatabaseHandle?
override func viewDidLoad() {
super.viewDidLoad()
dbRef = FIRDatabase.database().reference()
// Loads data to cell.
loadData()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return places.count
//return myList.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Table view cells are reused and should be dequeued using a cell identifier.
let cellIdentifier = "PlacesTableViewCell"
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? PlacesTableViewCell else {
fatalError("The dequeued cell is not an instance of PlacesTableView Cell.")
}
let place = places[indexPath.row]
cell.placeLabel.text = place.name
cell.ratingControl.rating = place.rating
//cell.placeLabel.text = myList[indexPath.row]
//cell.ratingControl.rating = myRatings[indexPath.row]
return cell
}
//MARK: Private Methods
private func loadData() {
handle = dbRef?.child("placeLabel").observe(.childAdded, with: { (snapshot) in
if let item = snapshot.value as? String
{
self.myList.append(item)
self.placesTableView.reloadData()
print (item)
}
})
/* handle = dbRef?.child("rating").observe(.childAdded, with: { (snapshot) in
if let item = snapshot.value as? String
{
self.myList.append(item)
self.placesTableView.reloadData()
}
})*/
/*guard let place1 = Places(name: "Veranda", rating: 4) else {
fatalError("Unable to instantiate place1")
}
places += [place1]*/
}
}
Places Class
import UIKit
class Places {
//MARK: Properties
var name: String
var rating: Int
//MARK:Types
struct PropertyKey {
static let name = "name"
static let rating = "rating"
}
//MARK: Initialization
init?(name: String, rating: Int) {
// Initialize stored properties.
self.name = name
self.rating = rating
// Initialization should fail if there is no name or if the rating is negative.
// The name must not be empty
guard !name.isEmpty else {
return nil
}
// The rating must be between 0 and 5 inclusively
guard (rating >= 0) && (rating <= 5) else {
return nil
}
}
}
PlacesTableViewCell Class
import UIKit
import FirebaseDatabase
class PlacesTableViewCell: UITableViewCell, UITableViewDelegate {
//MARK: Properties
#IBOutlet weak var placeLabel: UILabel!
#IBOutlet weak var ratingControl: RatingControl!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Firebase Database
Assuming your database layout should instead look like this (see comments above):
...
placeLabel
|
-- XXY: "Veranda"
-- YYY: "Dio Con Dio"
rating
|
-- XXX: 4
-- YYY: 1
...
then try this:
private func loadData() {
dbRef!.child("placeLabel").observe(.childAdded) {
(snapshot) in
let label = snapshot.value as! String
self.updatePlace(snapshot.key, label: label)
}
dbRef!.child("rating").observe(.childAdded) {
(snapshot) in
let rating = snapshot.value as! Int
self.updatePlace(snapshot.key, rating: rating)
}
}
private var loadedLabels = [String: String]()
private var loadedRatings = [String: Int]()
private func updatePlace(_ key: String, label: String? = nil, rating: Int? = nil) {
if let label = label {
loadedLabels[key] = label
}
if let rating = rating {
loadedRatings[key] = rating
}
guard let label = loadedLabels[key], let rating = loadedRatings[key] else {
return
}
if let place = Places(name: label, rating: rating) {
places.append(place)
placesTableView.reloadData()
}
}
By the way, you can temporarily hack your database — using Firebase (nice!) web console — if you want to quickly validate the above solution.
Writing to Database. Try the following code to write the nodes in your database (i.e., this code reuses the same key across all place properties):
let key = dbRef!.child("placeLabel").childByAutoId().key
dbRef!.child("placeLabel").child(key).setValue(placeLab‌​el.text)
dbRef!.child("comment").child(key).setValue(commentText‌​Field.text)
dbRef!.child("rating").child(key).setValue(ratingContro‌​l.rating)
Hacking the Database. To edit the database manually, try:
open http://console.firebase.google.com
select your app
open database option
add a new node with the right key
delete the old node

Trouble on SearchBar loading plist

I am loading my plist into a TableView and it is going everything ok, but now I am trying to include a SearchBar on the Page1. Below you see the directory.plist and my Main.storyboard
To load the plist correctly I put the following code on my didFinishLaunchingWithOptions:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if let url = Bundle.main.url(forResource: "directory", withExtension: "plist"), let array = NSArray(contentsOf: url) as? [[String:Any]] {
Shared.instance.employees = array.map{Employee(dictionary: $0)}
}
return true
}
I also have a Structure helping me to load all my stuff:
struct EmployeeDetails {
let functionary: String
let imageFace: String
let phone: String
init(dictionary: [String: Any]) {
self.functionary = (dictionary["Functionary"] as? String) ?? ""
self.imageFace = (dictionary["ImageFace"] as? String) ?? ""
self.phone = (dictionary["Phone"] as? String) ?? ""
}
}
struct Employee {
let position: String
let name: String
let details: [EmployeeDetails] // [String:Any]
init(dictionary: [String: Any]) {
self.position = (dictionary["Position"] as? String) ?? ""
self.name = (dictionary["Name"] as? String) ?? ""
let t = (dictionary["Details"] as? [Any]) ?? []
self.details = t.map({EmployeeDetails(dictionary: $0 as! [String : Any])})
}
}
struct Shared {
static var instance = Shared()
var employees: [Employee] = []
}
Until here, everything is running well! Now I became having trouble when I tried to insert a SearchView, take a look what I did until now:
class Page1: UITableViewController, UISearchBarDelegate {
#IBOutlet weak var searchBar: UISearchBar!
let employeesSearching: [String] = [String]() //now using: var employeesSearching = [Employee]()
var isSearching : Bool = false
override func viewDidLoad() {
super.viewDidLoad()
self.searchBar.delegate = self
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.isSearching == true {
return self.employeesSearching.count
} else {
return Shared.instance.employees.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell1
let employee = Shared.instance.employees[indexPath.row]
if self.isSearching == true {
cell.nameLabel.text = self.employeesSearching[indexPath.row].name
cell.positionLabel.text = self.employeesSearching[indexPath.row].position
} else {
cell.nameLabel.text = employee.name
cell.positionLabel.text = employee.position
}
return cell
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if self.searchBar.text!.isEmpty {
self.isSearching = false
self.tableView.reloadData()
} else {
self.isSearching = true
self.employeesSearching.removeAll(keepingCapacity: false)
for i in 0..<self.Shared.instance.itens.count {
let listItem : String = self.Shared.instance.itens[i]
if listItem.lowercased().range(of: self.searchBar.text!.lowercased()) != nil {
self.employeesSearching.append(listItem)
}
}
self.tableView.reloadData()
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? Page2,
let indexPath = tableView.indexPathForSelectedRow {
destination.newPage = Shared.instance.employees[indexPath.row]
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
These are the exactly mistakes:
EDIT 1
After tips, now the only trouble is:
EDIT 2
Now I am having this:
The errors are because employeesSearching is a constant array of String.
You probably want a variable array of Employee.
Change:
let employeesSearching: [String] = [String]()
to:
var employeesSearching = [Employee]()

fatal error: unexpectedly found nil while unwrapping an Optional value when load the value from Firebasedatabase [duplicate]

This question already has answers here:
What does "Fatal error: Unexpectedly found nil while unwrapping an Optional value" mean?
(16 answers)
Closed 6 years ago.
I am pretty new with swift. I tried to finger out myself. I know this is the common question, but I hope I could get help. When I run the application. I got the "fatal error: unexpectedly found nil while unwrapping an Optional value".
import Foundation
import Firebase
import FirebaseDatabase
import FirebaseStorage
import FirebaseAuth
struct TodoItemDatabase {
var eventID: String!
var title: String!
var staff: String!
var location: String!
var starts: String!
var ends: String!
var rpeat: String!
var imageName: String!
var description: String!
var secondPhoto: String!
var ref: FIRDatabaseReference?
var key: String!
var isCompleted: Bool
init (eventID: String!, title: String,staff:String, location: String,starts: String, ends: String, rpeat: String, imageName: String, description: String, secondPhoto: String, key: String = "", isCompleted: Bool){
self.eventID = eventID
self.title = title
self.staff = staff
self.location = location
self.starts = starts
self.ends = ends
self.rpeat = rpeat
self.imageName = imageName
self.description = description
self.secondPhoto = secondPhoto
self.key = key
self.ref = FIRDatabase.database().reference()
self.isCompleted = isCompleted
}
init(snapshot: FIRDataSnapshot){
**//I get the error from here. However, I think the main reason in tableview below**
self.eventID = snapshot.value!["eventID"] as! String
self.title = snapshot.value!["title"] as! String
self.staff = snapshot.value!["staff"] as! String
self.location = snapshot.value!["location"] as! String
self.starts = snapshot.value!["starts"] as! String
self.ends = snapshot.value!["ends"] as! String
self.rpeat = snapshot.value!["rpeat"] as! String
self.imageName = snapshot.value!["imageName"] as! String
self.description = snapshot.value!["description"] as! String
self.secondPhoto = snapshot.value!["secondPhoto"] as! String
self.key = snapshot.key
self.ref = snapshot.ref
self.isCompleted = snapshot.value!["isCompleted"] as! Bool
}
func toAnyObject() -> [String: AnyObject] {
return ["eventid": eventID, "title": title, "staff": staff, "location": location, "starts": starts, "ends": ends, "rpeat": rpeat, "imageName": imageName, "description": description, "secondPhoto": secondPhoto, "isCompleted": isCompleted]
}
}
However, When I run the application, and load the tableview. It appears that error.
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
import FirebaseStorage
var toDoList:[TodoItemDatabase] = [TodoItemDatabase]()
class CurrentEventViewController: UIViewController, UITableViewDelegate {
var databaseRef: FIRDatabaseReference!{
return FIRDatabase.database().reference()
}
var storageRef: FIRStorageReference!
#IBOutlet var toDoListTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return toDoList.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! myCell
let todoItem = toDoList[indexPath.row]
storageRef = FIRStorage.storage().referenceForURL(toDoList[indexPath.row].imageName)
storageRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) in
if error == nil {
dispatch_async(dispatch_get_main_queue(), {
if let data = data {
cell.myImageView.image = UIImage(data: data)
}
})
} else {
print(error!.localizedDescription)
}
}
cell.myLabel.text = todoItem.title!
return cell
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
let ref = toDoList[indexPath.row]
ref.ref?.removeValue()
toDoList.removeAtIndex(indexPath.row)
toDoListTable.reloadData()
}
}
override func viewDidAppear(animated: Bool) {
toDoListTable.reloadData()
}
override func viewWillAppear(animated: Bool) {
let postRef = FIRDatabase.database().reference().child("posts").queryOrderedByChild("isCompleted").queryEqualToValue(false)
postRef.observeEventType(.Value, withBlock: { (snapshot) in
var newPosts = [TodoItemDatabase]()
for post in snapshot.children{
**// I think the reason is the line after.**
let post = TodoItemDatabase(snapshot: post as! FIRDataSnapshot)
newPosts.insert(post, atIndex: 0)
}
toDoList = newPosts
dispatch_async(dispatch_get_main_queue(), {
self.toDoListTable.reloadData()
})
}) { (error) in
print(error.localizedDescription)
}
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
storageRef = FIRStorage.storage().referenceForURL(toDoList[indexPath.row].imageName)
let storageRef1 = FIRStorage.storage().referenceForURL(toDoList[indexPath.row].secondPhoto)
let itemSelected = toDoList[indexPath.row]
storageRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) in
if error == nil
{
dispatch_async(dispatch_get_main_queue(), {
if let data = data
{
storageRef1.dataWithMaxSize(1 * 1024 * 1024) { (data1, error) in
if error == nil
{
dispatch_async(dispatch_get_main_queue(), {
if let data1 = data1
{
let detailVC:DetailViewController = self.storyboard?.instantiateViewControllerWithIdentifier("DetailViewController") as! DetailViewController
detailVC.titleEvent = itemSelected.title
detailVC.staffEvent = itemSelected.staff
detailVC.locationEvent = itemSelected.location
detailVC.startEvent = itemSelected.starts
detailVC.endEvent = itemSelected.ends
detailVC.repeatEvent = itemSelected.rpeat
detailVC.imageDetail = UIImage(data: data)!
detailVC.descriptionDetail = itemSelected.description
detailVC.secondPhotoEvent = UIImage(data: data1)!
detailVC.key = itemSelected.key
self.presentViewController(detailVC, animated: true, completion: nil)
}
})
}
else
{
print(error!.localizedDescription)
}
}}
})
}
else
{
print(error!.localizedDescription)
}
}
}
}
You need to conditionally unwrap or nil coalesce these values. Force unwrapping the way you are is not safe.
self.eventID = snapshot.value!["eventID"] as! String
should probably be
eventID = snapshot.value?["eventID"] as? String ?? ""
Unfortunately, the compiler loves to suggest force-unwrapping when it encounters optional values. This is almost always a terrible suggestion. You need to get into the habit of handling Optionals gracefully when you encounter .None since Optionals are such an integral part of the Swift language.

Resources