I am having two ViewControllers, one called ComposingOverviewViewController and another one called CheapestViewController.
If the User presses a Button, he/ she ;) will be shown the CheapestViewController. If the user presses "Choose", cheapestBoolbecomes true. The selection made should be stored in Firebase, with the bool set as "true", so it can be checked afterwards, if the selection should be shown or not. Even when I check it while saving the data to firebase, Xcode tells me that the value is actually "true". But in Firebase it gets stored as "false".
I have to say, that to actually show something in CheapestViewController, the User has first to press the Button check Values. Since I am aware, that as soon as the View switches back again from CheapestViewControllerto ComposingOverviewViewControllerthe generated Selection gets lost. So as soon as the User presses "Save" in the ComposingOverviewController the selection gets generated again.
Maybe it has to do something with this.
I deleted as much unnecessary code as possible.
Hope that's okay for everyone!
But I actually don't have any clue.
Maybe someone can help. :)
class ComposingOVerviewViewController: UIViewController {
#IBOutlet weak var cheapestImageView: UIImageView!
var individualimageViewBool = false
var cheapestimageviewBool = false
var efficientImageViewBool = false
var bestImageViewBool = false
var overAllBestImageViewBool = false
var DollarJPerfor:Double?
var projectCreated:String?
let uid = User.current.uid
var indivCompValue = [WeighScore]()
var projCompValue = [ProjCompValue]()
var projectBudget:Int = 0
var projectDifficulty:Double = 0
var projectCreativity:Double = 0
var finalCheapest: [WeighScore] = []
var cheapestBool:Bool?
var freelancerArray = [WeighScore]()
var jobAmountNeeded = [JobNeeded]()
override func viewDidLoad() {
super.viewDidLoad()
UserService.projectjobamount(for: User.current, projectCreated: projectCreated ?? "no Value") { (jobNeeded) in
self.jobAmountNeeded = jobNeeded
}
UserService.individualComposingValues(for: User.current) { (indivCompValue) in
self.freelancerArray = indivCompValue
}
projectSpecification(for: User.current, projectCreated: projectCreated ?? "no Value")
imageHighlights()
}
// MARK: - Highlighten the Images when Team selected
func imageHighlights() {
if individualimageViewBool == true {
individualImageView.image = UIImage(named: "Individual-1")
} else {
individualImageView.image = UIImage(named: "Individual") }
if cheapestimageviewBool == true {
cheapestImageView.image = UIImage(named: "cheapesthigh")
cheapestBool = true
}
else { cheapestImageView.image = UIImage(named: "Cheapest") }
if efficientImageViewBool == true {
efficientImageView.image = UIImage(named: "Efficient-1")
}
else { efficientImageView.image = UIImage(named: "Efficient") }
if bestImageViewBool == true {
bestImageView.image = UIImage(named: "Besthighlight") }
else {bestImageView.image = UIImage(named: "Best") }
if overAllBestImageViewBool == true {
overAllBestImageView.image = UIImage(named: "absolutbesthigh") }
else {overAllBestImageView.image = UIImage(named: "absolutbest") }
}
func getCheapest(member: [WeighScore], neededValue: [JobNeeded]) {
var tempArray1: [WeighScore] = []
for jobAmount in jobAmountNeeded {
let neededValue = jobAmount.jobAmount
tempArray1 = freelancerArray.filter { $0.memberJob == jobAmount.jobName}
let amountInArray = tempArray1.count
if neededValue == 0 { return
} else if neededValue == amountInArray{
tempArray1.sort(by: {$0.normalPrice! < $1.normalPrice!})
for value in tempArray1 {
print(value.memberName as Any)
print(tempArray1.count)
finalBest.append(value) }
} else {
tempArray1.sort(by: {$0.normalPrice! < $1.normalPrice!})
let deletedValue = tempArray1.count - neededValue
print("deleted Value: ", deletedValue)
tempArray1.remove(0..<deletedValue)
for value in tempArray1 {
print(value.memberName as Any)
print(tempArray1.count)
finalCheapest.append(value)
}
}
}
}
// MARK: - Button Function to check Values only
#IBAction func checkValues(_ sender: Any) {
getBest(member: freelancerArray, neededValue: jobAmountNeeded, budgetLevel: projectBudget)
getAbsolutBest(member: freelancerArray, neededValue: jobAmountNeeded)
getMostEfficient(member: freelancerArray, neededValue: jobAmountNeeded)
getCheapest(member: freelancerArray, neededValue: jobAmountNeeded)
}
// MARK: - Save the Team/ Teams
#IBAction func saveAction(_ sender: Any) {
print(cheapestBool)
getCheapest(member: freelancerArray, neededValue: jobAmountNeeded)
for value in finalCheapest {
let finalCheapest = "finalCheapest"
PostService.proposedTeams(projectCreated: projectCreated ?? "No Value", teamType: finalCheapest, memberJob: value.memberJob ?? "no value", memberName: value.memberName ?? "no Value", memberID: value.memberID ?? "no Value", ajp: value.ajp ?? 999, crea: value.crea ?? 999, ijr: value.ijr ?? 999, qpa: value.qpa ?? 999, coj: value.coj ?? 999, los: value.los ?? 999, iracc: value.iracc ?? 999, dph: value.dph ?? 999, normalPrice: value.normalPrice ?? 999, sumFreelanceRating: value.sumFreelanceRating ?? 999, priceJPerfScore: value.priceJPerfScore ?? 999, teamSelected: cheapestBool ?? false)
}
}
// MARK: - Pass data to specific ViewController of Team Alternatives
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "teamToCheapest" {
let destVC = segue.destination as! CheapestViewController
print(sentcheapestTeam.count)
destVC.finalCheapest = finalCheapest
}
}
// MARK: - Go to specific Teams
#IBAction func cheapest(_ sender: Any) {
performSegue(withIdentifier: "teamToCheapest", sender: self)
}
}
// MARK: - Extensions
extension Array {
mutating func remove(_ range: Range<Int>) -> Array {
let values = Array(self[range])
self.removeSubrange(range)
return values
}
}
class CheapestViewController: UIViewController {
// MARK: - Properties
#IBOutlet weak var tableView: UITableView!
// var VC = ComposingOVerviewViewController()
var finalCheapest = [WeighScore]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "cheapestToOverview" {
let destVC = segue.destination as! ComposingOVerviewViewController
destVC.cheapestBool = true
}
}
#IBAction func chooseCheapest(_ sender: Any) {
print(finalCheapest.count)
for value in finalCheapest {
print(value.memberJob)
}
performSegue(withIdentifier: "cheapestToOverview", sender: self)
}
}
class WeighScore {
var key: String?
let memberJob: String?
let memberName: String?
let memberID:String?
let ajp: Double?
let crea:Double?
let ijr:Double?
let qpa:Double?
let coj:Double?
let los:Double?
let iracc:Double?
let dph:Double?
let normalPrice:Double?
var sumFreelanceRating:Double?
let priceJPerfScore:Double?
init(ajp: Double, crea:Double, ijr:Double, qpa:Double, coj:Double, los:Double, iracc:Double, dph:Double, sumFreelanceRating:Double, normalPrice:Double, memberJob: String, memberName: String, priceJPerfScore:Double, memberID:String) {
self.ajp = ajp
self.crea = crea
self.ijr = ijr
self.qpa = qpa
self.coj = coj
self.los = los
self.iracc = iracc
self.dph = dph
self.sumFreelanceRating = sumFreelanceRating
self.normalPrice = normalPrice
self.memberName = memberName
self.memberJob = memberJob
self.priceJPerfScore = priceJPerfScore
self.memberID = memberID
}
var dictValue: [String: Any] {
return ["memberName" : memberName,
"memberJob" : memberJob,
"ajp" : ajp,
"crea" : crea,
"ijr" : ijr,
"qpa" : qpa,
"coj" : coj,
"los" : los,
"iracc" : iracc,
"dph" : dph,
"normalPrice": normalPrice,
"sumFreelanceRating" : sumFreelanceRating,
"priceJPerfScore": priceJPerfScore,
"memberID": memberID,
]
}
init?(snapshot: DataSnapshot) {
guard let dict = snapshot.value as? [String: Any],
let memberJob = dict["memberJob"] as? String,
let memberName = dict["memberName"] as? String,
let ajp = dict["ajp"] as? Double,
let crea = dict["crea"] as? Double,
let ijr = dict["ijr"] as? Double,
let qpa = dict["qpa"] as? Double,
let coj = dict["coj"] as? Double,
let los = dict["los"] as? Double,
let iracc = dict["iracc"] as? Double,
let dph = dict["dph"] as? Double,
let normalPrice = dict["normalPrice"] as? Double,
let sumFreelanceRating = dict["sumFreelanceRating"] as? Double,
let priceJPerfScore = dict["priceJPerfScore"] as? Double,
let memberID = dict["memberID"] as? String
else {return nil}
self.memberJob = memberJob
self.memberName = memberName
self.ajp = ajp
self.crea = crea
self.ijr = ijr
self.qpa = qpa
self.coj = coj
self.los = los
self.iracc = iracc
self.dph = dph
self.normalPrice = normalPrice
self.sumFreelanceRating = sumFreelanceRating
self.priceJPerfScore = priceJPerfScore
self.memberID = memberID
}
}
class TeamSetting {
var key: String?
let memberJob: String?
let memberName: String?
let memberID:String?
let ajp: Double?
let crea:Double?
let ijr:Double?
let qpa:Double?
let coj:Double?
let los:Double?
let iracc:Double?
let dph:Double?
let normalPrice:Double?
var sumFreelanceRating:Double?
let priceJPerfScore:Double?
var teamSelected: Bool?
init(ajp: Double, crea:Double, ijr:Double, qpa:Double, coj:Double, los:Double, iracc:Double, dph:Double, sumFreelanceRating:Double, normalPrice:Double, memberJob: String, memberName: String, priceJPerfScore:Double, memberID:String, teamSelected: Bool) {
self.ajp = ajp
self.crea = crea
self.ijr = ijr
self.qpa = qpa
self.coj = coj
self.los = los
self.iracc = iracc
self.dph = dph
self.sumFreelanceRating = sumFreelanceRating
self.normalPrice = normalPrice
self.memberName = memberName
self.memberJob = memberJob
self.priceJPerfScore = priceJPerfScore
self.memberID = memberID
self.teamSelected = teamSelected
}
var dictValue: [String: Any] {
return ["memberName" : memberName,
"memberJob" : memberJob,
"ajp" : ajp,
"crea" : crea,
"ijr" : ijr,
"qpa" : qpa,
"coj" : coj,
"los" : los,
"iracc" : iracc,
"dph" : dph,
"normalPrice": normalPrice,
"sumFreelanceRating" : sumFreelanceRating,
"priceJPerfScore": priceJPerfScore,
"memberID": memberID,
"teamSelected": teamSelected]
}
init?(snapshot: DataSnapshot) {
guard let dict = snapshot.value as? [String: Any],
let memberJob = dict["memberJob"] as? String,
let memberName = dict["memberName"] as? String,
let ajp = dict["ajp"] as? Double,
let crea = dict["crea"] as? Double,
let ijr = dict["ijr"] as? Double,
let qpa = dict["qpa"] as? Double,
let coj = dict["coj"] as? Double,
let los = dict["los"] as? Double,
let iracc = dict["iracc"] as? Double,
let dph = dict["dph"] as? Double,
let normalPrice = dict["normalPrice"] as? Double,
let sumFreelanceRating = dict["sumFreelanceRating"] as? Double,
let priceJPerfScore = dict["priceJPerfScore"] as? Double,
let memberID = dict["memberID"] as? String,
let teamSelected = dict["teamSelected"] as? Bool
else {return nil}
self.memberJob = memberJob
self.memberName = memberName
self.ajp = ajp
self.crea = crea
self.ijr = ijr
self.qpa = qpa
self.coj = coj
self.los = los
self.iracc = iracc
self.dph = dph
self.normalPrice = normalPrice
self.sumFreelanceRating = sumFreelanceRating
self.priceJPerfScore = priceJPerfScore
self.memberID = memberID
self.teamSelected = teamSelected
}
}
There's no firebase code in the question so answering this question
Swift Firebase doesn't store Bool?
is not possible.
There's a lot of code in the question but it appears this is a Master->Detail setup (?) with the master viewController being ComposingOVerviewViewController and the detail being CheapestViewController. If so one issue appears to be that the detail viewController is spawning a new master?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "cheapestToOverview" {
let destVC = segue.destination as! ComposingOVerviewViewController
destVC.cheapestBool = true
}
}
Related
No cell of UITableView is displayed.
Probably the cause seems to be part of the setting of delegate and dataSource of UITableView, but I do not know the specific point.
So paste all the code.
If you do not understand the intention of the question, please do not hesitate to tell me.
I will tell you sincerity sincerity.
import UIKit
import Firebase
import FirebaseStorage
import FirebaseFirestore
import SDWebImage
struct CellData {
var date: Date
var time: String
var title: String
var name: String
var image: URL
}
struct TableSection<SectionItem: Comparable&Hashable, RowItem>: Comparable {
var sectionItem: SectionItem
var rowItems: [RowItem]
static func < (lhs: TableSection, rhs: TableSection) -> Bool {
return lhs.sectionItem > rhs.sectionItem
}
static func == (lhs: TableSection, rhs: TableSection) -> Bool {
return lhs.sectionItem == rhs.sectionItem
}
static func group(rowItems : [RowItem], by criteria : (RowItem) -> SectionItem ) -> [TableSection<SectionItem, RowItem>] {
let groups = Dictionary(grouping: rowItems, by: criteria)
return groups.map(TableSection.init(sectionItem:rowItems:)).sorted()
}
}
fileprivate func parseDate(_ str: String) -> Date {
let dateFormat = DateFormatter()
dateFormat.dateFormat = "yyyy年MM月dd日"
return dateFormat.date(from: str)!
}
fileprivate func firstDayOfMonth(date: Date) -> Date {
let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month, .day], from: date)
return calendar.date(from: components)!
}
class timelineViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
var arr = [CellData]()
let db = Firestore.firestore()
var sections = [TableSection<Date, CellData>]()
var teamIDFromFirebase: String = ""
var fireAuthUID = (Auth.auth().currentUser?.uid ?? "no data")
var dataImageFromFirestore = [Any]()
var dataTitleFromFireStore = [Any]()
var dataTimeFromFirestore = [Any]()
var dataNameFromFireStore = [Any]()
var dataDateFromFiewstore = [Any]()
var timelineDocumentIdArr = [Any]()
var draftDocumentIdArr = [Any]()
var submitDocumentIdArr = [Any]()
var selectedNum = 0
#IBOutlet weak var circleButton: UIButton!
#IBOutlet weak var userTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
circleButton = Circle()
if arr != nil {
self.arr = []
self.dataNameFromFireStore = [Any]()
self.dataTimeFromFirestore = [Any]()
self.dataTitleFromFireStore = [Any]()
self.dataImageFromFirestore = [Any]()
self.submitDocumentIdArr = [Any]()
self.selectedNum = 1
userTable.delegate = self
userTable.dataSource = self
userTable.register(UINib(nibName: "userTableViewCell", bundle: nil), forCellReuseIdentifier: "cellName")
self.db.collection("users").document(self.fireAuthUID).addSnapshotListener { (snapshot3, error) in
guard let document3 = snapshot3 else {
print("erorr2 \(String(describing: error))")
return
}
guard let data = document3.data() else { return }
self.teamIDFromFirebase = data["teamID"] as? String ?? ""
self.db.collection("diary").document(self.teamIDFromFirebase).collection("diaries").whereField("submit", isEqualTo: true).getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
return self.arr = [CellData(date: parseDate(""), time: "", title: "", name: "", image:URL(string: "")!)]
} else {
var i = 0
for document in querySnapshot!.documents {
self.timelineDocumentIdArr.append(document.documentID)
guard let documentData: [String: Any] = document.data() else { return }
self.dataTitleFromFireStore.append((documentData["今日のタイトル"] as? String)!)
self.dataTimeFromFirestore.append((documentData["time"] as? String)!)
self.dataNameFromFireStore.append((documentData["userName"] as? String)!)
self.dataImageFromFirestore.append((documentData["image"] as? String)!)
self.dataDateFromFiewstore.append((documentData["date"] as? String)!)
self.arr.append(CellData(date: parseDate(self.dataDateFromFiewstore[i] as! String), time: self.dataTimeFromFirestore[i] as? String ?? "", title: self.dataTitleFromFireStore[i] as? String ?? "", name: self.dataNameFromFireStore[i] as? String ?? "", image: URL(string: self.dataImageFromFirestore[i] as! String)!))
i += 1
}
self.userTable.reloadData()
}
}
}
}
self.sections = TableSection.group(rowItems: self.arr, by: { (headline) in
firstDayOfMonth(date: headline.date)
})
}
func numberOfSections(in tableView: UITableView) -> Int {
return self.sections.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let section = self.sections[section]
let date = section.sectionItem
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy年MM月dd日"
return dateFormatter.string(from: date)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let section = self.sections[section]
return section.rowItems.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = userTable.dequeueReusableCell(withIdentifier: "cellName", for: indexPath) as! userTableViewCell
let section = self.sections[indexPath.section]
let cellDetail = section.rowItems[indexPath.row]
cell.userTitle.text = cellDetail.title
cell.userName.text = cellDetail.name
cell.userTime.text = cellDetail.time
cell.userImage.sd_setImage(with: cellDetail.image)
return cell
}
}
You should assign the sections property inside the closure. This is corrected the viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
circleButton = Circle()
if arr != nil {
self.arr = []
self.dataNameFromFireStore = [Any]()
self.dataTimeFromFirestore = [Any]()
self.dataTitleFromFireStore = [Any]()
self.dataImageFromFirestore = [Any]()
self.submitDocumentIdArr = [Any]()
self.selectedNum = 1
userTable.delegate = self
userTable.dataSource = self
userTable.register(UINib(nibName: "userTableViewCell", bundle: nil), forCellReuseIdentifier: "cellName")
self.db.collection("users").document(self.fireAuthUID).addSnapshotListener { (snapshot3, error) in
guard let document3 = snapshot3 else {
print("erorr2 \(String(describing: error))")
return
}
guard let data = document3.data() else { return }
self.teamIDFromFirebase = data["teamID"] as? String ?? ""
self.db.collection("diary").document(self.teamIDFromFirebase).collection("diaries").whereField("submit", isEqualTo: true).getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
return self.arr = [CellData(date: parseDate(""), time: "", title: "", name: "", image:URL(string: "")!)]
} else {
var i = 0
for document in querySnapshot!.documents {
self.timelineDocumentIdArr.append(document.documentID)
guard let documentData: [String: Any] = document.data() else { return }
self.dataTitleFromFireStore.append((documentData["今日のタイトル"] as? String)!)
self.dataTimeFromFirestore.append((documentData["time"] as? String)!)
self.dataNameFromFireStore.append((documentData["userName"] as? String)!)
self.dataImageFromFirestore.append((documentData["image"] as? String)!)
self.dataDateFromFiewstore.append((documentData["date"] as? String)!)
self.arr.append(CellData(date: parseDate(self.dataDateFromFiewstore[i] as! String), time: self.dataTimeFromFirestore[i] as? String ?? "", title: self.dataTitleFromFireStore[i] as? String ?? "", name: self.dataNameFromFireStore[i] as? String ?? "", image: URL(string: self.dataImageFromFirestore[i] as! String)!))
i += 1
}
self.sections = TableSection.group(rowItems: self.arr, by: { (headline) in
firstDayOfMonth(date: headline.date)
})
self.userTable.reloadData()
}
}
}
}
}
This is shopping app after user select the products send to cart then checkout after fill the fields and press Checkout (Pay) send the details of the products to my firebase database please any one can help me I use json as my load products on tableview cell
I know I don't have payment serves but on this fields of payment information will be name , phone number, and location
[{
"name": "EGG",
"price": "3.00",
"image": "http://partiklezoo.com/Egg/u0001.jpg",
"description": "one Egg",
"category": "Food",
"uid": "u0001"
},]
Code
import UIKit
class CheckoutViewController: DetailViewController, UITableViewDataSource, UITableViewDelegate, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet var cardNumber: UITextField!
#IBOutlet var cardExpiryMonth: UITextField!
#IBOutlet var cardExpiryYear: UITextField!
#IBOutlet var cardCvv: UITextField!
#IBOutlet var pickerPickupPoint: UIPickerView!
#IBOutlet var tableViewOrderDetails: UITableView!
#IBOutlet var labelTotalPrice: UILabel!
var model = SingletonManager.model
override func viewDidLoad() {
super.viewDidLoad()
self.configureCheckout()
self.tableViewOrderDetails.dataSource = self
self.tableViewOrderDetails.delegate = self
self.pickerPickupPoint.dataSource = self
self.pickerPickupPoint.delegate = self
//Looks for single or multiple taps.
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(CheckoutViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
}
#objc func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status.
self.view.endEditing(true)
}
func configureCheckout() {
pickerPickupPoint.selectedRow(inComponent: 0)
labelTotalPrice.text = "$" + String(format: "%.2f", model.calculateCartTotal())
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return model.cart.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = model.products[Int(model.cart[indexPath.row][0])].name
cell.detailTextLabel?.text = String(Int(model.cart[indexPath.row][1])) + " x $" + String(format: "%.2f", model.cart[indexPath.row][4])
return cell
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return model.pickUpLocations.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return model.pickUpLocations[row]["street"]! + ", " + model.pickUpLocations[row]["suburb"]!
}
#IBAction func payNow(_ sender: Any) {
var error = ""
if self.model.cart.count == 0 {
error = "Your cart is empty."
}
else if (self.cardNumber.text?.isEmpty)! {
error = "Please enter your card number."
}
else if (self.cardExpiryMonth.text?.isEmpty)! {
error = "Please enter the expiry month of your card."
}
else if (self.cardExpiryYear.text?.isEmpty)! {
error = "Please enter the expiry year of your card."
}
else if (self.cardCvv.text?.isEmpty)!{
error = "Please enter the CVV number of your card."
}
if error.isEmpty {
showAlertMsg("Confirm Purchase", message: "Pay " + labelTotalPrice.text!, style: UIAlertControllerStyle.actionSheet)
}
else {
showAlertMsg("Error", message: error, style: UIAlertControllerStyle.alert)
}
}
var alertController: UIAlertController?
func showAlertMsg(_ title: String, message: String, style: UIAlertControllerStyle) {
self.alertController = UIAlertController(title: title, message: message, preferredStyle: style)
if style == UIAlertControllerStyle.actionSheet {
alertController?.addAction(UIAlertAction(title: "Pay", style: .default, handler: { _ in
self.checkout()
}))
alertController?.addAction(UIAlertAction(title: "Cancel", style: .cancel))
} else {
alertController?.addAction(UIAlertAction(title: "Okay", style: .default))
}
self.present(self.alertController!, animated: true, completion: nil)
}
func checkout() {
var success = true
for count in 0...self.model.cart.count - 1 {
let product = self.model.products[Int(self.model.cart[count][0])]
let quantity = Int(self.model.cart[count][1])
let total = self.model.cart[count][4]
let material = self.model.cart[count][3] == 0.0 ? "pla" : "abs"
let painting = self.model.cart[count][2] == 0.0 ? "false" : "true"
let temp = self.model.purchase(product: product, quantity: quantity, total: total, material: material, painting: painting)
if !temp {
success = false
}
}
if !success {
let error = "Oops! Something went wrong. Please try again later."
showAlertMsg("Error", message: error, style: UIAlertControllerStyle.alert)
} else {
print("Success! Checkout complete.")
self.cardNumber.text = ""
self.cardExpiryMonth.text = ""
self.cardExpiryYear.text = ""
self.cardCvv.text = ""
self.labelTotalPrice.text = "$0.00"
self.model.clearCart()
self.tableViewOrderDetails.reloadData()
self.performSegue(withIdentifier: "Thankyou", sender: self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let confirmationVc = (segue.destination as! UINavigationController).topViewController as! ConfirmationViewController
confirmationVc.location = self.model.pickUpLocations[self.pickerPickupPoint.selectedRow(inComponent: 0)]
}
}
this is my objective
Class Model: NSObject, CLLocationManagerDelegate {
var segueArray = [String]()
var seguesDictionary = Dictionary<String, UIImage>()
var products = [Product]()
var storedProducts = [NSManagedObject]()
var cart = [[Double]]()
var storedCart = [NSManagedObject]()
var pickUpLocations = [[String: String]]()
let locationManager = CLLocationManager()
override init() {
super.init()
segueArray.append("Home")
segueArray.append("List")
segueArray.append("Search")
segueArray.append("Cart")
segueArray.append("Finder")
segueArray.append("Checkout")
seguesDictionary["Home"] = UIImage(named: "home")
seguesDictionary["List"] = UIImage(named: "list")
seguesDictionary["Search"] = UIImage(named: "search")
seguesDictionary["Cart"] = UIImage(named: "cart")
seguesDictionary["Finder"] = UIImage(named: "finder")
seguesDictionary["Checkout"] = UIImage(named: "checkout")
self.loadProducts()
self.refreshProducts()
self.loadCart()
self.configureLocManager()
}
func loadProducts() {
let managedContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Products")
do {
let results = try managedContext.fetch(fetchRequest)
storedProducts = results as! [NSManagedObject]
if storedProducts.count > 0 {
for index in 0...storedProducts.count - 1 {
let binaryData = storedProducts[index].value(forKey: "image") as! Data
let image = UIImage(data: binaryData)
let name = storedProducts[index].value(forKey: "name") as! String
let price = storedProducts[index].value(forKey: "price") as! Double
let details = storedProducts[index].value(forKey: "details") as! String
let category = storedProducts[index].value(forKey: "category") as! String
let uid = storedProducts[index].value(forKey: "uid") as! String
let loadedProduct = Product(name: name, price: price, image: image!, details: details, category: category, uid: uid)
products.append(loadedProduct)
}
}
}
catch let error as NSError
{
print("Could not load. \(error), \(error.userInfo)")
}
}
func refreshProducts() {
let url = NSURL(string: "http://partiklezoo.com/3dprinting/")
let config = URLSessionConfiguration.default
config.isDiscretionary = true
let session = URLSession(configuration: config)
let task = session.dataTask(with: url! as URL, completionHandler:
{(data, response, error) in
let json = JSON(data: data!)
for count in 0...json.count - 1
{
let newProduct = Product()
newProduct.name = json[count]["name"].string
newProduct.price = Double(json[count]["price"].string!)
newProduct.details = json[count]["description"].string
newProduct.category = json[count]["category"].string
newProduct.uid = json[count]["uid"].string
let imgURL = json[count]["image"].string!
self.addItemToList(newProduct, imageURL: imgURL)
}
})
task.resume()
}
func checkForProduct(_ searchItem: Product) -> Int {
var targetIndex = -1
if products.count > 0 {
for index in 0...products.count - 1 {
if products[index].uid == searchItem.uid {
targetIndex = index
}
}
}
return targetIndex
}
func addItemToList(_ newProduct: Product!, imageURL: String) {
if checkForProduct(newProduct) == -1 {
let managedContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let picture = UIImageJPEGRepresentation(loadImage(imageURL), 1)
let entity = NSEntityDescription.entity(forEntityName: "Products", in: managedContext)
let productToAdd = NSManagedObject(entity: entity!, insertInto: managedContext)
productToAdd.setValue(newProduct.category, forKey: "category")
productToAdd.setValue(newProduct.details, forKey: "details")
productToAdd.setValue(picture, forKey: "image")
productToAdd.setValue(newProduct.name, forKey: "name")
productToAdd.setValue(newProduct.price, forKey: "price")
productToAdd.setValue(newProduct.uid, forKey: "uid")
do
{
try managedContext.save()
}
catch let error as NSError
{
print("Could not save. \(error), \(error.userInfo)")
}
storedProducts.append(productToAdd)
newProduct.image = UIImage(data: picture!)
products.append(newProduct)
}
}
func loadCart() {
let managedContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Cart")
do {
let results = try managedContext.fetch(fetchRequest)
storedCart = results as! [NSManagedObject]
if storedCart.count > 0 {
for index in 0...storedCart.count - 1 {
let product = storedCart[index].value(forKey: "product") as! Double
let quantity = storedCart[index].value(forKey: "quantity") as! Double
let finish = storedCart[index].value(forKey: "finish") as! Double
let material = storedCart[index].value(forKey: "material") as! Double
let totalPrice = storedCart[index].value(forKey: "total") as! Double
let temp = [product, quantity, finish, material, totalPrice]
cart.append(temp)
}
}
}
catch let error as NSError
{
print("Could not load. \(error), \(error.userInfo)")
}
}
func addToCart(product: Product, quantity: Double, finish: Double, material: Double, totalPrice: Double) {
let managedContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Cart", in: managedContext)
let productToAdd = NSManagedObject(entity: entity!, insertInto: managedContext)
productToAdd.setValue(checkForProduct(product), forKey: "product")
productToAdd.setValue(quantity, forKey: "quantity")
productToAdd.setValue(finish, forKey: "finish")
productToAdd.setValue(material, forKey: "material")
productToAdd.setValue(totalPrice, forKey: "total")
do
{
try managedContext.save()
}
catch let error as NSError
{
print("Could not save. \(error), \(error.userInfo)")
}
let temp = [Double(checkForProduct(product)), quantity, finish, material, totalPrice]
storedCart.append(productToAdd)
cart.append(temp)
}
I am not sure I understand the question but from the comments I believe the OP is asking for example code to put into an action button to write date to Firebase. So here it is.
(note: please see comments as the OP didn't clarify what he was after so it's not clear if this is an answer or not)
Start with initialzing Firebase in your view controller
class ViewController: UIViewController {
var ref: DatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
self.ref = Database.database().reference()
then lets have a button press write two cars to firebase in a 'car_list' node
#IBAction func button0Action(_ sender: Any) {
let itemDict0 = [
"Name": "Car",
"price": "2000"]
let itemDict1 = [
"Name": "Car",
"price": "3000"]
let carRef = self.ref.child("car_list")
carRef.childByAutoId().setValue(itemDict0)
carRef.childByAutoId().setValue(itemDict1)
}
and the result in Firebase looks like this
car_list
-LKYuRKpLL_JXsDGsYWY
Name: "Car"
Price: "2000"
-LKYuRKpLL_JXsDGsYWZ
Name: "Car"
Price: "3000"
EDIT: I had intially set this up like a grocery list per the data in the question but per a comment from the OP they want to make it cars and prices, so that's how it is now.
I need to initialize an object, and pass it through a prepareforsegue to another class.
Last line of the code below throws "Contextual type 'FPChat!.Type' cannot be used with dictionary literal"
if (segue.identifier == "chatmessages") {
let vc = segue.destination as! FPChatMessageViewController
//vc.currentChat = fPChat
}
}
fPchat = FPChat?
// Start the Chat
#IBAction func Chat(_ sender: UIButton) {
// Create a new entry in chats. This variable is passed with prepareforsegue
let chatRef = ref.child("chats").childByAutoId()
let chatId = chatRef.key
//fPchat = FPChat?
let fPchat = FPChat.currentChat(currentChatID: chatId)
Below chat class:
import Firebase
class FPChat {
var chatID = ""
var chatDate: Date!
var text = ""
var messages: [FPChatMessage]!
var author: FPUser!
var mine = true
// Calling FPChat.currentChat(id) I have back the FPChat object
static func currentChat(currentChatID: String) -> FPChat {
return FPChat(chatID: currentChatID)
}
private init(chatID: String) {
self.chatID = chatID
}
init(snapshot: DataSnapshot, andMessages messages: [FPChatMessage]) {
guard let value = snapshot.value as? [String: Any] else { return }
self.chatID = snapshot.key
if let text = value["text"] as? String {
self.text = text
}
guard let timestamp = value["timestamp"] as? Double else { return }
self.chatDate = Date(timeIntervalSince1970: (timestamp / 1_000.0))
guard let author = value["author"] as? [String: String] else { return }
self.author = FPUser(dictionary: author)
self.messages = messages
self.mine = self.author.userID == Auth.auth().currentUser?.uid
}
}
What I am doing wrong?
people in my app sometimes needs to update the status of something. Now can you choose of 2 things: The so called "Rollerbank" is still there or the "Rollerbank" is removed. The users can create a data ref. The id that will be created by childbyAutoID. Now is my question how to get the right child and update some childs with a value. My post:
class Post {
let ref: DatabaseReference!
var TypeControle: String = ""
var Stad: String = ""
var Tijd: String = ""
var TijdControle: String = ""
var TijdControleniet: String = ""
var Latitude: String = ""
var Longitude: String = ""
var Extrainformatie: String = ""
var Staater: String = ""
var Staaternietmeer: String = ""
init(TypeControle: String) {
self.TypeControle = TypeControle
ref = Database.database().reference().child("Rollerbanken").childByAutoId()
}
init(Stad: String){
self.Stad = Stad
ref = Database.database().reference().child("Rollerbanken").childByAutoId()
}
init(Tijd: String) {
self.Tijd = Tijd
ref = Database.database().reference().child("Rollerbanken").childByAutoId()
}
init(Latitude: String) {
self.Latitude = Latitude
ref = Database.database().reference().child("Rollerbanken").childByAutoId()
}
init(Longitude: String) {
self.Longitude = Longitude
ref = Database.database().reference().child("Rollerbanken").childByAutoId()
}
init(Extrainformatie: String) {
self.Extrainformatie = Extrainformatie
ref = Database.database().reference().child("Rollerbanken").childByAutoId()
}
init(Staater: String) {
self.Staater = Staater
ref = Database.database().reference().child("Rollerbanken").child("Controletest").childByAutoId()
}
init(Staaternietmeer: String) {
self.Staaternietmeer = Staaternietmeer
ref = Database.database().reference().child("Rollerbanken").childByAutoId()
}
init(TijdControle: String) {
self.TijdControle = TijdControle
ref = Database.database().reference().child("Rollerbanken").childByAutoId()
}
init(TijdControleniet: String) {
self.TijdControleniet = TijdControleniet
ref = Database.database().reference().child("Rollerbanken").childByAutoId()
}
init() {
ref = Database.database().reference().child("Rollerbanken").childByAutoId()
}
init(snapshot: DataSnapshot)
{
ref = snapshot.ref
if let value = snapshot.value as? [String : Any] {
TypeControle = value["TypeControle"] as! String
Stad = value["Stad"] as! String
Tijd = value["Tijd"] as! String
Latitude = value["Latitude"] as! String
Longitude = value["Longitude"] as! String
Extrainformatie = value["Extrainformatie"] as! String
Staater = value["Staater"] as! String
Staaternietmeer = value["Staaternietmeer"] as! String
TijdControle = value["TijdControle"] as! String
TijdControleniet = value["TijdControleniet"] as! String
}
}
func save() {
ref.setValue(toDictionary())
}
func toDictionary() -> [String : Any]
{
return [
"TypeControle" : TypeControle,
"Stad" : Stad,
"Tijd" : Tijd,
"Latitude" : Latitude,
"Longitude" : Longitude,
"Extrainformatie" : Extrainformatie,
"Staater" : Staater,
"Staaternietmeer" : Staaternietmeer,
"TijdControle" : TijdControle,
"TijdControleniet" : TijdControleniet
]
}
}
Data for the TableViewCell:
class ControleTableViewCell: UITableViewCell {
#IBOutlet weak var storyControle: UILabel!
#IBOutlet weak var storyTijd: UILabel!
var post: Post! {
didSet {
storyControle.text = "\(post.Staaternietmeer)"
storyTijd.text = "\(post.TijdControleniet)"
storyControle.text = "\(post.Staater)"
storyTijd.text = "\(post.TijdControle)"
}
}
How my update button looks like:
#IBAction func Update(_ sender: Any) {
let alertController1 = UIAlertController(title: "Update melden" , message: "De rollerbank", preferredStyle: .alert)
// Create the actions
let RollerbankAction1 = UIAlertAction(title: "Staat er nog steeds", style: UIAlertActionStyle.default) {
UIAlertAction in
NSLog("Ja Pressed")
self.newStory.Staater = self.Staater
self.newStory.TijdControle = self.TijdControle
self.newStory.save()
}
let cancelAction1 = UIAlertAction(title: "Staat er niet meer", style: UIAlertActionStyle.cancel) {
UIAlertAction in
NSLog("Cancel Pressed")
let date = Date()
let calendar = Calendar.current
let hour = calendar.component(.hour, from: date)
let minutes = calendar.component(.minute, from: date)
let Tijd = "\(hour) : \(minutes)"
self.newStory.Staaternietmeer = self.Staaternietmeer
self.newStory.TijdControleniet = Tijd
self.newStory.save()
}
alertController1.addAction(RollerbankAction1)
alertController1.addAction(cancelAction1)
self.present(alertController1, animated: true, completion: nil)
}
This is the Structure that i use. If i run all this code, the new data will go in a other childbyAutoID and thats not what i want. It just needs to update/setvalue in the cleare space named "Staaternietmeer" and "TijdControleniet". Can anybody help me with that?
You would then need to store the Push ID somewhere so that you can reuse it later.
To generate a unique Push ID you would use :
Database.database().reference().childByAutoId()
And to store it somewhere :
let postKey = Database.database().reference().childByAutoId().key
And then, say you need a method to share a post for example, and want to add this post to multiple nodes, that's how it may look like :
func sharePost(_ postContent: String, completion: #escaping (Bool) -> ()) {
guard let currentUserId = Auth.auth().currentUser?.uid else {
completion(false)
return
}
let postKey = Database.database().reference().childByAutoId().key
let postData: [String: Any] = [ "content": "blabla",
"author": currentUserId ]
let childUpdates: [String: Any] = ["users/\(currentUserId)/posts/\(postKey)": true,
"posts/\(postKey)": postData ]
Database.database().reference().updateChildValues(childUpdates, withCompletionBlock: { (error, ref) in
guard error == nil else {
completion(false)
return
}
completion(true)
})
}
Now to access the unique Push ID later on, you would use :
Database.database().reference().observe(.childAdded, with: { (snapshot) in
// Here you get the Push ID back :
let postKey = snapshot.key
// And others things that you need :
guard let author = snapshot.childSnapshot(forPath: "author").value as? String else { return }
guard let content = snapshot.childSnapshot(forPath: "content").value as? String else { return }
// Here you store your object (Post for example) in an array, and as you can see you initialize your object using the data you got from the snapshot, including the Push ID (`postKey`) :
posts.append(Post(id: postKey, content: content, author: author))
})
I am having a hard time trying to figure out, how I can change/update a specific part of my firebase database through swift. To give you an example of how my firebase database is structured, here you have a photo:
I am trying to update the likesForPost +1 everytime someone hits the like button that I have in my tableViewController. The important part is that every likesForPost should not be updates, just the one where the button is. I hope you understand my situation and that you can help me :-)
My struct
struct Sweet {
let key: String!
let content: String!
let addedByUser: String!
let profilePhoto: String!
var likesForPost: String!
let itemRef: FIRDatabaseReference?
init (content: String, addedByUser: String, profilePhoto: String!, likesForPost: String!, key: String = "") {
self.key = key
self.content = content
self.addedByUser = addedByUser
self.profilePhoto = profilePhoto
self.likesForPost = likesForPost
self.itemRef = nil
}
init (snapshot: FIRDataSnapshot) {
key = snapshot.key
itemRef = snapshot.ref
if let theFeedContent = snapshot.value!["content"] as? String {
content = theFeedContent
} else {
content = ""
}
if let feedUser = snapshot.value!["addedByUser"] as? String {
addedByUser = feedUser
} else {
addedByUser = ""
}
if let feedPhoto = snapshot.value!["profilePhoto"] as? String! {
profilePhoto = feedPhoto
} else {
profilePhoto = ""
}
if let feedLikes = snapshot.value!["likesForPost"] as? String! {
likesForPost = feedLikes
} else {
likesForPost = "0"
}
}
func toAnyObject() -> AnyObject {
return ["content":content, "addedByUser":addedByUser, "profilePhoto":profilePhoto!, "likesForPost":likesForPost]
}
}
My UITableViewController
import UIKit
import FirebaseDatabase
import FirebaseAuth
import FBSDKCoreKit
class feedTableViewController: UITableViewController {
#IBOutlet weak var loadingSpinner: UIActivityIndicatorView!
var facebookProfileUrl = ""
var dbRef: FIRDatabaseReference!
var updates = [Sweet]()
override func viewDidLoad() {
super.viewDidLoad()
loadingSpinner.startAnimating()
dbRef = FIRDatabase.database().reference().child("feed-items")
startObersvingDB()
}
func startObersvingDB() {
dbRef.observeEventType(.Value, withBlock: { (snapshot: FIRDataSnapshot) in
var newUpdates = [Sweet]()
for update in snapshot.children {
let updateObject = Sweet(snapshot: update as! FIRDataSnapshot)
newUpdates.append(updateObject)
}
self.updates = newUpdates
self.tableView.reloadData()
}) { (error: NSError) in
print(error.description)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func addToFeed(sender: AnyObject) {
let feedAlert = UIAlertController(title: "New update", message: "Enter your update", preferredStyle: .Alert)
feedAlert.addTextFieldWithConfigurationHandler { (textField:UITextField) in
textField.placeholder = "Your update"
}
feedAlert.addAction(UIAlertAction(title: "Send", style: .Default, handler: { (action:UIAlertAction) in
if let feedContent = feedAlert.textFields?.first?.text {
if let user = FIRAuth.auth()?.currentUser {
let name = user.displayName
//let photoUrl = user.photoURL
let accessToken = FBSDKAccessToken.currentAccessToken()
if(accessToken != nil) //should be != nil
{
let req = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"id"], tokenString: accessToken.tokenString, version: nil, HTTPMethod: "GET")
req.startWithCompletionHandler({ (connection, result, error : NSError!) -> Void in
if(error == nil)
{
let userId: String! = result.valueForKey("id") as? String!
let userID = userId
self.facebookProfileUrl = "http://graph.facebook.com/\(userID)/picture?type=large"
let likes = "0"
let feed = Sweet(content: feedContent, addedByUser: name!, profilePhoto: self.facebookProfileUrl, likesForPost: likes)
let feedRef = self.dbRef.child(feedContent.lowercaseString)
feedRef.setValue(feed.toAnyObject())
}
else
{
print("error \(error)")
}
})
}
// LAV FEEDCONTENT OM TIL OGSÅ AT MODTAGE PROFIL BILLEDE URL I STRING OG GIV SÅ facebookProfileUrl STRING LIGE HERUNDER I feed
} else {
// No user is signed in.
}
}
}))
self.presentViewController(feedAlert, animated: true, completion: nil)
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return updates.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:updateTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! updateTableViewCell
let update = updates[indexPath.row]
//cell.textLabel?.text = update.content
//cell.detailTextLabel?.text = update.addedByUser
cell.nameLabel.text = update.addedByUser
cell.updateLabel.text = update.content
cell.likesLabel.text = "\(update.likesForPost) hi-fives"
if update.profilePhoto! != "" {
if let url = NSURL(string: update.profilePhoto!) {
if let data = NSData(contentsOfURL: url) {
cell.picView.image = UIImage(data: data)
cell.picView.layer.cornerRadius = cell.picView.frame.size.width/2
cell.picView.clipsToBounds = true
}
}
} else {
print("Empty facebookProfileUrl")
}
loadingSpinner.stopAnimating()
return cell
}
}
Modify your struct to include one more variable (lets say let path : String!)that will include the value of the node key retrieved from your DB(megaTest or test).
Your Struct
struct Sweet {
let key: String!
let content: String!
let addedByUser: String!
let profilePhoto: String!
var likesForPost: String!
let itemRef: FIRDatabaseReference?
let path : String!
init (content: String, addedByUser: String, profilePhoto: String!, likesForPost: String!, key: String = "",dataPath : String!) {
self.key = key
self.content = content
self.addedByUser = addedByUser
self.profilePhoto = profilePhoto
self.likesForPost = likesForPost
self.itemRef = nil
self.path = dataPath
}
init (snapshot: FIRDataSnapshot) {
key = snapshot.key
itemRef = snapshot.ref
path = key
if let theFeedContent = snapshot.value!["content"] as? String {
content = theFeedContent
} else {
content = ""
}
if let feedUser = snapshot.value!["addedByUser"] as? String {
addedByUser = feedUser
} else {
addedByUser = ""
}
if let feedPhoto = snapshot.value!["profilePhoto"] as? String! {
profilePhoto = feedPhoto
} else {
profilePhoto = ""
}
if let feedLikes = snapshot.value!["likesForPost"] as? String! {
likesForPost = feedLikes
} else {
likesForPost = "0"
}
}
func toAnyObject() -> AnyObject {
return ["content":content, "addedByUser":addedByUser, "profilePhoto":profilePhoto!, "likesForPost":likesForPost,"pathInTheDB" : path]
}
}
In cellForIndexPath just add this
cell. pathDB = self.structArray![indexPath.row].path
Modify your customCell class like this
class customTableViewCell : UITableViewCell{
var pathDB : String! //megaTest or test
#IBAction func likeBtn(sender : UIButton!){
//Update like's
}
}
For updating the value you can use either runTransactionBlock:-
FIRDatabase.database().reference().child(pathDB).child("likesForPost").runTransactionBlock({ (likes: FIRMutableData) -> FIRTransactionResult in
// Set value and report transaction success
likes.value = likes.value as! Int + 1
return FIRTransactionResult.successWithValue(likes)
}) { (err, bl, snap) in
if let error = error {
print(error.localizedDescription)
}
}
Or observe that node with .observeSingleEventOfType, retrieve the snap and then update
let parentRef = FIRDatabase.database().reference().child(pathDB).child("likesForPost")
parentRef.observeSingleEventOfType(.Value,withBlock : {(snap) in
if let nOfLikes = snap.value as? Int{
parentRef.setValue(nOfLikes+1)
}
})