How to Store data permanently in Swift 3 - ios

I am on a Timer project that takes a value from a variable through unwind segue to pass it to another view controller, then append its value to an Array that should be used to insert a row with the task name whenever the user pressed save button I need to save the result permanently, but I am confused which data should I save the value of the variable itself, the row, or the array?
var taskList = [String]()
#IBAction func saveToTaskList (segue: UIStoryboardSegue) {
let newItemViewController = segue.source as! AddTaskTableViewController
let name = newItemViewController.itemName
let date = newItemViewController.date
print("itemName passed is: \(name)")
if name == "" {
}
else {
print(date)
taskList.append(name!)
let indexToInsert = taskList.count == 0 ? 0 : taskList.count - 1
let indexPath = IndexPath(row: indexToInsert, section: 0)
tableView.insertRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
}
}
add task view controller
Timer / Task List

Ok, thanks to the hint of Matt Le Fleur
I solved the issue by using objects as below:
#IBAction func saveToTaskList (segue: UIStoryboardSegue) {
let newItemViewController = segue.source as! AddTaskTableViewController
var name = newItemViewController.itemName
let date = newItemViewController.date
let itemsObject = UserDefaults.standard.object(forKey: "items")
var items:[String]
if let tempItems = itemsObject as? [String] {
items = tempItems
items.append(name!)
print(items)
} else {
items = [name!]
}
UserDefaults.standard.set(items, forKey: "items")
name = ""
}
Then added a ViewDidAppear as below:
override func viewDidAppear(_ animated: Bool) {
let itemsObject = UserDefaults.standard.object(forKey: "items")
if let tempItems = itemsObject as? [String] {
items = tempItems
}
tableView.reloadData()
}

Related

How to get current child (AutoID) from Firebase clicking TableViewCell - SWIFT?

I need to get current child (AutoID) from Firebase by clicking TableViewCell. I have cells with names, and I need to get ID from current name (cell) and passing to another view controller where will be displayed more details for that person.
So, I'm new in swift and I want to know how to get the ID?
This is in my VC1 ->
'''
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedGuest = guestsList[indexPath.row]
let controller = self.storyboard?.instantiateViewController(identifier:
"GuestDetail") as! GuestDetailsViewController
controller.guestUser = selectedGuest
self.present(controller, animated: true, completion: nil)
}
//THIS IS MY VC 2
func showGuestDetails(){
ref = Database.database().reference().child("userInfo").child(uid!).child("guests")
ref.queryOrderedByKey().observeSingleEvent(of: .value) { (snapshot) in
if snapshot.childrenCount>0{
self.guestDetail.removeAll()
for guests in snapshot.children.allObjects as![DataSnapshot]{
let guestObject = guests.value as? [String: AnyObject]
let name = guestObject?["guestName"]
let familyName = guestObject?["guestFamilyName"]
let phone = guestObject?["guestPhoneNumber"]
guard let email = guestObject?["guestEmail"] as? String,
email != self.guestUser?.guestEmail else {
continue
}
let guest = GuestModel(guestName: name as? String, guestFamilyName: familyName as! String, guestPhoneNumber: phone as? String, guestEmail: email as? String)
self.phoneNoLabel.text = guest.guestPhoneNumber
self.emailLabel.text = guest.guestEmail
}
}
}
self.nameLabel.text = guestUser!.guestName
}
'''
Try guests.key inside the for-loop

How to iterate through each key that contains the current rider id?

I am trying to retrieve data from firebase to place in textviews but the code I have is only giving me one instance of all the keys in "history".
I want to get the data, if the "rider" is equal to the current rider id.
I have tried different solutions here and on internet but nothing seemed to do what I needed it to do.
Firebase database:
The code I have :
let rider = FIRAuth.auth()?.currentUser?.displayName
// getting a reference to the node history
historyRef = ref.child("history")
// retrieve history key from firebase ....
let query = historyRef.queryOrdered(byChild: "rider").queryEqual(toValue: uid)
query.observe(.childAdded) { (snapshot) in
// history auto generated key ............
_ = snapshot.value as? String
let key = snapshot.key
// get values from history and place in outlet
self.historyRef.child(key).observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() {
var dict = snapshot.value as! [String: AnyObject]
self.price = ((dict["ride_price"] as AnyObject) as! Double)
self.txtPrice1.text = "\(self.price!)" // to make double work in textview
self.txtPrice1.text = "\( Double(round(100 * self.price!)/100) )" // format .xx
self.txtPrice2.text = "\( Double(round(100 * self.price!)/100) )"
self.txtPrice3.text = "\( Double(round(100 * self.price!)/100) )"
self.distance = ((dict["distance"] as AnyObject) as! Double)
self.txtDistance.text = "\(self.distance!)"
self.txtDistance.text = "\( Double(round(100 * self.distance!)/100) )"
self.location = (dict["location"] as! String)
self.txtLocation.text = self.location
self.destination = (dict["destination"] as! String)
self.txtDestination.text = self.destination
self.timestamp = (dict["timestamp"] as! String)
self.txtTimestamp.text = self.timestamp
}
})
}
With the assistance of #Ratul Sharker, my issue is resolved. Here is what we had to do -- pass the key from History to HistoryDetails.
TripHistory
In my previous screen that contains the tableview that leads to the page in question
private var selectedIndexPath: IndexPath?
// didSelectRowAt indexPath
selectedIndexPath = indexPath
performSegue(withIdentifier: "segueShowTripDetail", sender: self)
// add method:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let key = completedTrips[selectedIndexPath!.row]
if segue.identifier == "segueShowTripDetail" {
let destination = segue.destination as! TripDetail
destination.key = key
}
}
In TripDetail
public var key: String! // container for the passed-in historyKey
// use passed-in 'key'
self.historyRef.child(self.key).observe(.value, with: { (snapshot) in

Attempting to get numberOfRowsInSection count to be equal to an array count from another file in Swift

Currently I am fetching data from firebase, turning the data into an array of objects and trying to have that array count be the count of the "numberOfRowsInSection".
So, I get the right count on the view controller where the array is declare but I keep getting 0's when I pass that data to the tableview controller.
Below I am showing the viewcontroller where I am fetching data and putting it in a filtered array:
func fetchAllData( completion: #escaping (_ call: [Restaurant]) -> Void) {
self.ref = Database.database().reference()
self.ref?.observe(.value, with: { (snap) in
guard let topArray = snap.value as? [[String:Any]] else {print(":(") ; return }
var restaurantArray = [Restaurant]()
for dictionary in topArray {
self.restaurantGroup.enter()
guard let address = dictionary["Address"] as? String,
let city = dictionary["City"] as? String,
let inspectionDate = dictionary["Inspection Date"] as? String,
let name = dictionary["Name"] as? String,
let major = dictionary["Number of Occurrences (Critical Violations)"] as? Int,
let minor = dictionary["Number of Occurrences (Noncritical Violations)"] as? Int,
let violationTitle = dictionary["Violation Title"] as? String else { continue }
print(2)
//MARK: - creates restaurants from the list above
let restaurant = Restaurant(address: address, city: city, inspectionDate: inspectionDate, name: name, major: major, minor: minor, violationTitle: violationTitle)
print(3)
//MARK: - Adds a restaurant to restaurant array instance
restaurantArray.append(restaurant)
}
self.restaurantList = restaurantArray
self.restaurantGroup.leave()
completion(self.restaurantList)
let dictionaryNew = Dictionary(grouping: self.restaurantList) { $0.name + " " + $0.address}
self.restaurantListModified = dictionaryNew
print(self.restaurantListModified.count)
})
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
var filteredArray = [[Restaurant]]()
guard let userSearch = searchBar.text?.uppercased() else { return }
pulleyViewController?.setDrawerPosition(position: .partiallyRevealed, animated: true)
var nameArray = [String]()
for (key, value) in restaurantListModified {
if value[0].name.hasPrefix(userSearch.uppercased()){
filteredArray.append(value)
}
}
for subarray in filteredArray {
let nameArrayForTBView = subarray[0].name
nameArray.append(nameArrayForTBView)
}
self.tableViewNameArray = nameArray
print("\(tableViewNameArray.count)😋😋😋😋😋😋😋😋😋😋😋😋")
print("this First")
}
}
The tableViewNameArray is the array I am trying to pass to this tableView Controller
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("This second")
print(MapViewController.sharedMapViewController.tableViewNameArray.count)
return MapViewController.sharedMapViewController.tableViewNameArray.count
}
I also have my array set to a Notification Center that is received in the tableView Controller as shown below:
var tableViewNameArray = [String]() {
didSet {
DispatchQueue.main.async {
DispatchQueue.main.async {
NotificationCenter.default.post(name: MapViewController.RestaurantNotification.notificationSet, object: self)
}
}
}
}
Points:
My array from viewcontroller is getting the right count on the view controller but the accurate count is not being passed to the tableView Controller.
the tableview count for the array being passed is 0
I found the problem that #Kamran pointed to. I was not assigning self.tableViewNameArray = nameArray. So I changed
var tableViewNameArray to
static var tableViewNameArray
If you're new to programming like I, make sure you read a bit more on local and global variables. Very helpful.

How to append data in to NSMutableArray in ios swift

I'm working on an food ordering app currently when I add items into any array, then I need to pass that items to cartVC via CartDataModal where the cartArrayDict is of NSMutableArray type. But when I insert the SelectedDict the app crashes can anyone help me with this?
Heres my code:
var restMenu = [[String:Any]]()
func addTapped(cell: RestaurantItemViewCell)
{
//get the indexPath for add button click
let indexPath = self.restTableView.indexPath(for: cell)
print("the indexPath is", indexPath?.row)
print("all obj is",restMenu)
var selectedDict = restMenu[(indexPath?.row)!]
print("selected dict is",selectedDict)
selectedDict["ItemQuant"] = cell.itemQuantityLabel.text
print("selected dict is",selectedDict)
// Append In Cart Modal
CartDataModal.shared_Inst.cartArrayDict.insert(selectedDict, at: (indexPath?.row)!)
print("rest menu is",restMenu)
restMenu.remove(at: (indexPath?.row)!)
print("rest menu is",restMenu)
restMenu.insert(selectedDict, at: (indexPath?.row)!)
print("restmenu is",restMenu)
}
My CartDataModal:
class CartDataModal: NSObject {
static let shared_Inst = CartDataModal()
var cartArrayDict: [String:Any]!
}
from my ViewController i'm getting data From my Restaurant.plist
func moveToDetailController(img:UIImage,name:String)
{
print("the rest name is", name)
let pathUrl = Bundle.main.path(forResource: "ResturantFile", ofType: ".plist")
print("path url is",pathUrl as Any)
let finalArray = NSMutableArray(contentsOfFile: pathUrl!)
print("final Array is",finalArray)
let restaurantNames = finalArray?.firstObject as? NSDictionary
print("resturant name is",restaurantNames as Any)
if let menuDataArray:[[String:Any]] = restaurantNames?.value(forKey: name) as? [[String:Any]]
{
print("menu data is",menuDataArray)
let restVC = self.storyboard?.instantiateViewController(withIdentifier: "RestaurantViewController") as! RestaurantViewController
restVC.tempImg = img
restVC.tempTitle = name
restVC.restMenu = menuDataArray
self.navigationController?.pushViewController(restVC, animated: true)
}
}
You need to modify your struct:
class CartDataModal: NSObject {
static let shared_Inst = CartDataModal()
var cartArrayDict = [[String: Any]]()
}
You need to init array of the dictionary before insert. So You can init in struct or you can init before use according to your use.

UserDefault Won't save data in tableView Swift 4

I have been trying to save data when reloading app. However some how data won't save.
my global variable
let defaults = UserDefaults.standard
this is my code on AddTaskView
#IBAction func addTask(_ sender: Any) {
let date = datePicker.date
let dateStr = dateFormatter.string(from: date)
taskArray.append(selectedTask)
dateArray.append(dateStr)
defaults.set(selectedTask, forKey: "task")
defaults.set(dateStr, forKey: "date")
dismiss(animated: true, completion: nil)
}
In my ViewController I have my viewWillApper
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
defaults.string(forKey: "task")
defaults.string(forKey: "date")
tableView.reloadData()
}
If I print the data coming back from AddTaskView It will print on console
but data disappear when reloading app
tableView.dataSource = self (saved in my viewDidLoad)
this is my tableView
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "taskCell", for: indexPath)
cell.textLabel?.text = "\(indexPath.row + 1). \(taskArray[indexPath.row])"
cell.detailTextLabel?.text = dateArray[indexPath.row]
return cell
}
What Am I doing wrong?
thanks
You have multiple checks to do:
defaults.string(forKey: "task") has a return value that you dont use
As you append entered data, check if its has been append.
If entered value is there, check count of rows of the table.
I believe the key to solve your problem is in one of these points.
Took me a while but I finally figured
#IBAction func addTask(_ sender: Any) {
let date = datePicker.date
let dateStr = dateFormatter.string(from: date)
taskArray.append(selectedTask)
dateArray.append(dateStr)
defaults.set(taskArray, forKey: "task")
defaults.set(dateArray, forKey: "date")
defaults.synchronize()
dismiss(animated: true, completion: nil)
}
func loadUserDefaults() {
if let tempStr = defaults.stringArray(forKey: "task") {
taskArray = tempStr as [String]
}
if let tempDateStr = defaults.stringArray(forKey: "date") {
dateArray = tempDateStr as [String]
}
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
loadUserDefaults()
}

Resources