SWIFT 3 and Firebase using tableEdit mode to insert data to firebase which updates my table array for tableview - swift

SWIFT 3 and Firebase - I'm trying to use the UITable inEditing mode to insert cells into firebase and have a firebase listener that updates my arraty. My insertions to fire base are fine, but I keep getting an index out of range when I try to do the insertion with the new add button i created. Has anyone used Firebase with UITable inEditing mode to insert into a table and update firebase.
This is what I looking for:
enter image description here
The problem maybe be how I wrote the cellForAt:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("zzz indexPath index path row: \(indexPath.row)")
print("zzz indexPath name \(myPins[indexPath.row].pinName)")
print("ZZZ myPins Count \(myPins.count)")
let cell = tableView.dequeueReusableCell(withIdentifier: "PinCell", for: indexPath)
if indexPath.row == 0 && isEditing {
//this means we are in editing mode an we to add the cell that will be addPlace
//let indexPathOfFirstRow = IndexPath(item: 0, section: 0)
cell.textLabel?.text = "Add Place"
print("add place was called index.row is : \(indexPath.row)")
} else {
//let cell = tableView.dequeueReusableCell(withIdentifier: "PinCell", for: indexPath)
let pin = myPins[indexPath.row]
cell.textLabel?.text = pin.pinName
}
return cell
}
i get this error message: fatal error: Index out of range
Here is the rest of the table set up code:
//When the use press the editing button it will make the table enditable
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
//if the viw is in editing mode then we will set the table to be in enditing mode.
if isEditing {
//This is adding the addtional cell in for add place
tableView.beginUpdates()
let indexPath = IndexPath(row: 0, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
// self.tableView.insertRows(at: [indexPathOfFirstRow], with: UITableViewRowAnimation.automatic)
tableView.endUpdates()
tableView.setEditing(true, animated: true)
} else {
//when the 'Done' is pressed this will take away the add button
tableView.beginUpdates()
let indexPathOfFirstRow = IndexPath(item: 0, section: 0)
self.tableView.deleteRows(at: [indexPathOfFirstRow], with: UITableViewRowAnimation.automatic)
tableView.endUpdates()
//otherwise the table will not be in editing mode.
tableView.setEditing(false, animated: false)
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//STEP 1 for adding a row that will fuction as add place
//If we are in editing mode a 1 will be return and the extra cell will be added
let adjustment = isEditing ? 1 : 0
//add the extra cell if we are in editing mode
return myPins.count + adjustment
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PinCell", for: indexPath)
if indexPath.row == 0 && isEditing {
//this means we are in editing mode an we to add the cell that will be addPlace
//let indexPathOfFirstRow = IndexPath(item: 0, section: 0)
cell.textLabel?.text = "Add Place"
print("add place was called index.row is : \(indexPath.row)")
//addCell.addButton.tag = indexPath.row
//addCell.addButton.addTarget(self, action: "addPlace", for: .touchUpInside)
} else {
// let cell = tableView.dequeueReusableCell(withIdentifier: "PinCell", for: indexPath)
//this is the info I want to dispaly in the cell
let pin = myPins[indexPath.row]
cell.textLabel?.text = pin.pinName
return cell
}
//add the green plus button icon for the extra row added
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
// let indexRow = IndexPath(item: 0, section: 0)
if indexPath.row == 0 {
return .insert
}
return .delete
}
//delete with a with a swipe
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
print("pins count before deleate\(myPins.count)")
if editingStyle == .delete {
let pin = myPins[indexPath.row]
guard let currentUser = FIRAuth.auth()?.currentUser?.uid else {return}
rootRef.child(child.users.rawValue).child(currentUser).child(users.myPins.rawValue).child(plotToEdit!.plotID).child(pin.placeID).removeValue()
}
//When you press on the green plus button as appose to the row.
else if editingStyle == .insert {
let autocompleteController = GMSAutocompleteViewController()
autocompleteController.delegate = self
present(autocompleteController, animated: true, completion: nil)
}
}
//When in ending more I can slect the first row that is add places
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
// let indexPathOfFirstRow = IndexPath(item: 0, section: 0)
if isEditing && (indexPath.row > 0) {
return nil
}
return indexPath
}

Related

How to change image in imageview when tableview cell is expand and collapse in swift

I am using two images for cell, one i am showing when tableview cell is expand and the other one when cell is collapse
when cell expand i am using arrow-bottom
when cell is collapse arrow-right
for cell expand and collapse i am using below code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let cell = tableView.cellForRow(at: indexPath) as! FAQTableVIewCell
if selectedIndex == indexPath.row{
if self.isCollapse == false{
cell.arrowImage.image = UIImage(named: "arrow-rightt")
self.isCollapse = true
}else{
cell.arrowImage.image = UIImage(named: "arrow-bottom")
self.isCollapse = false
}
}else{
self.isCollapse = true
}
self.selectedIndex = indexPath.row
tableView.reloadRows(at: [indexPath], with: .automatic)
}
but the above code not working properly, first time when i expand cell its not showing bottom arrow, and if i expand two cells then also its not showing properly, pls do help with code
i need when cell expand then i need to show bottom-arrow, when cell in normal(back to its orginal position or collapsed position) then i need to show right-arrow
When you reload rows, they get in cellForRowAt method.
You must apply changes in this method. Store collapsed indexPath and check it in method.
With array:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//use your cell identifier
let cell = tableView.dequeueReusableCell(withIdentifier: "FAQTableVIewCell", for: indexPath) as! FAQTableVIewCell
let image = collapsedCells.contains(indexPath) ? UIImage(named: "arrow-rightt") : UIImage(named: "arrow-bottom")
cell.image = image
//other settings
return cell
}
var collapsedCells = [IndexPath]()
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
//use your height values instead 44 and 120
return collapsedCells.contains(indexPath) ? 44 : 120
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if let index = collapsedCells.firstIndex(of: indexPath) {
collapsedCells.remove(at: index)
} else {
collapsedCells.append(indexPath)
}
tableView.reloadRows(at: [indexPath], with: .automatic)
}

Swift progressBar filling on every cell-click

Each of my cells in tableView has its own progressBar which is being filled in cellForRowAt method and it works fine.
My problem is whenever I select a cell, it's progress bar refreshes filling.
Does anyone have an idea why and how to prevent it? I think didSelectRowAt method is not a reason because that method does nothing with the progressBar.
Method for filling progressBar:
func updateProgressBar(_ cell: TestTableViewCell, level: String) {
let cellCards = Float64(self.getNumberOfCardsForLevel(level: level))!
let totalCards = Float64(self.totalCards())!
delay(0.3) {
cell.cellProgress.setProgress(Float(cellCards / totalCards), animated: true)
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TestTableViewCell", for: indexPath) as! TestTableViewCell
cell.accessoryType = .disclosureIndicator;
cell.cellProgress.progress = 0
cell.cellTitle.text = "Test"
cell.numOfCardsInCell.text = getNumberOfCardsForLevel(level: "1")
updateProgressBar(cell, level: "1")
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.tableView.indexPathsForSelectedRows?.forEach { index in
if(self.cellSelectedImage[indexPath.row] == UIImage(named: "imageTwo") ) {
tableView.deselectRow(at: indexPath, animated: false)
self.cellSelectedImage[indexPath.row] = UIImage(named: "imageOne")
}
else {
print("Selected row -> \(index.row)")
if self.cellSelectedImage[indexPath.row] == UIImage(named: "imageTwo") {
self.cellSelectedImage[indexPath.row] = UIImage(named: "imageOne")
}
}
}
tableView.reloadRows(at: [indexPath], with: .automatic)
}

Inserting cell in specific section

I am trying to find a way that allows me to insert a new cell under a specific section on my tableview. There is a button that is pressed called "add song" and once a user presses on that it should insert a new cell that is built by with a prototype cell. That prototype cell will allow a user to click on it and edit certain information on that cell. I have been trying to code a way to insert the cell below the cell that is currently in that section which is section "3". I'm sure it is something simple that I am messing up since I'm not very use to doing tableviews. Here is my code:
import UIKit
class MultipleSongsTableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func addSong(_ sender: Any) {
insertNewSongCell()
}
func insertNewSongCell() {
let indexPath = IndexPath(row: -1, section: 3)
tableView.beginUpdates()
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
}
}
extension MultipleSongsTableViewController {
override func numberOfSections(in tableView: UITableView) -> Int {
return 5
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return 1
} else if section == 1 {
return 1
} else if section == 2 {
return 1
} else if section == 3 {
return 1
} else {
return 1
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "trackTitleCell", for: indexPath) as! ReleaseTitleTableViewCell
return cell
} else if indexPath.section == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "genreCell", for: indexPath) as! Genre2TableViewCell
return cell
} else if indexPath.section == 2 {
let cell = tableView.dequeueReusableCell(withIdentifier: "TrackListCell", for: indexPath) as! TrackListTableViewCell
return cell
} else if indexPath.section == 3 {
let cell = tableView.dequeueReusableCell(withIdentifier: "TrackListSongCells", for: indexPath) as! TrackListSongsTableViewCell
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "AddSongButtonCell", for: indexPath) as! AddSongTableViewCell
return cell
}
}
}
Also here is a screenshot of how my viewcontroller looks and where I expect the new cell to populate.
I would like the new cell to be inserted after the cell that says "Song Name", I would like the inserted cell to be the same prototype cell that is currently there because the user can click on that cell and fill out information and change the current "Song Name" label to what ever they want.
First of all you need a data source array for the section for example
var songs = [String]()
Then you have to modify numberOfRowsInSection to return the number of songs for section 3. This method can be simplified anyway
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 3: return songs.count
default: return 1
}
}
Now you can add a new song to the array and insert the row
func insertNewSongCell() {
let insertionIndex = songs.count
songs.append("New Song")
let indexPath = IndexPath(row: insertionIndex, section: 3)
tableView.insertRows(at: [indexPath], with: .automatic)
}
beginUpdates and endUpdates have no effect in this case, you can omit the lines.
Calling UITableView.insertRows(at:with:) will insert cells into your UITableView. You can insert exactly 1 cell by passing an indexPaths argument containing 1 IndexPath:
self.tableView.insertRows(at: [IndexPath(row: 1, section: 3)], with: .automatic)
You may need to also update your UITableViewDataSource to return expected values, e.g. from its tableView(_:numberOfRowsInSection:), to account for the additional row(s). Otherwise, your app will throw an unhandled exception and crash.

when i scroll down the tableview the checkmarks of the hidden cells disappear

Cell with enabled checkmark before scrolling:
Cells with disabled checkmarks after I have scrolled up:
hey Guys, I have created a tableview and an add button to add new cells. when i add cells and i enable the UITableViewCell.AccessoryType.checkmark the checkmarks disappear when i scroll the tableview and the cells disappear out of the view.
how can i fix it ?
var waterValue = [String]()
#IBAction func addButtonPressed(_ sender: Any) {
let alert = UIAlertController(title: "add your amount of water for today", message: nil, preferredStyle: .alert)
alert.addTextField(configurationHandler: {(waterAmountTodayTF) in waterAmountTodayTF.placeholder = "enter L for today"})
alert.textFields?.first?.textAlignment = .center
alert.textFields?.first?.becomeFirstResponder()
alert.textFields?.first?.keyboardType = UIKeyboardType.decimalPad
let action = UIAlertAction(title: "add", style: .default) {
(_) in
guard let waterAmountForToday = (alert.textFields?.first?.text) else { return }
self.add("\(waterAmountForToday) L")
// print(self.sliderValue)
}
alert.addAction(action)
present(alert, animated: true)
}
func add(_ individualWaterAmount: String) {
let index = 0
waterValue.insert(individualWaterAmount, at: index)
let indexPath = IndexPath(row: index, section: 0)
tableView.insertRows(at: [indexPath], with: .left)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 70.0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return waterValue.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let individualWaterValues = waterValue[indexPath.row]
cell.textLabel?.text = individualWaterValues
cell.textLabel?.textAlignment = .right
cell.selectionStyle = .none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView.cellForRow(at: indexPath)?.accessoryType == UITableViewCell.AccessoryType.checkmark {
tableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCell.AccessoryType.none
} else {
tableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCell.AccessoryType.checkmark
}
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
guard editingStyle == .delete else { return }
waterValue.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
}
You have not added logic to set accessory type to checkmark while creating new cell.
What you need to do is, save the value which you have selected, and then use that values while creating new cell.
var selectedIndexes: [Int] = []; //global variable
...
...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let individualWaterValues = waterValue[indexPath.row]
cell.textLabel?.text = individualWaterValues
cell.textLabel?.textAlignment = .right
cell.accessoryType = selectedIndexes.contains(indexPath.row) ? UITableViewCell.AccessoryType.checkmark : UITableViewCell.AccessoryType.none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView.cellForRow(at: indexPath)?.accessoryType == UITableViewCell.AccessoryType.checkmark {
tableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCell.AccessoryType.none
selectedIndexes.removeAll(where: { $0 == indexPath.row } )
} else {
tableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCell.AccessoryType.checkmark
selectedIndexes.append(indexPath.row)
}
}

SWIFT 3: List with Dropdown pictures/clips

I'm trying to develop an app that has a similar look as the pictures that I have attached here, since I really like that Idea.
After selecting an item, it drops down and a clip starts playing
Any idea on how to implement this? I can work with tables and lists, but I have no idea on how to actually implement something like this.
You can achieve this with multiple ways
let indexPath = NSIndexPath(forRow: YourSelectedRow, inSection: 0)
tableView.insertRowsAtIndexPaths(indexPath, withRowAnimation: .none )
insert a different row here which will be tricky to manage.
Create all this headers and and create only one cell under selected section.
var selectedSection = -1
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
let view = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 50)
let button = UIButton(frame: view.frame)
button.tag = section
button.addTarget(self, action: #selector(selectExercise(_:), forControlEvents: UIControlEvents.TouchUpInside)
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 5
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
if section == selectedSection
{
return 1
}
else
{
return 0
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier(“YourDetailCell”, forIndexPath: indexPath) as! YourDetailCell
return cell
}
fun selectExercise(sender:UIButton)
{
selectedSection = sender.tag
}
Create two cells and change that specific cell with whole cell portion with animation
var selectedRow = -1
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
if selectedRow == -1
{
selectedRow = indexPath.row
tblConfirmedServices.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Bottom)
}
else
{
selectedRow = - 1
tblConfirmedServices.reloadRowsAtIndexPaths([indexPathPre], withRowAnimation: .Top)
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
if selectedRow = indexPath.row
{
let cell = tableView.dequeueReusableCellWithIdentifier(“YourDetailCell”, forIndexPath: indexPath) as! YourDetailCell
return cell
}
else
{
let cell = tableView.dequeueReusableCellWithIdentifier(“YourCell”, forIndexPath: indexPath) as! YourCell
return cell
}
}