Cell of UITableView is not displayed at all - swift

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

Related

UICollectionView is running before the data load from Web Api

UICollectionView is running before data(finalAllItems) is populated from web api. I should show UICollectionView with data. I have added below line end of the convertReturnsInToWantedType function. But it did not fix the problem. outletForTheCollectionView.reloadData() How can I show data in UICollectionView?
import UIKit
class HomeViewController: UIViewController {
#IBOutlet weak var outletForTheCollectionView: UICollectionView!
#IBOutlet weak var outletForThePageController: UIPageControl!
var howmanyWords : Int = 0
var dataList : [[String:Any]]?
var finalAllItems = [AllItems]()
override func viewDidLoad() {
super.viewDidLoad()
loadVerbs()
outletForTheCollectionView.delegate = self
outletForTheCollectionView.dataSource = self
let xib = UINib(nibName: "CustomCell", bundle: nil)
self.outletForTheCollectionView.register(xib, forCellWithReuseIdentifier: "ViewCellID")
}
func loadVerbs ()
{
let urlString = "http://somelink/english/vocabularyVerbs.ashx"
let url = URL(string: urlString)
let request = URLRequest(url: url!, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 30.0)
let task = URLSession.shared.dataTask(with: request)
{
(data, response, error) in
if let result = try? JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [[String:Any]]
{
DispatchQueue.main.async
{
self.dataList = result
self.convertReturnsInToWantedType()
}
}
}
task.resume()
}
func convertReturnsInToWantedType()
{
// I populate finalAllItems array of dictionary object in here.
// Code might be not well-written in this scope
var datalistCount = dataList!.count
howmanyWords = datalistCount
datalistCount = datalistCount - 1
let nullLabel : String = "variable is coming null from web api"
for n in 0...datalistCount {
let oneItem = self.dataList![n]
var itemWord : String = ""
if let itemWordTemp = oneItem["itemWord"] as? String
{
itemWord = itemWordTemp
}
else
{
itemWord = nullLabel
}
var itemMeaning : String = ""
if let itemMeaningTemp = oneItem["itemMeaning"] as? String
{
itemMeaning = itemMeaningTemp
}
else
{
itemMeaning = nullLabel
}
var itemVerb2Form : String = ""
if let itemVerb2FormTemp = oneItem["itemVerb2Form"] as? String
{
itemVerb2Form = itemVerb2FormTemp
}
else
{
itemVerb2Form = nullLabel
}
var itemVerb3Form : String = ""
if let itemVerb3FormTemp = oneItem["itemVerb3Form"] as? String
{
itemVerb3Form = itemVerb3FormTemp
}
else
{
itemVerb3Form = nullLabel
}
var itemDefination : String = ""
if let itemDefinationTemp = oneItem["itemDefination"] as? String
{
itemDefination = itemDefinationTemp
}
else
{
itemDefination = nullLabel
}
var itemUsingInSentence : String = ""
if let itemUsingInSentenceTemp = oneItem["itemUsingInSentence"] as? String
{
itemUsingInSentence = itemUsingInSentenceTemp
}
else
{
itemUsingInSentence = nullLabel
}
var itemThisWordIsRelatedWithThatWord : String = ""
if let itemThisWordIsRelatedWithThatWordTemp = oneItem["itemThisWordIsRelatedWithThatWord"] as? String
{
itemThisWordIsRelatedWithThatWord = itemThisWordIsRelatedWithThatWordTemp
}
else
{
itemThisWordIsRelatedWithThatWord = nullLabel
}
var itemTrapReply1 : String = ""
if let itemTrapReply1Temp = oneItem["itemTrapReply1"] as? String
{
itemTrapReply1 = itemTrapReply1Temp
}
else
{
itemTrapReply1 = nullLabel
}
var itemTrapReply2 : String = ""
if let itemTrapReply2Temp = oneItem["itemTrapReply2"] as? String
{
itemTrapReply2 = itemTrapReply2Temp
}
else
{
itemTrapReply2 = nullLabel
}
var itemTrapReply3 : String = ""
if let itemTrapReply3Temp = oneItem["itemTrapReply3"] as? String
{
itemTrapReply3 = itemTrapReply3Temp
}
else
{
itemTrapReply3 = nullLabel
}
var itemTrapReply4 : String = ""
if let itemTrapReply4Temp = oneItem["itemTrapReply4"] as? String
{
itemTrapReply4 = itemTrapReply4Temp
}
else
{
itemTrapReply4 = nullLabel
}
finalAllItems.append(
AllItems(
itemWord:itemWord,
itemWordMeaning: itemMeaning,
itemVerb2Form: itemVerb2Form,
itemVerb3Form: itemVerb3Form,
itemDefination: itemDefination,
itemUsingInSentence: itemUsingInSentence,
itemThisWordIsReleatedWithThatWord: itemThisWordIsRelatedWithThatWord,
itemTrapReply1: itemTrapReply1,
itemTrapReply2: itemTrapReply2,
itemTrapReply3: itemTrapReply3,
itemTrapReply4: itemTrapReply4
)
)
} // FOR LOOP ENDS
} // convertReturnsInToWantedType ENDS
override var prefersStatusBarHidden: Bool {
return true
}
}
extension HomeViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
{
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//return self.dataList.count
return self.howmanyWords
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = outletForTheCollectionView.dequeueReusableCell(withReuseIdentifier: "ViewCellID", for: indexPath) as! CustomCell
cell.outletForTheViewInCell.backgroundColor = .lightGray
// word label
cell.outletForTheLabelInCell.text = self.finalAllItems[indexPath.row].itemWord
print(finalAllItems[indexPath.row].itemWord)
var allRepliesArray =
[
self.finalAllItems[indexPath.row].itemTrapReply1,
self.finalAllItems[indexPath.row].itemTrapReply2,
self.finalAllItems[indexPath.row].itemTrapReply3,
self.finalAllItems[indexPath.row].itemTrapReply4,
self.finalAllItems[indexPath.row].itemWordMeaning
]
print(allRepliesArray)
print(allRepliesArray.count)
let randomIndex1 = Int(arc4random_uniform(UInt32(allRepliesArray.count)))
cell.btnOptionA.setTitle(allRepliesArray[randomIndex1], for: .normal)
allRepliesArray = allRepliesArray.filter {$0 != allRepliesArray[randomIndex1]}
print(allRepliesArray.count)
let randomIndex2 = Int(arc4random_uniform(UInt32(allRepliesArray.count)))
cell.btnOptionB.setTitle(allRepliesArray[randomIndex2], for: .normal)
allRepliesArray = allRepliesArray.filter {$0 != allRepliesArray[randomIndex2]}
let randomIndex3 = Int(arc4random_uniform(UInt32(allRepliesArray.count)))
cell.btnOptionC.setTitle(allRepliesArray[randomIndex3], for: .normal)
allRepliesArray = allRepliesArray.filter {$0 != allRepliesArray[randomIndex3]}
let randomIndex4 = Int(arc4random_uniform(UInt32(allRepliesArray.count)))
cell.btnOptionD.setTitle(allRepliesArray[randomIndex4], for: .normal)
allRepliesArray = allRepliesArray.filter {$0 != allRepliesArray[randomIndex4]}
cell.btnOptionE.setTitle(allRepliesArray[0], for: .normal)
cell.correctReply = self.correctAnswerArray[indexPath.row]
print("cevapDogruMu: \(cevapDogruMu)")
cell.dismiss = { [weak self] str in
//Here.
if str == "true"
{
cell.outletForTheViewInCell.backgroundColor = .green
}
else
{
cell.outletForTheViewInCell.backgroundColor = .red
}
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let screenSize = UIScreen.main.bounds.size
return screenSize
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let index = self.outletForTheCollectionView.contentOffset.x / self.outletForTheCollectionView.frame.size.width
self.outletForThePageController.currentPage = Int(index)
//self.outletForThePageController.numberOfPages = dataList.count
self.outletForThePageController.numberOfPages = self.howmanyWords
}
class SnappingCollectionViewLayout: UICollectionViewFlowLayout {
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
guard let collectionView = collectionView else { return super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity) }
var offsetAdjustment = CGFloat.greatestFiniteMagnitude
let horizontalOffset = proposedContentOffset.x + collectionView.contentInset.left
let targetRect = CGRect(x: proposedContentOffset.x, y: 0, width: collectionView.bounds.size.width, height: collectionView.bounds.size.height)
let layoutAttributesArray = super.layoutAttributesForElements(in: targetRect)
layoutAttributesArray?.forEach({ (layoutAttributes) in
let itemOffset = layoutAttributes.frame.origin.x
if fabsf(Float(itemOffset - horizontalOffset)) < fabsf(Float(offsetAdjustment)) {
offsetAdjustment = itemOffset - horizontalOffset
}
})
return CGPoint(x: proposedContentOffset.x + offsetAdjustment, y: proposedContentOffset.y)
}
}
} // extension ENDS
extension MutableCollection {
/// Shuffles the contents of this collection.
mutating func shuffle() {
let c = count
guard c > 1 else { return }
for (firstUnshuffled, unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
// Change `Int` in the next line to `IndexDistance` in < Swift 4.1
let d: Int = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
let i = index(firstUnshuffled, offsetBy: d)
swapAt(firstUnshuffled, i)
}
}
}
extension Sequence {
/// Returns an array with the contents of this sequence, shuffled.
func shuffled() -> [Element] {
var result = Array(self)
result.shuffle()
return result
}
}
This is an example for the JSON return
[
{
"itemWord": "surpass",
"itemMeaning": "lorem",
"itemVerb2Form": "surpassVerb2",
"itemVerb3Form": "surpassVerb3",
"itemDefination": null,
"itemUsingInSentence": null,
"itemThisWordIsRelatedWithThatWord": null,
"itemTrapReply1": "lorem",
"itemTrapReply2": "lorem",
"itemTrapReply3": "lorem",
"itemTrapReply4": "lorem"
},
{
"itemWord": "affect",
"itemMeaning": "lorem",
"itemVerb2Form": "affectVerb2",
"itemVerb3Form": "affectVerb3",
"itemDefination": null,
"itemUsingInSentence": null,
"itemThisWordIsRelatedWithThatWord": null,
"itemTrapReply1": "lorem",
"itemTrapReply2": "lorem",
"itemTrapReply3": "lorem",
"itemTrapReply4": "lorem"
}
]
AllItems.swift file
import Foundation
class AllItems
{
var itemWord : String = "" // 1
var itemWordMeaning : String = "" // 2
var itemVerb2Form : String = "" // 3
var itemVerb3Form : String = "" // 4
var itemDefination : String = "Verb" // 5
var itemUsingInSentence: String = "" // 6
var itemThisWordIsReleatedWithThatWord : String = "" // 7
var itemTrapReply1 : String = ""
var itemTrapReply2 : String = ""
var itemTrapReply3 : String = ""
var itemTrapReply4 : String = ""
init(
itemWord:String,
itemWordMeaning:String,
itemVerb2Form:String,
itemVerb3Form:String,
itemDefination: String,
itemUsingInSentence:String,
itemThisWordIsReleatedWithThatWord: String,
itemTrapReply1: String,
itemTrapReply2: String,
itemTrapReply3: String,
itemTrapReply4: String)
{
self.itemWord = itemWord //1
self.itemWordMeaning = itemWordMeaning //2
self.itemVerb2Form = itemVerb2Form // 3
self.itemVerb3Form = itemVerb3Form // 4
self.itemDefination = itemDefination // 5
self.itemUsingInSentence = itemUsingInSentence // 6
self.itemThisWordIsReleatedWithThatWord = itemThisWordIsReleatedWithThatWord // 7
self.itemTrapReply1 = itemTrapReply1 // 8
self.itemTrapReply2 = itemTrapReply2 // 9
self.itemTrapReply3 = itemTrapReply3 // 10
self.itemTrapReply4 = itemTrapReply4 // 11
}
}
Data request from API is asynchronous. To solve your problem you can call the reloadData function when your finalAllItems variable is setted.
var finalAllItems = [AllItems]() {
didSet {
outletForTheCollectionView.reloadData()
}
}
I'm not sure, but I think you're not setting up the values in your cells.
Right now you're just seeing a bunch of gray cells, right? Maybe just one?
In the func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell, you should set up the values to be shown in the cells before returning them. All you're doing right now is setting up the background color, nothing else.
You should do something like cell.setUpData(finalAllItems[indexPath.row]) inside that function, and then in the cell class you have to create the setUpData method and do whatever you want to do with your data in the cell.
And yes, you should call outletForTheCollectionView.reloadData() every time you want to show new data.

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.

swift, Tableview is displayed incorrectly after saving new Data

at first sorry for my bad english.
My problem is that my tableview will be misrepresented as soon as I save a new file in Firebase.
When saving, a new AddViewController is called.
After saving is automatically returned to the TableviewController.
However, if I stop and restart the app so that the TableviewController is recreated, my tableview will be displayed correctly.
I create a header from an array.
Then I create the cell from another array.
I do not understand why my tableview is displayed incorrectly when I return after saving, but when I recreate the view after the app has finished everything is shown correctly.
My sample pictures:
that's right:
that's bad
My Code from TableViewController:
override func viewDidLoad() {
super.viewDidLoad()
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "Pull to refresh")
refresher.addTarget(self, action: #selector(TagebuchViewController.refresh), for: UIControlEvents.valueChanged)
tableView.addSubview(refresher)
loadTableview()
}
Load data from Firebase, loadTableView():
func loadTableview(){
let userID = Firebase.Auth.auth().currentUser?.uid
databaseRef = Database.database().reference().child("DiabetesIOS").child(userID!)
databaseRef.observe(.value, with: {(snapshot) in
var newItems = [Post]()
var newItemsDate = [String]()
var aNewTime = [String]()
var aNewBl = [String]()
var aNewK = [String]()
var aNewBo = [String]()
var aNewBa = [String]()
var aNewBlu = [String]()
var aNewP = [String]()
var aNewN = [String]()
var dimArrayNewTime = [[String]]()
var dimArrayNewBl = [[String]]()
var dimArrayNewK = [[String]]()
var dimArrayNewBo = [[String]]()
var dimArrayNewBa = [[String]]()
var dimArrayNewBlu = [[String]]()
var dimArrayNewP = [[String]]()
var dimArrayNewN = [[String]]()
for year in snapshot.children.allObjects as! [DataSnapshot] {
for month in year.children.allObjects as! [DataSnapshot] {
for day in month.children.allObjects as! [DataSnapshot] {
for date in day.children.allObjects as! [DataSnapshot] {
for time in date.children.allObjects as! [DataSnapshot] {
let newPost = Post(snapshot: time)
newItems.append(newPost)
let newDate = Post(snapshot: time)
newItemsDate.append(newDate.snap6Date!)
if self.snapshotCheck == 0{
self.snapshotCheckDate = newDate.snap6Date
self.snapshotCheck += 1
}
else{
}
if self.snapshotCheckDate == newDate.snap6Date{
aNewTime.append(newDate.time)
aNewBl.append(newDate.blutzucker)
aNewKe.append(newDate.ke)
aNewBo.append(newDate.bolusInsulin)
aNewBa.append(newDate.basalInsulin)
aNewBlu.append(newDate.blutdruck)
aNewP.append(newDate.puls)
aNewN.append(newDate.notiz)
}
else{
dimArrayNewTime.append(aNewTime)
dimArrayNewBl.append(aNewBlutzucker)
dimArrayNewK.append(aNewKe)
dimArrayNewBo.append(aNewBolusinsulin)
dimArrayNewBa.append(aNewBasalinsulin)
dimArrayNewBlu.append(aNewBlutdruck)
dimArrayNewP.append(aNewPuls)
dimArrayNewN.append(aNewNotiz)
aNewTime.removeAll()
aNewBl.removeAll()
aNewK.removeAll()
aNewBo.removeAll()
aNewBa.removeAll()
aNewBlu.removeAll()
aNewP.removeAll()
aNewN.removeAll()
aNewTime.append(newDate.time)
aNewBl.append(newDate.blutzucker)
aNewK.append(newDate.ke)
aNewBo.append(newDate.bolusInsulin)
aNewBa.append(newDate.basalInsulin)
aNewBlu.append(newDate.blutdruck)
aNewP.append(newDate.puls)
aNewN.append(newDate.notiz)
self.snapshotCheckDate = newDate.snap6Date
}
}
}
}
}
}
self.postArrayValue = newItems
self.aHeaderDate = newItemsDate
self.aHeaderDate = self.uniq(source: self.aHeaderDate)
dimArrayNewTime.append(aNewTime)
dimArrayNewBl.append(aNewBl)
dimArrayNewK.append(aNewK)
dimArrayNewBo.append(aNewBo)
dimArrayNewBa.append(aNewBa)
dimArrayNewBlu.append(aNewBlu)
dimArrayNewP.append(aNewP)
dimArrayNewN.append(aNewN)
self.dimArrayTime = dimArrayNewTime
self.dimArrayBl = dimArrayNewBl
self.dimArrayK = dimArrayNewK
self.dimArrayBo = dimArrayNewBo
self.dimArrayBa = dimArrayNewBa
self.dimArrayBlu = dimArrayNewBlu
self.dimArrayP = dimArrayNewP
self.dimArrayN = dimArrayNewN
newItems.removeAll()
newItemsDate.removeAll()
aNewTime.removeAll()
aNewBl.removeAll()
aNewK.removeAll()
aNewBo.removeAll()
aNewBa.removeAll()
aNewBlu.removeAll()
aNewP.removeAll()
aNewN.removeAll()
dimArrayNewTime.removeAll()
dimArrayNewBl.removeAll()
dimArrayNewK.removeAll()
dimArrayNewBo.removeAll()
dimArrayNewBa.removeAll()
dimArrayNewBlu.removeAll()
dimArrayNewP.removeAll()
dimArrayNewN.removeAll()
self.tableView.reloadData()
}){
(error) in
print(error.localizedDescription)
}
}
For my Header:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = Bundle.main.loadNibNamed("TableViewCell1", owner: self, options: nil)?.first as! TableViewCell1
headerView.date.text = aHeaderDate[section]
headerView.backgroundColor = UIColor.white
return headerView
}
NumberOfRows:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dimArrayTime[section].count
}
Number of Headers:
override func numberOfSections(in tableView: UITableView) -> Int {
return aHeaderDate.count
}
Number of Cells:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dimArrayTime[section].count
}
Section:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell2 = Bundle.main.loadNibNamed("TableViewCell2", owner: self, options: nil)?.last as! TableViewCell2
let sectionTime = dimArrayTime[indexPath.section][indexPath.row]
let sectionBl = dimArrayBl[indexPath.section][indexPath.row]
let sectionK = dimArrayK[indexPath.section][indexPath.row]
let sectionBo = dimArrayBo[indexPath.section][indexPath.row]
let sectionBa = dimArrayBa[indexPath.section][indexPath.row]
let sectionBlu = dimArrayBlu[indexPath.section][indexPath.row]
let sectionP = dimArrayP[indexPath.section][indexPath.row]
let sectionN = dimArrayN[indexPath.section][indexPath.row]
cell2.time.text = sectionTime
cell2.bl.text = sectionBl
cell2.k.text = sectionK
cell2.bo.text = sectionBo
cell2.ba.text = sectionBa
cell2.blu.text = sectionBlu
cell2.p.text = sectionP
cell2.n.text = sectionN
return cell2
}
addViewController:
#IBAction func saveInDatabaseFirebase(_ sender: Any) {
let userID = Firebase.Auth.auth().currentUser?.uid
let postRef = dataRef.child("DIOS").child(userID!).child(stringForDbYear).child(stringForDbMonth).child(stringForDbDay).child(stringForDbDate).child(stringForDbTime)
sDate = tFDate.text!
if tFBl.text == "" {
sBl = "-"
}
else{
sBl = tFBl.text!
}
if tFK.text == "" {
sK = "-"
}
else{
sK = tFK.text!
}
if tFBo.text == "" {
sBo = "-"
}
else{
sBo = tFBo.text!
}
if tFBa.text == "" {
sBa = "-"
}
else{
sBa = tFBa.text!
}
if tfBlu.text == "" {
sBlu = "-"
}
else{
sBlu = tfBlu.text!
}
if tFP.text == "" {
sP = "-"
}
else{
sP = tFP.text!
}
if tFN.text == "" {
sN = "-"
}
else{
sN = tFN.text!
}
let post = Post (date: stringForDbDate, time: stringForDbTime, day: stringForDbDay, bl: sBl, k: sK, bo: sBo, ba: sBa, blu: sBlu, p: sP, n: sN, snap1DIOS: "DIOS", snap2UserID: userID!, snap3Year: stringForDbYear, snap4Month: stringForDbMonth, snap5Day: stringForDbDay, snap6Date: stringForDbDate, snap7Time: stringForDbTime)
postRef.setValue(post.toAnyObject())
self.dismiss(animated: true, completion: nil);
}
Thank you very much for help

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

swift/parse: error when setting Parse data to labels

What I am trying to do is to have data from Parse be retrieved from columns by object order. All labels are connected to their respective outlets and all of the outputs retrieve their correct data.
When I run it and open a cell in the tableview it crashes and gives me Thread 1: EXC_BAD_INSTRUCTION (code=EXC>I386_INVOP, subcode=0x0) on this line: self.navBar.topItem?.title = output1 if I select the first cell, and then on this line: self.navBar.topItem?.title = output1b if I select the second cell.
Here is the full function:
firstObject is grabbing the first object in the "eventsdetail" column
secondObject is grabbing the second object in the "eventsdetail" column
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var query = PFQuery(className: "eventsdetail")
let runkey = query.orderByAscending("ID")
runkey.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error : NSError?) -> Void in
if error == nil {
if let objects = objects as [PFObject]! {
for object in objects {
var firstObject = objects[0]
var secondObject = objects[1]
let output1 = firstObject.objectForKey("navTitle") as! String!
let output2 = firstObject.objectForKey("articleTitle") as! String!
let output3 = firstObject.objectForKey("written") as! String!
let output4 = firstObject.objectForKey("date") as! String!
let output5 = firstObject.objectForKey("article") as! String!
let output1b = secondObject.objectForKey("navTitle") as! String!
let output2b = secondObject.objectForKey("articleTitle") as! String!
let output3b = secondObject.objectForKey("written") as! String!
let output4b = secondObject.objectForKey("date") as! String!
let output5b = secondObject.objectForKey("article") as! String!
if indexPath.row == 0 {
self.performSegueWithIdentifier("0a", sender: nil)
self.tableview.deselectRowAtIndexPath(indexPath, animated: true)
self.navBar.topItem?.title = output1
self.articleTitle.text = output2
self.writtenBy.text = output3
self.date.text = output4
self.article.text = output5
} else if indexPath.row == 1 {
self.performSegueWithIdentifier("0a", sender: nil)
self.tableview.deselectRowAtIndexPath(indexPath, animated: true)
self.navBar.topItem?.title = output1b
self.articleTitle.text = output2b
self.writtenBy.text = output3b
self.date.text = output4b
self.article.text = output5b
}
}
}
}
}
}
If there is an easier way of doing this, please mention it, if not try to just solve this method's problem. I know it isn't the cleanest way of doing things.
I am not sure of how you Parse your data but if it can help you, here's how I would do:
//
// Test.swift
// Test
//
// Created by Charles-Olivier Demers on 16-01-04.
//
import UIKit
//import Parse
class EventViewController: UIViewController, UITableViewDelegate {
private var _info = [EventDetails]()
override func viewDidLoad() {
fetchData()
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("0a", sender: nil)
self.tableview.deselectRowAtIndexPath(indexPath, animated: true)
self.navBar.topItem?.title.text = _info[indexPath.row].navTitle()
self.articleTitle.text = _info[indexPath.row].articleTitle()
self.writtenBy.text = _info[indexPath.row].writtenBy()
self.date.text = _info[indexPath.row].date()
self.article.text = _info[indexPath.row].article()
}
func fetchData() {
let query = PFQuery(className: "eventsDetails")
query.orderByAscending("ID")
query.findObjectsInBackgroundWithBlock { (objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects {
for object in objects {
let navTitleObject = object["navTitle"] as! String
let articleTitleObject = object["articleTitle"] as! String
let writtenByObject = object["writtenByObject"] as! String
let dateObject = object["dateObject"] as! String
let articleObject = object["articleObject"] as! String
_info.append(EventDetails(navTitle: navTitleObject, articleTitle: articleTitleObject, writtenBy: writtenByObject, date: dateObject, article: articleObject))
}
}
}
else {
print("Error #\(error!.code)")
}
}
}
}
class EventDetails {
private var _navTitle: String!
private var _articleTitle: String!
private var _writtenBy: String!
private var _date: String!
private var _article: String!
init(navTitle: String, articleTitle: String, writtenBy: String, date: String, article: String) {
self._navTitle = navTitle
self._article = articleTitle
self._writtenBy = writtenBy
self._date = date
self._article = article
}
func navTitle() -> String {
return _navTitle
}
func articleTitle() -> String {
return _articleTitle
}
func writtenBy() -> String {
return _writtenBy
}
func date() -> String {
return _date
}
func article() -> String {
return _article
}
}
First of all, I would create a class named EventDetails. This class will take all the property of EventsDetails class on Parse. So when you fetch your data, you append the data you fetch in an array of EventDetails class in Swift.
After that in your
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
you take the value in your EventDetails array with the indexPath.row and you fill your Table View.
That is how I would do.