assertion failed: self.form property MUST be assigned - swift

I am using this library for Swift forms: https://github.com/ortuman/SwiftForms This is very similar to Eureka.
Here's an explanation of what I am trying to do:
I have 2 Pickers in my form. Picker1 is just a normal picker while Picker2 depends on the value of Picker1. So when the user changes the value of Picker1. Options in Picker2 should be changed also. To do this, here's my function:
func change_data(){
row4.configuration[FormRowDescriptor.Configuration.Options] = ["hello", "from", "the"]
row4.value = "hello"
self.tableView.reloadData()
}
I use the reloadData() to see the changes in the values of my 2 pickers. But unfortunately, I get the error: assertion failed: self.form property MUST be assigned!
I tried putting that code in the action of a button in top bar and it works.
func submit(_: UIBarButtonItem!) {
//let message = self.form.formValues().description
//let alert: UIAlertView = UIAlertView(title: "Form output", message: message, delegate: nil, cancelButtonTitle: "OK")
//alert.show()
row4.configuration[FormRowDescriptor.Configuration.Options] = ["hello", "from", "the"]
row4.value = "hello"
self.tableView.reloadData()
}
But I need to call the reloadData() inside my function and not in button click.
Here's the viewDidLoad of my FormViewController:
public override func viewDidLoad() {
super.viewDidLoad()
assert(form != nil, "self.form property MUST be assigned!")
navigationItem.title = form.title
}
What I am trying to accomplish is this:
I have several pickers, and the last picker will depend on the chosen items from 2nd and 3rd. I call those functions to update the content of my last picker.
Here's my FormViewController class:
import UIKit
import CoreData
import SwiftForms
class ExampleFormViewController: FormViewController {
struct Static {
static let nameTag = "name"
static let passwordTag = "password"
static let lastNameTag = "lastName"
static let jobTag = "job"
static let emailTag = "email"
static let URLTag = "url"
static let phoneTag = "phone"
static let enabled = "enabled"
static let check = "check"
static let segmented = "segmented"
static let picker = "picker"
static let birthday = "birthday"
static let categories = "categories"
static let button = "button"
static let stepper = "stepper"
static let slider = "slider"
static let textView = "textview"
}
var val_territory = [Int]()
var val_company = [Int]()
var val_facility = [Int]()
var val_specialty = [Int]()
var putu_company = ""
var putu_territory = ""
var putu_facility = ""
var str_territory = [String]()
var str_company = [String]()
var str_facility = [String]()
var str_specialty = [String]()
var territory: [Territory] = []
var company: [Company] = []
var facility: [Facility] = []
var specialty: [Specialty] = []
var row1 = FormRowDescriptor(tag: Static.picker, rowType: .Picker, title: "Territory")
var row2 = FormRowDescriptor(tag: Static.picker, rowType: .Picker, title: "Company")
var row3 = FormRowDescriptor(tag: Static.picker, rowType: .Picker, title: "Facility")
var row4 = FormRowDescriptor(tag: Static.picker, rowType: .Picker, title: "Specialty")
let name: String
var form2 = FormDescriptor(title: "Create Shift Entry")
init(_ coder: NSCoder? = nil) {
name = "Bar"
if let coder = coder {
super.init(coder: coder)
} else {
super.init(nibName: nil, bundle:nil)
}
}
required convenience init(coder: NSCoder) {
self.init(coder)
load_data()
self.loadForm()
}
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Save", style: .Plain, target: self, action: "submit:")
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: "cancel:")
}
// MARK: Actions
func submit(_: UIBarButtonItem!) {
//let message = self.form.formValues().description
//let alert: UIAlertView = UIAlertView(title: "Form output", message: message, delegate: nil, cancelButtonTitle: "OK")
//alert.show()
row4.configuration[FormRowDescriptor.Configuration.Options] = ["hello", "from", "the"]
row4.value = "hello"
self.tableView.reloadData()
}
func cancel(_: UIBarButtonItem!) {
self.performSegueWithIdentifier("goto_main2", sender: self)
}
private func loadForm() {
let form = FormDescriptor(title: "Create Shift Entry")
let section1 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)
row1.configuration[FormRowDescriptor.Configuration.Options] = str_territory
row1.value = str_territory[0]
section1.addRow(row1)
row2.configuration[FormRowDescriptor.Configuration.Options] = str_company
row2.value = str_company[0]
section1.addRow(row2)
row3.configuration[FormRowDescriptor.Configuration.Options] = str_facility
row3.value = str_facility[0]
section1.addRow(row3)
row4.configuration[FormRowDescriptor.Configuration.Options] = str_specialty
row4.value = str_specialty[0]
section1.addRow(row4)
let section2 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)
var row = FormRowDescriptor(tag: Static.phoneTag, rowType: .Phone, title: "Scheduled Hours")
row.configuration[FormRowDescriptor.Configuration.CellConfiguration] = ["textField.placeholder" : "e.g. 8", "textField.textAlignment" : NSTextAlignment.Right.rawValue]
section2.addRow(row)
let section3 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)
row = FormRowDescriptor(tag: Static.birthday, rowType: .DateAndTime, title: "Time In")
section3.addRow(row)
row = FormRowDescriptor(tag: Static.birthday, rowType: .DateAndTime, title: "Time Out")
section3.addRow(row)
let section4 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)
row = FormRowDescriptor(tag: Static.enabled, rowType: .BooleanSwitch, title: "Missed Lunch")
section4.addRow(row)
let section5 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)
row = FormRowDescriptor(tag: Static.textView, rowType: .MultilineText, title: "Notes")
section5.addRow(row)
let section8 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)
row = FormRowDescriptor(tag: Static.button, rowType: .Button, title: "Add Staff Signature")
row.configuration[FormRowDescriptor.Configuration.DidSelectClosure] = {
self.view.endEditing(true)
} as DidSelectClosure
section8.addRow(row)
let section9 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)
row = FormRowDescriptor(tag: Static.button, rowType: .Button, title: "Add Supervisor Signature")
row.configuration[FormRowDescriptor.Configuration.DidSelectClosure] = {
self.view.endEditing(true)
} as DidSelectClosure
section9.addRow(row)
form.sections = [section1, section2, section3, section4, section5, section8, section9]
self.form = form
form2 = form
}
func load_data(){
let sortDescriptor = NSSortDescriptor(key: "orig_id", ascending: true)
let sortDescriptors = [sortDescriptor]
let facilityPredicate = NSPredicate(format: "facility = %#", NSNumber(integer: 1))
var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext
let fetchRequest = NSFetchRequest(entityName:"Company")
fetchRequest.sortDescriptors = sortDescriptors
let fetchRequestTerritory = NSFetchRequest(entityName:"Territory")
fetchRequestTerritory.sortDescriptors = sortDescriptors
let fetchRequestFacility = NSFetchRequest(entityName:"Facility")
fetchRequestFacility.sortDescriptors = sortDescriptors
let fetchRequestSpecialty = NSFetchRequest(entityName:"Specialty")
fetchRequestSpecialty.sortDescriptors = sortDescriptors
fetchRequestSpecialty.predicate = facilityPredicate
let error:NSError
do {
let company_temp = try context.executeFetchRequest(fetchRequest)
company = company_temp as! [Company]
for t in company {
val_company.append(t.orig_id! as Int)
str_company.append(t.name! as String)
}
print(company.count)
let territory_temp = try context.executeFetchRequest(fetchRequestTerritory)
territory = territory_temp as! [Territory]
for t in territory {
val_territory.append(Int(t.orig_id!)!)
str_territory.append(t.name! as String)
}
print(territory_temp.count)
let facility_temp = try context.executeFetchRequest(fetchRequestFacility)
facility = facility_temp as! [Facility]
for t in facility {
val_facility.append(Int(t.orig_id!)!)
str_facility.append(t.name! as String)
}
print(facility_temp.count)
let specialty_temp = try context.executeFetchRequest(fetchRequestSpecialty)
specialty = specialty_temp as! [Specialty]
for t in specialty {
val_specialty.append(Int(t.orig_id!)!)
str_specialty.append(t.name! as String)
}
print(specialty_temp.count)
} catch let error as NSError {
// failure
print("Fetch failed: \(error.localizedDescription)")
}
}
func get_facility_ter(company: Int!){
//print("company: " + company)
//print("territory: " + territory!)
var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext
let sortDescriptor = NSSortDescriptor(key: "orig_id", ascending: true)
let sortDescriptors = [sortDescriptor]
let fetchRequest = NSFetchRequest(entityName:"Territory")
fetchRequest.sortDescriptors = sortDescriptors
do {
let territory_temp = try context.executeFetchRequest(fetchRequest)
var territory2 = territory_temp as! [Territory]
for t in territory2 {
val_territory.append(Int(t.orig_id!)!)
str_territory.append(t.name! as String)
}
} catch let error as NSError {
// failure
print("Fetch failed: \(error.localizedDescription)")
}
if let company2 = company{
let companyPredicate = NSPredicate(format: "company = %#", NSNumber(integer: val_territory[str_territory.indexOf(putu_territory)!]))
let territoryPredicate = NSPredicate(format: "territory = %#", NSNumber(integer: val_territory[company]))
let predicate = NSCompoundPredicate(type: NSCompoundPredicateType.OrPredicateType, subpredicates: [companyPredicate, territoryPredicate])
let fetchRequestFacility = NSFetchRequest(entityName:"Facility")
fetchRequestFacility.predicate = predicate
print(companyPredicate)
do {
let facility_temp = try context.executeFetchRequest(fetchRequestFacility)
facility = facility_temp as! [Facility]
str_facility.removeAll()
val_facility.removeAll()
for t in facility {
val_facility.append(Int(t.orig_id!)!)
str_facility.append(t.name! as String)
}
row3.configuration[FormRowDescriptor.Configuration.Options] = str_facility
} catch let error as NSError {
// failure
print("Fetch failed: \(error.localizedDescription)")
}
}
}
func get_facility_com(company: Int!){
//print("company: " + company)
//print("territory: " + territory!)
var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext
let sortDescriptor = NSSortDescriptor(key: "orig_id", ascending: true)
let sortDescriptors = [sortDescriptor]
let fetchRequest = NSFetchRequest(entityName:"Company")
fetchRequest.sortDescriptors = sortDescriptors
do {
let company_temp = try context.executeFetchRequest(fetchRequest)
var company2 = company_temp as! [Company]
for t in company2 {
val_company.append(t.orig_id! as Int)
str_company.append(t.name! as String)
}
} catch let error as NSError {
// failure
print("Fetch failed: \(error.localizedDescription)")
}
print(val_company.count)
print(str_company.count)
print(putu_company)
print(str_company)
print(str_company.contains(putu_company))
if let company2 = company{
let companyPredicate = NSPredicate(format: "company = %#", NSNumber(integer: val_company[company]))
let territoryPredicate = NSPredicate(format: "territory = %#", NSNumber(integer: val_company[str_company.indexOf(putu_company)!]))
let predicate = NSCompoundPredicate(type: NSCompoundPredicateType.OrPredicateType, subpredicates: [companyPredicate, territoryPredicate])
let fetchRequestFacility = NSFetchRequest(entityName:"Facility")
fetchRequestFacility.predicate = predicate
print(companyPredicate)
do {
let facility_temp = try context.executeFetchRequest(fetchRequestFacility)
facility = facility_temp as! [Facility]
str_facility.removeAll()
val_facility.removeAll()
for t in facility {
val_facility.append(Int(t.orig_id!)!)
str_facility.append(t.name! as String)
}
row3.configuration[FormRowDescriptor.Configuration.Options] = str_facility
} catch let error as NSError {
// failure
print("Fetch failed: \(error.localizedDescription)")
}
}
}
func get_specialty(facility_txt: Int!){
print("VALUE OF FACILITY: " + String(facility_txt))
var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext
let sortDescriptor = NSSortDescriptor(key: "orig_id", ascending: true)
let sortDescriptors = [sortDescriptor]
let facilityPredicate = NSPredicate(format: "facility = %#", NSNumber(integer: val_facility[str_facility.indexOf(putu_facility)!]))
let fetchRequestSpecialty = NSFetchRequest(entityName:"Specialty")
fetchRequestSpecialty.sortDescriptors = sortDescriptors
fetchRequestSpecialty.predicate = facilityPredicate
do {
let specialty_temp = try context.executeFetchRequest(fetchRequestSpecialty)
specialty = specialty_temp as! [Specialty]
str_specialty.removeAll()
val_specialty.removeAll()
for t in specialty {
val_specialty.append(Int(t.orig_id!)!)
str_specialty.append(t.name! as String)
}
print(str_specialty)
self.form = form2
row4.configuration[FormRowDescriptor.Configuration.Options] = str_specialty
row4.value = "hello"
self.tableView.reloadData()
} catch let error as NSError {
// failure
print("Fetch failed: \(error.localizedDescription)")
}
}
func put_company(putu: String!, row: Int!){
print("haler")
putu_company = putu
print(putu_company)
print(row)
get_facility_com(row)
}
func put_territory(putu: String!, row: Int!){
print("haler")
putu_territory = putu
print(putu_territory)
print(row)
get_facility_ter(row)
}
func put_facility(putu: String!, row: Int!){
print("haler")
putu_facility = putu
print(putu_facility)
print(row)
var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext
let sortDescriptor = NSSortDescriptor(key: "orig_id", ascending: true)
let sortDescriptors = [sortDescriptor]
let fetchRequestFacility = NSFetchRequest(entityName:"Facility")
fetchRequestFacility.sortDescriptors = sortDescriptors
do {
let facility_temp = try context.executeFetchRequest(fetchRequestFacility)
facility = facility_temp as! [Facility]
for t in facility {
val_facility.append(Int(t.orig_id!)!)
str_facility.append(t.name! as String)
}
} catch let error as NSError {
// failure
print("Fetch failed: \(error.localizedDescription)")
}
print(val_facility)
get_specialty(val_facility[row])
}
}
I call those functions here:
import UIKit
public class FormPickerCell: FormValueCell, UIPickerViewDelegate, UIPickerViewDataSource {
// MARK: Properties
private let picker = UIPickerView()
private let hiddenTextField = UITextField(frame: CGRectZero)
struct MyVariables {
static var mv_territory = 0
static var mv_company = 0
static var mv_facility = 0
static var mv_specialty = 0
}
// MARK: FormBaseCell
public override func configure() {
super.configure()
accessoryType = .None
picker.delegate = self
picker.dataSource = self
hiddenTextField.inputView = picker
contentView.addSubview(hiddenTextField)
}
public override func update() {
super.update()
titleLabel.text = rowDescriptor.title
if let value = rowDescriptor.value {
valueLabel.text = rowDescriptor.titleForOptionValue(value)
if let options = rowDescriptor.configuration[FormRowDescriptor.Configuration.Options] as? NSArray {
let index = options.indexOfObject(value)
if index != NSNotFound {
picker.selectRow(index, inComponent: 0, animated: false)
}
}
}
}
public override class func formViewController(formViewController: FormViewController, didSelectRow selectedRow: FormBaseCell) {
if selectedRow.rowDescriptor.value == nil {
if let row = selectedRow as? FormPickerCell {
let options = selectedRow.rowDescriptor.configuration[FormRowDescriptor.Configuration.Options] as? NSArray
let optionValue = options?[0] as? NSObject
selectedRow.rowDescriptor.value = optionValue
row.valueLabel.text = selectedRow.rowDescriptor.titleForOptionValue(optionValue!)
row.hiddenTextField.becomeFirstResponder()
}
} else {
if let row = selectedRow as? FormPickerCell {
guard let optionValue = selectedRow.rowDescriptor.value else { return }
row.valueLabel.text = selectedRow.rowDescriptor.titleForOptionValue(optionValue)
row.hiddenTextField.becomeFirstResponder()
}
}
}
// MARK: UIPickerViewDelegate
public func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return rowDescriptor.titleForOptionAtIndex(row)
}
public func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let options = rowDescriptor.configuration[FormRowDescriptor.Configuration.Options] as? NSArray
let optionValue = options?[row] as? NSObject
rowDescriptor.value = optionValue
valueLabel.text = rowDescriptor.titleForOptionValue(optionValue!)
if(rowDescriptor.title == "Company"){
print("company")
print(valueLabel.text)
ExampleFormViewController().put_company(valueLabel.text, row: row)
}else if(rowDescriptor.title == "Territory"){
print("territory")
print(valueLabel.text)
ExampleFormViewController().put_territory(valueLabel.text, row: row)
}
else if(rowDescriptor.title == "Facility"){
print("facility")
print(valueLabel.text)
ExampleFormViewController().put_facility(valueLabel.text, row: row)
}
}
// MARK: UIPickerViewDataSource
public func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if let options = rowDescriptor.configuration[FormRowDescriptor.Configuration.Options] as? NSArray {
return options.count
}
return 0
}
}
I do that to put new values to my picker whenever the selected item in other pickers change.

I believe the error is in FormPickerCell in pickerView:didSelectRow:inComponent: method:
ExampleFormViewController().put_territory(valueLabel.text, row: row)
In this line you are creating a new instance of ExampleFormViewController. And I assume you want to call this function on your existing controller instance.
The easiest (and the wrongest) solution would be to use FormBaseCell. formViewController property:
public func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let options = rowDescriptor.configuration[FormRowDescriptor.Configuration.Options] as? NSArray
let optionValue = options?[row] as? NSObject
rowDescriptor.value = optionValue
valueLabel.text = rowDescriptor.titleForOptionValue(optionValue!)
let controller = formViewController as! ExampleFormViewController
if(rowDescriptor.title == "Company"){
controller.put_company(valueLabel.text, row: row)
} else if(rowDescriptor.title == "Territory"){
controller.put_territory(valueLabel.text, row: row)
} else if(rowDescriptor.title == "Facility"){
controller.put_facility(valueLabel.text, row: row)
}
}
But correct solution for SwiftForm would be to use standard FormPickerCell (don't override it with custom logic just for one controller!) and use row.configuration[FormRowDescriptor.Configuration.DidUpdateClosure]:
private func loadForm() {
let form = FormDescriptor(title: "Create Shift Entry")
let section1 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)
row1.configuration[FormRowDescriptor.Configuration.Options] = str_territory
row1.value = str_territory[0]
row1.configuration[FormRowDescriptor.Configuration.DidUpdateClosure] = { [weak self] rowDescriptor in
guard let value = rowDescriptor.value else { return }
guard let options = rowDescriptor.configuration[FormRowDescriptor.Configuration.Options] as? NSArray else { return }
let index = options.indexOfObject(value)
self?.put_territory(rowDescriptor.titleForOptionValue(value), row: index)
}
section1.addRow(row1)
/// add corresponding DidUpdateClosure for row2 and row3
/// ...
}

Related

Why is my alert controller not dismissing in my Swift app?

I have a custom view controller class which presents an alert controller when it receives a not connected notification from my network services class. I want to dismiss the alert controller when I receive a further connected notification from the network services class but I am unable to dismiss the presenting alert.
Here is my custom view controller class;
class CompanyPriceListVC: UITableViewController {
// MARK: - Properties
let companyStockSymbols = ["AAPL","AMZN", "MSFT", "GOOGL", "TSLA", "META","COINBASE:BTC", "BINANCE:BTCUSDT", "BINANCE:BNBBTC", "IC MARKETS:1", "IC MARKETS:2"]
let defaultStockInfo = StockInfo(tradeConditions: nil, price: 0.00, symbol: "-", timestamp: 0.0, volume: 0.0)
lazy var companyStockInfo = [StockInfo](repeating: defaultStockInfo, count: companyStockSymbols.count)
var companyDetailsVC:CompanyDetailsVC?
var tableRowSelected: Int?
let defaultPriceHistory = PriceHistory(previous: nil, relative: 0.0, absolute: 0.0)
lazy var priceHistory = [PriceHistory](repeating: defaultPriceHistory , count: companyStockSymbols.count)
var deviceOrientation: Orientation = .portrait
let activityIndicator: UIActivityIndicatorView = {
let activityIndicator = UIActivityIndicatorView()
activityIndicator.style = .large
activityIndicator.hidesWhenStopped = true
activityIndicator.color = .white
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
activityIndicator.startAnimating()
return activityIndicator
}()
let isConnected = Notification.Name(rawValue: isConnectedNotificationKey)
let isNotConnected = Notification.Name(rawValue: isDisconnectedNotificationKey)
let alertController = UIAlertController(title: "Connectivity Error", message: "Network connection lost. Please check your WiFi settings, mobile data settings or reception coverage.", preferredStyle: .alert)
// MARK: - Lifecycle Methods
override func viewDidLoad() {
super.viewDidLoad()
if UIDevice.current.orientation.isPortrait {
self.deviceOrientation = .portrait
self.tableView.register(CompanyStockCellPortrait.self, forCellReuseIdentifier: "CompanyStockCellPortrait")
} else {
self.deviceOrientation = .landscape
self.tableView.register(CompanyStockCellLandscape.self, forCellReuseIdentifier: "CompanyStockCellLandscape")
}
configureNavigationBar()
view.backgroundColor = .black
configureTableView()
configureConstraints()
createObservers()
}
deinit {
NotificationCenter.default.removeObserver(self)
}
private func createObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(CompanyPriceListVC.dismissAndFetchStockInfo), name: isConnected, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(CompanyPriceListVC.notifyUserOnScreen(notification:)), name: isNotConnected, object: nil)
}
#objc private func fetchStockInfo() {
NetworkServices.sharedInstance.fetchStockInfo(symbols: companyStockSymbols, delegate: self)
}
#objc private func notifyUserOnScreen(notification: NSNotification) {
self.present(alertController, animated: true)
}
#objc public func dismissAndFetchStockInfo() {
print("DEBUG: isBeingPresented: \(alertController.isBeingPresented)")
if alertController.isBeingPresented {
self.alertController.dismiss(animated: true, completion: nil)
}
fetchStockInfo()
}
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
super.willTransition(to: newCollection, with: coordinator)
coordinator.animate(alongsideTransition: { (context) in
guard let windowInterfaceOrientation = self.windowInterfaceOrientation else { return }
if windowInterfaceOrientation.isPortrait {
self.deviceOrientation = .portrait
self.tableView.register(CompanyStockCellPortrait.self, forCellReuseIdentifier: "CompanyStockCellPortrait")
self.tableView.reloadData()
} else {
self.deviceOrientation = .landscape
self.tableView.register(CompanyStockCellLandscape.self, forCellReuseIdentifier: "CompanyStockCellLandscape")
self.tableView.reloadData()
}
})
}
private var windowInterfaceOrientation: UIInterfaceOrientation? {
return self.view.window?.windowScene?.interfaceOrientation
}
// MARK: - TableView Data Source Methods
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return companyStockInfo.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch deviceOrientation {
case .portrait:
let tableViewCellPortrait = tableView.dequeueReusableCell(withIdentifier: "CompanyStockCellPortrait", for: indexPath) as! CompanyStockCellPortrait
tableViewCellPortrait.symbolValue.text = companyStockInfo[indexPath.row].symbol
var latestPrice = companyStockInfo[indexPath.row].price
latestPrice = round(latestPrice * 100.0) / 100.00
tableViewCellPortrait.priceValue.text = String(format: "%.2f", arguments:[latestPrice])
if let _ = priceHistory[indexPath.row].previous {
let absoluteDifference = priceHistory[indexPath.row].absolute
let relativeDifference = priceHistory[indexPath.row].relative
if absoluteDifference > 0.0 {
tableViewCellPortrait.priceDirectionImageView.image = UIImage(systemName: "arrowtriangle.up.fill")
tableViewCellPortrait.priceDirectionImageView.tintColor = .systemGreen
tableViewCellPortrait.relativePriceDiffValue.text = String(format: "%.2f%%", arguments: [relativeDifference])
tableViewCellPortrait.relativePriceDiffValue.textColor = .systemGreen
tableViewCellPortrait.absolutePriceDiffValue.text = String(format: "(%.2f)", arguments: [absoluteDifference])
tableViewCellPortrait.absolutePriceDiffValue.textColor = .systemGreen
} else if absoluteDifference < 0.0 {
tableViewCellPortrait.priceDirectionImageView.image = UIImage(systemName: "arrowtriangle.down.fill")
tableViewCellPortrait.priceDirectionImageView.tintColor = .systemRed
tableViewCellPortrait.relativePriceDiffValue.text = String(format: "%.2f%%", arguments: [relativeDifference])
tableViewCellPortrait.relativePriceDiffValue.textColor = .systemRed
tableViewCellPortrait.absolutePriceDiffValue.text = String(format: "(%.2f)", arguments: [absoluteDifference])
tableViewCellPortrait.absolutePriceDiffValue.textColor = .systemRed
} else {
tableViewCellPortrait.priceDirectionImageView.image = UIImage(systemName: "diamond.fill")
tableViewCellPortrait.priceDirectionImageView.tintColor = .white
tableViewCellPortrait.relativePriceDiffValue.text = "0.00%"
tableViewCellPortrait.relativePriceDiffValue.textColor = .white
tableViewCellPortrait.absolutePriceDiffValue.text = "(0.00)"
tableViewCellPortrait.absolutePriceDiffValue.textColor = .white
}
} else {
tableViewCellPortrait.priceDirectionImageView.image = UIImage()
tableViewCellPortrait.priceDirectionImageView.tintColor = .white
tableViewCellPortrait.relativePriceDiffValue.text = ""
tableViewCellPortrait.absolutePriceDiffValue.text = ""
}
return tableViewCellPortrait
case .landscape:
let tableViewCellLandscape = tableView.dequeueReusableCell(withIdentifier: "CompanyStockCellLandscape", for: indexPath) as! CompanyStockCellLandscape
tableViewCellLandscape.symbolValue.text = companyStockInfo[indexPath.row].symbol
var latestPrice = companyStockInfo[indexPath.row].price
latestPrice = round(latestPrice * 100.0) / 100.00
tableViewCellLandscape.priceValue.text = String(format: "%.2f", arguments:[latestPrice])
if let _ = priceHistory[indexPath.row].previous {
let absoluteDifference = priceHistory[indexPath.row].absolute
let relativeDifference = priceHistory[indexPath.row].relative
if absoluteDifference > 0.0 {
tableViewCellLandscape.priceDirectionImageView.image = UIImage(systemName: "arrowtriangle.up.fill")
tableViewCellLandscape.priceDirectionImageView.tintColor = .systemGreen
tableViewCellLandscape.relativePriceDiffValue.text = String(format: "%.2f%%", arguments: [relativeDifference])
tableViewCellLandscape.relativePriceDiffValue.textColor = .systemGreen
tableViewCellLandscape.absolutePriceDiffValue.text = String(format: "(%.2f)", arguments: [absoluteDifference])
tableViewCellLandscape.absolutePriceDiffValue.textColor = .systemGreen
} else if absoluteDifference < 0.0 {
tableViewCellLandscape.priceDirectionImageView.image = UIImage(systemName: "arrowtriangle.down.fill")
tableViewCellLandscape.priceDirectionImageView.tintColor = .systemRed
tableViewCellLandscape.relativePriceDiffValue.text = String(format: "%.2f%%", arguments: [relativeDifference])
tableViewCellLandscape.relativePriceDiffValue.textColor = .systemRed
tableViewCellLandscape.absolutePriceDiffValue.text = String(format: "(%.2f)", arguments: [absoluteDifference])
tableViewCellLandscape.absolutePriceDiffValue.textColor = .systemRed
} else {
tableViewCellLandscape.priceDirectionImageView.image = UIImage(systemName: "diamond.fill")
tableViewCellLandscape.priceDirectionImageView.tintColor = .white
tableViewCellLandscape.relativePriceDiffValue.text = "0.00%"
tableViewCellLandscape.relativePriceDiffValue.textColor = .white
tableViewCellLandscape.absolutePriceDiffValue.text = "(0.00)"
tableViewCellLandscape.absolutePriceDiffValue.textColor = .white
}
} else {
tableViewCellLandscape.priceDirectionImageView.image = UIImage()
tableViewCellLandscape.priceDirectionImageView.tintColor = .white
tableViewCellLandscape.relativePriceDiffValue.text = ""
tableViewCellLandscape.absolutePriceDiffValue.text = ""
}
return tableViewCellLandscape
}
}
// MARK: - TableView Delegate Methods
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100.0
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
companyDetailsVC = CompanyDetailsVC(companyStockInfo: companyStockInfo[indexPath.row])
tableRowSelected = indexPath.row
navigationController?.pushViewController(companyDetailsVC!, animated: true)
}
// MARK: - Helper Functions
private func configureNavigationBar() {
UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
navigationController?.navigationBar.topItem?.title = "Trade Tracker"
navigationController?.navigationBar.barStyle = .black
navigationController?.navigationBar.prefersLargeTitles = true
}
private func configureTableView() {
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .singleLine
tableView.separatorColor = .white
tableView.tableFooterView = UIView()
}
private func configureConstraints() {
tableView.addSubview(activityIndicator)
NSLayoutConstraint.activate([
activityIndicator.centerXAnchor.constraint(equalTo: tableView.centerXAnchor),
activityIndicator.topAnchor.constraint(equalTo: tableView.topAnchor, constant: 250)
])
tableView.layoutSubviews()
}
}
// MARK: - Network Service Delegate Method
extension CompanyPriceListVC: NetworkServicesDelegate {
func sendStockInfo(stocksInfo: [String : StockInfo]) {
DispatchQueue.main.async {
// Compute absolute and relative price differences
for (index, symbol) in self.companyStockSymbols.enumerated() {
if stocksInfo[symbol] != nil {
self.priceHistory[index].previous = self.companyStockInfo[index].price
self.companyStockInfo[index] = stocksInfo[symbol]!
var latestPrice = self.companyStockInfo[index].price
latestPrice = round(latestPrice * 100.0) / 100.00
if let previous = self.priceHistory[index].previous {
let previousPrice = round(previous * 100.0) / 100.0
var absoluteDifference = latestPrice - previousPrice
absoluteDifference = round(absoluteDifference * 100.0) / 100.0
self.priceHistory[index].absolute = absoluteDifference
var relativeDifference = 0.0
if previousPrice != 0.00 {
relativeDifference = (absoluteDifference / previousPrice) * 100.0
relativeDifference = round(relativeDifference * 100) / 100.0
}
self.priceHistory[index].relative = relativeDifference
}
}
}
self.tableView.reloadData()
self.activityIndicator.stopAnimating()
guard let rowSelected = self.tableRowSelected else { return }
self.companyDetailsVC!.companyStockInfo = self.companyStockInfo[rowSelected]
self.companyDetailsVC!.relativeDifference = self.priceHistory[rowSelected].relative
self.companyDetailsVC!.absoluteDifference = self.priceHistory[rowSelected].absolute
}
}
}
and here is my network services class;
import UIKit
import Starscream
import Network
protocol NetworkServicesDelegate: AnyObject {
func sendStockInfo(stocksInfo: [String: StockInfo])
}
final class NetworkServices {
static let sharedInstance = NetworkServices()
var request = URLRequest(url: FINNHUB_SOCKET_STOCK_INFO_URL!)
var socket: WebSocket!
public private(set) var isConnected = false
var stocksInfo: [String: StockInfo] = [:]
var socketResults: [String: [StockInfo]] = [:]
weak var delegate: NetworkServicesDelegate?
var stockSymbols: [String] = []
private init() {
request.timeoutInterval = 5
socket = WebSocket(request: request)
socket.delegate = self
}
private let queue = DispatchQueue.global()
private let monitor = NWPathMonitor()
public func startMonitoring() {
monitor.start(queue: queue)
self.monitor.pathUpdateHandler = { [weak self] path in
if path.status == .satisfied {
// connect the socket
self?.socket.connect()
} else {
// disconnect the socket
self?.socket.disconnect()
// post notification that socket is now disconnected
DispatchQueue.main.async {
let name = Notification.Name(rawValue: isDisconnectedNotificationKey)
NotificationCenter.default.post(name: name, object: nil)
}
}
}
}
public func stopMonitoring() {
monitor.cancel()
}
func fetchStockInfo(symbols: [String], delegate: CompanyPriceListVC) {
stockSymbols = symbols
self.delegate = delegate
for symbol in symbols {
let string = FINNHUB_SOCKET_MESSAGE_STRING + symbol + "\"}"
socket.write(string: string)
}
}
private func parseJSONSocketData(_ socketString: String) {
self.socketResults = [:]
self.stocksInfo = [:]
let decoder = JSONDecoder()
do {
let socketData = try decoder.decode(SocketData.self, from: socketString.data(using: .utf8)!)
guard let stockInfoData = socketData.data else { return }
for stockInfo in stockInfoData {
let symbol = stockInfo.symbol
if self.socketResults[symbol] == nil {
self.socketResults[symbol] = [StockInfo]()
}
self.socketResults[symbol]?.append(stockInfo)
}
for (symbol, stocks) in self.socketResults {
for item in stocks {
if self.stocksInfo[symbol] == nil {
self.stocksInfo[symbol] = item
} else if item.timestamp > self.stocksInfo[symbol]!.timestamp {
self.stocksInfo[symbol] = item
}
}
}
self.delegate?.sendStockInfo(stocksInfo: self.stocksInfo)
} catch {
print("DEBUG: error: \(error.localizedDescription)")
}
}
func fetchCompanyInfo(symbol: String, completion: #escaping (CompanyInfo?, UIImage?)->()) {
let urlString = FINNHUB_HTTP_COMPANY_INFO_URL_STRING + symbol + "&token=" + FINNHUB_API_TOKEN
guard let url = URL(string: urlString) else { return }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
print("Error fetching company info: \(error)")
}
guard let data = data else { return }
let decoder = JSONDecoder()
do {
let companyInfo = try decoder.decode(CompanyInfo.self, from: data)
guard let logoURL = URL(string: companyInfo.logo) else { return }
let task = URLSession.shared.dataTask(with: logoURL) { data, response, error in
if let error = error {
print("Error fetching logo image: \(error)")
}
guard let data = data else { return }
guard let logoImage = UIImage(data: data) else { return }
completion(companyInfo, logoImage)
}
task.resume()
} catch {
print("Error decoding JSON: \(error)")
completion(nil, nil)
}
}
task.resume()
}
}
extension NetworkServices: WebSocketDelegate {
func didReceive(event: WebSocketEvent, client: WebSocket) {
switch event {
case .connected(_):
self.isConnected = true
// post notification that socket is now connected
let name = Notification.Name(rawValue: isConnectedNotificationKey)
NotificationCenter.default.post(name: name, object: nil)
case .disconnected(let reason, let code):
print("DEBUG: Got disconnected.")
self.isConnected = false
case .cancelled:
print("DEBUG: cancelled.")
// post notification that socket is not connected
case .reconnectSuggested(let suggestReconnect):
print("DEBUG: suggestReconnect = \(suggestReconnect)")
// post notification that socket is not connected
case .viabilityChanged(let viabilityChanged):
print("DEBUG: viabilityChange = \(viabilityChanged)")
case .error(let error):
print("DEBUG error: \(String(describing: error?.localizedDescription))")
case .text(let socketString):
parseJSONSocketData(socketString)
default:
break
}
}
}
I've tried querying the isBeingPresented property of the alert controller but it always tests as false even though I can see the alert controller is being presented.
You could do a check if the currently presented UIViewController is actually the alertController like this:
#objc public func dismissAndFetchStockInfo() {
if presentedViewController == alertController {
alertController.dismiss(animated: true, completion: nil)
}
fetchStockInfo()
}
This is because isBeingPresented is only valid inside the view[Will|Did][Disa|A]ppear methods.

Cell of UITableView is not displayed at all

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()
}
}
}
}
}

firebase upload after checkout

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.

iOS Swift - Use predicate core data to filter a tableView

I'm trying to filter my NSFetchedResultsController object when I search in the tableView. I have tried with NSPredicate but I can't make it work.
I'm using Swift 3.
This is my code:
func filtrarContenido(searchText: String) {
let buscar = searchText.lowercased()
let nombrePredicate = NSPredicate(format: "nombre_comercial contains[cd] %#", buscar)
let razSocialPredicate = NSPredicate(format: "razon_social contains[cd] %#", buscar)
let predicate = NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.or, subpredicates: [nombrePredicate, razSocialPredicate])
let respuesta = self.funcCoreData.obtenerResultadosFiltrados(entidad: "Clientes", orden: "nombre_comercial", ascendente: true, predicate: predicate)
self.resultadosFiltrados = respuesta[1] as! NSFetchedResultsController<NSManagedObject>
do {
try self.resultadosFiltrados.performFetch()
} catch {
print("👋 \(error)")
}
}
And here is the function in FuncCoreData file, it returns an array with the NSManagedObject and NSFetchedResultsController:
func obtenerResultadosFiltrados(entidad: String, orden: String, ascendente: Bool, predicate: NSPredicate) -> [AnyObject] {
let appDelegate = UIApplication.shared.delegate as? AppDelegate
let context = appDelegate?.persistentContainer.viewContext
let objeto = NSFetchRequest<NSManagedObject>(entityName: entidad)
let ordenacion = NSSortDescriptor(key: orden, ascending: ascendente)
objeto.sortDescriptors = [ordenacion]
objeto.predicate = predicate
print("OBJETO: ", objeto)
let recorrerResultados = NSFetchedResultsController<NSManagedObject>(fetchRequest: objeto, managedObjectContext: context!, sectionNameKeyPath: "seccionLetra", cacheName: nil)
var array = [AnyObject]()
array.append(objeto)
array.append(recorrerResultados)
return array
}
Well, is no getting any error, but the searching is always return empty, I think my expression in predicate is not correct:
NSPredicate(format: "razon_social contains[cd] %#", buscar)
Moreover, I want to make it insensitive, that is achieved with ANY razon_social .. ?
Your predicate looks valid to me. "c" is for caseInsensitive and "d" for accents and stuff like that.
I've tried to set up a project similar to yours, with an entity called Clientes, containing 3 optional Strings called nombre_comercial, razon_social and seccionLetra, used your functions and it seems to be working.
I have tried printing the results right after your performFetch() and got correct results.
do {
try resultadosFiltrados.performFetch()
if let results = resultadosFiltrados.fetchedObjects as? [Clientes] {
print ("results.count \(results.count)")
for cliente in results {
print("nombre comercial \(cliente.nombre_comercial! )")
}
}
} catch {
print("👋 \(error)")
}
You should try to check if your data is correct, by removing the predicate for example, to see the complete results, and so on.
I got it with a little help some days ago, and I'm going to share it with you.
var estaBuscando = false
let funcCoreData = FuncCoreData()
var resultados: NSFetchedResultsController<NSManagedObject> = NSFetchedResultsController()
var resultadosFiltrados: NSFetchedResultsController<NSManagedObject> = NSFetchedResultsController()
var objeto: NSFetchRequest<NSManagedObject> = NSFetchRequest()
var aFiltrados = [Cliente]()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let respuesta = self.funcCoreData.obtenerResultados(entidad: "Clientes", orden: "nombre_comercial", ascendente: true)
self.objeto = respuesta[0] as! NSFetchRequest<NSManagedObject>
self.resultados = respuesta[1] as! NSFetchedResultsController<NSManagedObject>
do {
try self.resultados.performFetch()
self.pintarSecciones()
} catch {
print("👋👋👋👋 \(error)")
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
if estaBuscando {
let obj2 = self.aFiltrados[indexPath.item]
cell.codigo.text = obj2.codigo
cell.titulo.text = obj2.nombre
cell.subtitulo.text = obj2.razonSocial
return cell;
} else {
if let obj = self.resultados.object(at: indexPath) as? Clientes {
cell.codigo.text = obj.codigo!
cell.titulo.text = obj.nombre_comercial!
cell.subtitulo.text = obj.razon_social!
}
}
return cell
}
func filtrarContenido(searchText: String) {
let buscar = searchText.lowercased()
let p1 = NSPredicate(format: "nombre_comercial contains[cd] %#", buscar)
let p2 = NSPredicate(format: "razon_social contains[cd] %#", buscar)
let predicate = NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.or, subpredicates: [p1, p2])
let respuesta = self.funcCoreData.obtenerResultadosFiltrados(entidad: "Clientes", orden: "nombre_comercial", ascendente: true, predicate: predicate)
self.resultadosFiltrados = respuesta[1] as! NSFetchedResultsController<NSManagedObject>
do {
try self.resultadosFiltrados.performFetch()
self.aFiltrados = [Cliente]() // limpiar listado
// convertir cada resultado obtenido al modelo Cliente
for cli in self.resultadosFiltrados.fetchedObjects as! [Clientes] {
let cliente = Cliente()
cliente.convertir(cliente: cli)
self.aFiltrados.append(cliente)
}
} catch {
print("👋👋👋👋 Filtrar clientes \(error)")
}
}
func searchDisplayController(_ controller: UISearchDisplayController, shouldReloadTableForSearch searchString: String?) -> Bool {
self.filtrarContenido(searchText: searchString!)
return true
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if(searchText.isEmpty) {
estaBuscando = false
} else {
estaBuscando = true
}
self.filtrarContenido(searchText: searchText)
self.tableView.reloadData()
}
File: FuncCoreData.swift
func obtenerResultadosFiltrados(entidad: String, orden: String, ascendente: Bool, predicate: NSPredicate) -> [AnyObject] {
let appDelegate = UIApplication.shared.delegate as? AppDelegate
let context = appDelegate?.persistentContainer.viewContext
let objeto = recorrerObjeto(entidad: entidad, orden: orden, ascendente: ascendente)
objeto.predicate = predicate
let recorrerResultados = NSFetchedResultsController<NSManagedObject>(fetchRequest: objeto, managedObjectContext: context!, sectionNameKeyPath: "seccionLetra", cacheName: nil)
var array = [AnyObject]()
array.append(objeto)
array.append(recorrerResultados)
return array
}
func obtenerResultados(entidad: String, orden: String, ascendente: Bool) -> [AnyObject] {
let appDelegate = UIApplication.shared.delegate as? AppDelegate
let context = appDelegate?.persistentContainer.viewContext
let objeto = recorrerObjeto(entidad: entidad, orden: orden, ascendente: ascendente)
let recorrerResultados = NSFetchedResultsController<NSManagedObject>(fetchRequest: objeto, managedObjectContext: context!, sectionNameKeyPath: "seccionLetra", cacheName: nil)
var array = [AnyObject]()
array.append(objeto)
array.append(recorrerResultados)
return array
}
func recorrerObjeto(entidad: String, orden: String, ascendente: Bool) -> NSFetchRequest<NSManagedObject> {
let objeto = NSFetchRequest<NSManagedObject>(entityName: entidad)
let ordenacion = NSSortDescriptor(key: orden, ascending: ascendente, selector: #selector(NSString.caseInsensitiveCompare))
objeto.sortDescriptors = [ordenacion]
return objeto
}
File: Clientes+CoreDataProperties.swift
import Foundation
import CoreData
extension Clientes {
#nonobjc public class func fetchRequest() -> NSFetchRequest<Clientes> {
return NSFetchRequest<Clientes>(entityName: "Clientes");
}
#NSManaged public var cif_dni: String?
#NSManaged public var codigo: String?
#NSManaged public var domicilio: String?
...
var seccionLetra: String? {
let letra = nombre_comercial!.characters.map { String($0) }
return letra[0].uppercased()
}
}
IMPORTANT!! File: Cliente.swift.
An object class 'Cliente' with function 'convertir()'.
This class works like an object with which 'aFiltrados'is filled, and to filter a CoreData object is required to transform it to this object 'Cliente'.
import UIKit
class Cliente {
var codigo = ""
var nombre = ""
...
...
func convertir(cliente: Clientes) {
codigo = cliente.cif_dni!
nombre = cliente.nombre_comercial!
...
...
}
}

Update specific part of firebase database swift

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)
}
})