How to search in Firebase Database Swift - swift

am trying to use UISearchbar with my firebase database but i don't know if my code is rghit or not becuase it's crash everytime i run it and this's my code
var hotelList = [hotelsModel]()
var hotelsArray : [NSDictionary] = []
var filterHotels : [NSDictionary] = []
var databaseRef = Database.database().reference()
databaseRef.child("Hotels").queryOrdered(byChild: "name").observe(.childAdded, with: { (snapshot) in
self.hotelsArray.append(snapshot.value as! NSDictionary)
self.tableView.insertRows(at: [IndexPath(row: self.hotelsArray.count-1, section: 0)], with: UITableView.RowAnimation.automatic)
List item
}) { (error) in
print(error.localizedDescription)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//creating a cell using the custom class
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! hotelsTableViewCell
let hotelSearch : NSDictionary?
//the artist object
var hotel: hotelsModel
//getting the artist of selected position
//hotel = hotelList[indexPath.row]
if searchController.isActive && searchController.searchBar.text != "" {
hotelSearch = filterHotels[indexPath.row] as! NSDictionary
} else {
//getting the artist of selected position
hotel = hotelList[indexPath.row]
}
//getting the artist of selected position
hotel = hotelList[indexPath.row]
//adding values to labels
cell.lblName.text = hotel.name
cell.lblLocation.text = hotel.location
cell.appSuggest.text = hotel.appSuggest
cell.price.text = hotel.price
cell.canceletion.text = hotel.cancelation
cell.paymentNeeded.text = hotel.paymentNeeded
if let imgUrl = hotel.img{
let url = URL(string: imgUrl)
cell.img.kf.setImage(with: url)
cell.img.clipsToBounds = true
cell.img.layer.cornerRadius = 10
cell.img.layer.shadowColor = UIColor.black.cgColor
cell.img.layer.shadowOpacity = 1.8
cell.img.layer.shadowOffset = CGSize(width: 5, height: 0)
}
return cell
}
func updateSearchResults(for searchController: UISearchController) {
//update the searchbar result
//filterHotels(serachText:searchController.searchBar.text!)
filterHotels.removeAll()
filterHotels = hotelsArray.filter({ (text) -> Bool in
let tmp: NSString = (text as? NSString ?? nil) ?? ""
let range = tmp.range(of: searchController.searchBar.text!, options: NSString.CompareOptions.caseInsensitive)
return range.location != NSNotFound
})
self.tableView.reloadData()
}
it's crashed in this line
self.hotelsArray.append(snapshot.value as! NSDictionary)
How can I solve this?
Thank You

Related

Why my TableView not updating cells which are fetched from database?

I have TableView and every cell contains one reservation fetched from Firestore. I added refresh controller but no data reloads. I don't know where can be a problem. When I changed one reservation status for eg. canceled in Firebase it changes but in tableview after reloads no UI label change to "canceled". I must to display another controller and go back to update UI label in cell.
override func viewDidLoad()
{
super.viewDidLoad()
reservationsTableView.delegate = self
reservationsTableView.dataSource = self
navigationItem.hidesBackButton = true
searchReservations = Reservations
refreshControl.addTarget(self, action: #selector(refresh(send: )), for: UIControl.Event.valueChanged)
reservationsTableView.addSubview(refreshControl)
loadReservations()
}
#objc func refresh(send: UIRefreshControl)
{
DispatchQueue.main.async {
self.loadReservations()
self.refreshControl.endRefreshing()
self.reservationsTableView.reloadData()
}
}
}
func loadReservations()
{
Reservations = []
guard let uid = Auth.auth().currentUser?.uid else { return }
let userCollection = Firestore.firestore().collection("Users")
let thisUserDoc = userCollection.document(uid)
let snapshot = thisUserDoc.collection("Reservations").getDocuments { (querySnapshot, error) in
if let e = error {
print(e)
}
else
{
if let snapshotDocuments = querySnapshot?.documents
{
for doc in snapshotDocuments
{
let data = doc.data()
// let rid = doc.documentID
if let Time = data["Time"] as? String, let Date = data["Date"] as? String, let Guests = data["Guests"] as? String, let RestaurantName = data["RestaurantName"] as? String, let Name = data["Name"] as? String, let Status = data["Status"] as? String, let Phone = data["Phone"] as? String, let Id = data["Id"] as? String, let RestaurantId = data["RestaurantID"] as? String, let Id2 = data["Id2"] as? String, let guestId = data["GuestId"] as? String
{
let newReservation = Reservation(id: Id, userId: guestId, id2: Id2,restaurantId: RestaurantId ,restaurantName: RestaurantName, name: Name, phone: Phone, guests: Guests, time: Time, date: Date, status: Status)
self.Reservations.append(newReservation)
DispatchQueue.main.async {
self.reservationsTableView.reloadData()
}
}
}
}
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return searchReservations.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: K.reusableCellReservationsC, for: indexPath) as! ReservationCellC
cell.guestName.text = searchReservations[indexPath.row].name
cell.contact.text = searchReservations[indexPath.row].phone
cell.reservationTime.text = searchReservations[indexPath.row].time
cell.reservationDate.text = searchReservations[indexPath.row].date
cell.reservationGuets.text = searchReservations[indexPath.row].guests
cell.reservationStatus.text = searchReservations[indexPath.row].status
cell.cancelBtn.tag = indexPath.row
cell.cancelBtn.addTarget(self, action: #selector(btnCanceledCellTapped(sender: )), for: .touchUpInside)
cell.confirmBtn.addTarget(self, action: #selector(btnConfirmedCellTapped(sender: )), for: .touchUpInside)
cell.lateBtn.addTarget(self, action: #selector(btnLateCellTapped(sender: )), for: .touchUpInside)
return cell
}
What's this line
searchReservations = Reservations
By the way you are appending reservations as below
self.Reservations.append(newReservation)
But you are having row count as
searchReservations.count
This is wrong. It has to be return Reservations.count or you must append values as self.searchReservations.append(newReservation)

How to fix "Value of type 'viewbusdata' has no subscripts" error in Xcode

I'm trying add a search function in my table view. I am calling data from firebase but I get an error at the filterecontent function
the error messages is "Value of type 'viewbusdata' has no subscripts"
here is my firebase structure
firebase structure
searchcontroller.searchResultsUpdater = self
searchcontroller.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
tbv.tableHeaderView = searchcontroller.searchBar
tbv.dataSource = self
tbv.delegate = self
ref = Database.database().reference()
ref.child("BusData").queryOrdered(byChild: "BusData").observe(.childAdded, with: {(snapshot)in
if snapshot.childrenCount>0{
self.viewdata.removeAll()
for BusData in snapshot.children.allObjects as! [DataSnapshot]{
let BusDataobject = BusData.value as? [String: AnyObject]
let Deperture1 = BusDataobject?["Deperture"]
let Arrival1 = BusDataobject?["Arrival"]
let Time1 = BusDataobject?["Time"]
let Price1 = BusDataobject?["Price"]
let id1 = BusDataobject?["id"]
let BusData = viewbusdata(id1: id1 as! String?, Deperture1: Deperture1 as! String?, Arrival1: Arrival1 as! String?, Time1: Time1 as! String?, Price1: Price1 as! String?)
self.viewdata.append(BusData)
}
//self.tbv.reloadData()
}
self.tbv.insertRows(at: [IndexPath(row: self.viewdata.count-1, section: 0)], with: UITableViewRowAnimation.automatic)
}) { (error) in
print(error.localizedDescription)
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchcontroller.isActive && searchcontroller.searchBar.text !=
""{
return filteruser.count
}
return self.viewdata.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tbv.dequeueReusableCell(withIdentifier: "viewcell2", for: indexPath) as! userbusTableViewCell
let BusData : viewbusdata
if searchcontroller.isActive && searchcontroller.searchBar.text !=
""{
BusData = filteruser[indexPath.row]
}
else
{
BusData = self.viewdata[indexPath.row]
}
cell.label1.text = BusData.Deperture1
cell.label2.text = BusData.Arrival1
cell.label3.text = BusData.Time1
cell.label4.text = BusData.Price1
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "showdata", sender: nil)
}
func updateSearchResults(for searchController: UISearchController) {
filterecontent(searchText: self.searchcontroller.searchBar.text!)
}
here is the error message
func filterecontent(searchText: String)
{
self.filteruser = self.viewdata.filter { BusData in
let BusData = BusData ["Deperture"] as? String
return(BusData?.lowercased().contains(searchText.lowercased()))!
}
tbv.reloadData()
}
First of all your code is very hard to read. Please conform to the naming convention that variable and property names start with a lowercase letter (busData) and structs start with a capital letter (Viewbusdata).
The error occurs because busData is a struct, not a dictionary. You get the value with dot notation.
func filterecontent(searchText: String)
{
self.filteruser = self.viewdata.filter { busData in
guard let deperture = busData.deperture else { return false }
return deperture.lowercased().contains(searchText.lowercased())
}
tbv.reloadData()
}
Or a bit swiftier
func filterecontent(searchText: String)
{
self.filteruser = self.viewdata.filter { $0.deperture?.range(of: searchText, options: .caseInsensitive) != nil }
tbv.reloadData()
}
Another bad practice is this pointless force-unwrap-an-optional-to-an-optional as! String?. Don't do that.
If the result is supposed to be an optional write as? String otherwise as! String

Swift - Search in UITableView [duplicate]

This question already has answers here:
Searchbar filtering issue
(3 answers)
Closed 3 years ago.
I'm trying to be able to search my Firebase data using a UISearchBar in my app & I am stuck. I am successfully receiving data from Firebase in a table view. I have a memories-writing app that the user can create memories (that are shown in a tableview from the firebase). memories has a title, description, a pic and a date and I want it to be able to search memories by the title.
I have a code here that doesn't work for some reason... il'l be glad if you could help me find out what's wrong in the code or find a replacement for this code :)
MemoryTitles class:
class MemoryTitles {
var title : String
init(withTitle: String) {
self.title = withTitle
}
}
MemoryViewController:
class MemoryViewController: UIViewController,UITableViewDelegate,UITableViewDataSource
// the filtered memories array for the search bar
var memoriesTitlesArr: [String] = []
var filteredDataa: [String] = []
// connections from storyboard to the code
#IBOutlet weak var tbl: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
// an array of memories
var memories : [Memory] = []
var ref = Database.database().reference()
let sref = Storage.storage().reference()
var lastIndex : Int = 0
var strMode : String = ""
// TableView functions
// Return the number of rows in section
// section - an index number identifying a section in tableView.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searching {
return filteredDataa.count
} else {
return memories.count
}
// return memories.count
}
// Return Cell for row function : an object inheriting from UITableViewCell
// indexPath - an index path locating a row in tableView.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "iden")
if searching {
cell?.textLabel?.text = filteredDataa[indexPath.row]
} else {
var cell : UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: "iden", for: indexPath)
if cell == nil
{
cell = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "iden")
}
let temp = memories[indexPath.row]
cell?.textLabel?.text = temp.title
cell?.imageView?.image = temp.image
return cell!
}
return cell!
}
// Can edit row : asks the data source to verify that the given row is editable.
// indexPath - an index path locating a row in tableView.
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true // true if the row indicated by indexPath is editable; otherwise, false.
}
// Asks the data source to commit the insertion or deletion of a specified row.
// indexPath - an index path locating a row in tableView.
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete // editingStyle - the cell editing style corresponding to a insertion or deletion requested for the row specified by indexPath.
{
let temp = self.memories[indexPath.row]
self.memories.remove(at: indexPath.row)
self.ref.child("MEmories/\(temp.key)").removeValue()
tableView.deleteRows(at: [indexPath as IndexPath], with: .fade)
}
}
override func viewDidLoad() {
super.viewDidLoad()
ref = Database.database().reference()
let rightButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(MemoryViewController.barButtonItemClicked(_:)))
self.navigationItem.setRightBarButton(rightButton, animated: true)
// Do any additional setup after loading the view.
self.loadMemories()
self.tbl.delegate = self
self.tbl.dataSource = self
}
// click on bar-Button function
#objc func barButtonItemClicked(_ sender:UIBarButtonItem)
{
print("+ clicked") // writes "+ clicked"
let addMemoryViewController = self.storyboard?.instantiateViewController(withIdentifier: "AddMemoryViewController") as! AddMemoryViewController
self.strMode = "newMemory"
self.navigationController?.pushViewController(addMemoryViewController, animated: true)
}
// Reading from NSUserDefault (A class that provides simple storage of different data types solution.)
func readFromNSUserDefault()-> Memory?
{
let d : UserDefaults = UserDefaults.standard
let strTitle = d.object(forKey: "title") as? String
let strBody = d.object(forKey: "body") as? String
let strImageRef = d.object(forKey: "imageRef") as? String
let uid = d.object(forKey: "uid") as? String
let imageData = d.object(forKey: "imageData") as? Data
let key = d.object(forKey: "key") as? String
let date = d.object(forKey: "date") as? NSNumber
let m = Memory(title: strTitle!, body: strBody!, key: key!, uid: uid!, imageRef: strImageRef!, date: date!) // A variable from type memory
m.image = UIImage(data: imageData!)
m.key = key!
return m
}
override func viewDidAppear(_ animated: Bool) {
let d = UserDefaults.standard
let newMemory = readFromNSUserDefault()
let userAdded = d.bool(forKey: "userAdded") //key new user = true
let userEdited = d.bool(forKey: "userEdited")//key user edited = true
if self.strMode == "newMemory" && userAdded
{
self.memories.append(newMemory!)
self.tbl.reloadData()
}
else if self.strMode == "edit" && userEdited
{
memories[lastIndex] = newMemory!
self.tbl.reloadData()
}
d.set(false, forKey: "userAdded")
d.set(false, forKey: "userEdited")
d.synchronize()
self.strMode = " "
}
// loading the memories from the Database
func loadMemories()
{
let UID = Auth.auth().currentUser!.uid
self.ref.child("MEmories").queryOrdered(byChild: "uid").queryEqual(toValue: UID).observeSingleEvent(of: .value, with: {
snapShot in
if let dict = snapShot.value as? NSDictionary
{
for d in (dict as? Dictionary<String,AnyObject>)!
{
let title = d.value["title"] as?String
let body = d.value["body"] as? String
let uid = d.value["uid"] as? String
let imageRef = d.value["imageRef"] as? String
let date = d.value["date"] as? NSNumber
let m = Memory(title: title!, body: body!, uid: uid!,imageRef:imageRef!, date: date!)
m.key = d.key
let tempImageRef = self.sref.child(m.imageRef)
tempImageRef.getData(maxSize: 500*1024*1024, completion: {(data,error) in
if error == nil
{
if let imageData = data
{
m.image = UIImage(data: imageData)
self.memories.append(m)
self.tbl.reloadData()
}
}
})
self.memoriesTitlesArr.append(title!)
}
}//end of if
})
}
// Notifies the view controller that a segue is about to be performed.
// segue - The segue object containing information about the view controllers involved in the segue.
// senderThe object that initiated the segue.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let identifier = segue.identifier
{
if identifier == "goToEdit"
{
let indexPath = self.tbl.indexPathForSelectedRow
let addMemoryViewController = segue.destination as! AddMemoryViewController
self.strMode = "edit"
self.lastIndex = (indexPath?.row)!
addMemoryViewController.mode = self.strMode
addMemoryViewController.current = memories[(indexPath?.row)!]
}
}
}
var searching = false
}
extension MemoryViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredDataa = memoriesTitlesArr.filter({ $0.prefix(searchText.count)==searchText.lowercased()})
searching = true
tbl.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searching = false
searchBar.text = ""
tbl.reloadData()
}
}
Here is how you can get that working.
1. First of all, there is no need for searching to maintain the state of searching and not searching.
2. Secondly, use filteredData as the dataSource for tableView instead of memories. filteredData will initially contain all the objects from memories, i.e.
var memories : [Memory] = []
lazy var filteredData = self.memories
The UITableViewDataSource methods will be like,
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.filteredData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "iden") {
cell.textLabel?.text = self.filteredData[indexPath.row].title
return cell
}
return UITableViewCell()
}
Now, while searching update the filteredData with filtered memories using the relevant condition, i.e.
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
self.filteredData = self.memories.filter({ $0.title.hasPrefix(searchText) })
//change the condition as per your requirement......
self.tbl.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.text = nil
self.filteredData = self.memories
self.tbl.reloadData()
}
When cancelled, refill the filteredData with the whole memories data.

Index out of range custom cell TableViewController

I'm trying to populate 3 custom cells into a TableViewController.
but I always get index out of range error. I`m not sure whats wrong with my code. anyone can help me, I'm newbie in swift.
but when i use 0 for numberOfRowsInSection return, the output is the first cell.
here's my code :
class testResize: UITableViewController {
#objc var comments = [AnyObject]()
#objc var images = [UIImage]()
var getImg = [String]()
override func viewDidLoad() {
super.viewDidLoad()
loadPosts()
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let getCom = comments[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: testResizeHeadCell.self), for: indexPath) as! testResizeHeadCell
let user = getCom["nickname"] as! String
let ava = getCom["ava"] as! String
if ava != "" {
let resource = ImageResource(downloadURL: URL(string: ava)!, cacheKey: ava)
cell.avaImg.kf.setImage(with: resource)
}
cell.username.text = user
return cell
}else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: testResizeCell.self), for: indexPath) as! testResizeCell
cell.setCustomImage(image: images[indexPath.row])
return cell
}else {
let getCom = comments[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: testRezieTextCell.self), for: indexPath) as! testRezieTextCell
let text = getCom["text"] as! String
cell.explaination.text = text
return cell
}
}
here is my load function :
#objc func loadPosts() {
let uuid = "959D1073"
let url = URL(string: "some/url.php")!
self.tableView.reloadData()
var request = URLRequest(url: url)
request.httpMethod = "POST"
let body = "uuid=\(uuid)"
//print(body)
request.httpBody = body.data(using: String.Encoding.utf8)
URLSession.shared.dataTask(with: request) { data, response, error in
DispatchQueue.main.async(execute: {
if error == nil {
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
self.comments.removeAll(keepingCapacity: false)
self.images.removeAll(keepingCapacity: false)
self.tableView.reloadData()
guard let parseJSON = json else {
print("Error While Parsing")
return
}
guard let posts = parseJSON["posts"] as? [AnyObject] else {
print("Error while parseJSONing")
return
}
self.comments = posts.reversed()
print(self.comments)
for i in 0 ..< self.comments.count {
let path = self.comments[i]["path"] as? String
self.getImg = [path!]
if !path!.isEmpty {
let url = NSURL(string: path!)!
let imageData = try? Data(contentsOf: url as URL)
let image = UIImage(data: imageData! as Data)!
self.images.append(image)
} else {
let image = UIImage()
self.images.append(image)
}
}
self.tableView.reloadData()
//print(posts)
} catch {
print(error)
}
}else{
print(error!)
}
})
}.resume()
}
i think you have a single comment and 3 cell type and when you use indexPath.row happen some thing like this :
for example :
comments = {[{nickname : "mahdi" , ava : "url"} ]}
if indexPath.row == 0 {
let getCom = comments[0]
let user = getCom["nickname"] as! String
let ava = getCom["ava"] as! String
}else if indexPath.row == 1 {
images[1]
}else {
let getCom = comments[2]
let text = getCom["text"] as! String
}
but you have just one comment and when you call comments[1] or commens [2] , you get index out of range error
please try this code :
class testResize:UITableViewController {
#objc var comments = [AnyObject]()
#objc var images = [UIImage]()
var getImg = [String]()
override func viewDidLoad() {
super.viewDidLoad()
loadPosts()
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (self.comments.count == 0 ? 0 : self.comments.count + 2)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let getCom = comments[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: testResizeHeadCell.self), for: indexPath) as! testResizeHeadCell
let user = getCom["nickname"] as! String
let ava = getCom["ava"] as! String
if ava != "" {
let resource = ImageResource(downloadURL: URL(string: ava)!, cacheKey: ava)
cell.avaImg.kf.setImage(with: resource)
}
cell.username.text = user
return cell
}else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: testResizeCell.self), for: indexPath) as! testResizeCell
cell.setCustomImage(image: images[indexPath.row - 1])
return cell
}else {
let getCom = comments[indexPath.row - 2]
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: testRezieTextCell.self), for: indexPath) as! testRezieTextCell
let text = getCom["text"] as! String
cell.explaination.text = text
return cell
}
}
and change your numberOfRowInSection :
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return (self.comments.count == 0 ? 0 : self.comments.count + 2)
}
I am assuming that you load your posts asynchronously.
But you do not check if there are actually enough elements in the array. You should check if there are actually enough elements in the array before you access it with a fixed index.
Additionally, you should change your numberOfRows method to the following:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.comments.count
}
After you have loaded your posts, you can then call
self.tableView.reloadData()

image not displaying on cell swift

I'm trying to pick an image and convert it to a string to save into the model var picture = "". I can select the image but it's not displaying any suggestions on my error will help.
UPDATE: I figured it out with these changes and still used a string for the model.
var imagePath = ""
var profilePic: UIImage?
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let referenceUrl = info[UIImagePickerControllerReferenceURL] as? URL, let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
ALAssetsLibrary().asset(for: referenceUrl, resultBlock: { asset in
let fileName = asset?.defaultRepresentation().filename()
let userModel = User()
userModel.picture = fileName!
let filePath = "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/\(String(describing: fileName))"
self.imagePath = filePath
let imageData : NSData = UIImagePNGRepresentation(pickedImage)! as NSData
imageData.write(toFile: filePath, atomically: true)
UserDefaults.standard.set(imageData, forKey: "profileImage")
UserDefaults.standard.synchronize()
self.profilePic = pickedImage
self.tableView.reloadData()
}, failureBlock: nil)
}
dismiss(animated: true, completion: nil)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.section {
case Setting.preferences.rawValue:
guard let cell = tableView.dequeueReusableCell(withIdentifier: PreferencesTableViewCell.identifier,
for: indexPath) as? PreferencesTableViewCell else { return UITableViewCell() }
cell.addressTextfield.delegate = self
cell.cityTextField.delegate = self
cell.stateTextField.delegate = self
cell.zipcodeTextField.delegate = self
return cell
case Setting.personal.rawValue:
guard let cell = tableView.dequeueReusableCell(withIdentifier: PersonalTableViewCell.identifier,
for: indexPath) as? PersonalTableViewCell else { return UITableViewCell() }
cell.firstNameTextField.delegate = self
cell.lastNameTextField.delegate = self
cell.phoneNumberTextField.delegate = self
cell.emailTextField.delegate = self
cell.buttonTouchedClosure = { [weak self] in
self?.pickImage()
}
return cell
case Setting.notifications.rawValue:
guard let cell = tableView.dequeueReusableCell(withIdentifier: NotificationsTableViewCell.identifier,
for: indexPath) as? NotificationsTableViewCell else { return UITableViewCell() }
return cell
case Setting.social.rawValue:
guard let cell = tableView.dequeueReusableCell(withIdentifier: SocialTableViewCell.identifier,
for: indexPath) as? SocialTableViewCell else { return UITableViewCell() }
cell.logoutButton.addTarget(self, action: #selector(UserProfileTableViewController.logout), for: .touchUpInside)
return cell
default: return UITableViewCell()
}
}