I am trying to design View where i can show elements in sync with my Firebase Database. Every time element in my array changes it gets duplicated. Tried to use
self.tableView.reloadData()
but nothing changes. Tried as well
self.tableView.beginUpdates()
self.tableView.reloadRowsAtIndexPaths(NSArray.init(object: indexPath) as! [NSIndexPath], withRowAnimation: .Automatic)
self.tableView.endUpdates()
and it didn't work as previously.
I have tried unsuccesfully to perform reloading tableView in main thread using function
performSelectorOnMainThread
I am posting my code for you guys so someone can help me. Im quite new to iOS programming and i can't figure out when to reload data in tableView. Even after reading Apple's Documentation.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let alert = UIAlertController(title: "Akcja", message: "Wybierz akcję", preferredStyle: .ActionSheet)
let changeFieldNumberAction = UIAlertAction(title: "Zmień numer boiska", style: .Default, handler: {(action) in
self.showAlertOfChangingFieldNumber(indexPath)
})
let sendToRefereeAction = UIAlertAction(title: "Wskaż sędziego", style: .Default, handler: {(action) in
//self.championshitTournamentMode = false
})
let cancelAction = UIAlertAction(title: "Anuluj", style: .Cancel, handler: nil)
alert.addAction(cancelAction)
alert.addAction(changeFieldNumberAction)
alert.addAction(sendToRefereeAction)
self.presentViewController(alert, animated: true, completion: nil)
}
func showAlertOfChangingFieldNumber(indexPath: NSIndexPath) {
let fieldNumberAlert = UIAlertController(title: "Numer boiska", message: "Wpisz numer boiska", preferredStyle: .Alert)
fieldNumberAlert.addTextFieldWithConfigurationHandler({(textField: UITextField!) -> Void in
textField.placeholder = "Numer boiska"
textField.keyboardType = UIKeyboardType.NumberPad
})
let saveAction = UIAlertAction(title: "Zapisz", style: .Default, handler: {(action) -> Void in
let fieldNumberTextField = fieldNumberAlert.textFields![0] as UITextField
let fieldNumber = Int(fieldNumberTextField.text!)
self.updateGameFieldNumber(fieldNumber!, indexPath: indexPath)
})
let cancelAction = UIAlertAction(title: "Anuluj", style: .Cancel, handler: nil)
fieldNumberAlert.addAction(cancelAction)
fieldNumberAlert.addAction(saveAction)
self.presentViewController(fieldNumberAlert, animated: true, completion: nil)
}
func updateGameFieldNumber(fieldNumber: Int, indexPath: NSIndexPath){
let gameKey = games[indexPath.row].key
let ref = FIRDatabase.database().reference().child("games").child(gameKey)
games[indexPath.row].fieldNumber = fieldNumber
ref.updateChildValues(games[indexPath.row].toAnyObject() as! [NSObject : AnyObject])
//self.games.removeAtIndex(indexPath.row+1)
self.tableView.beginUpdates()
self.tableView.reloadRowsAtIndexPaths(NSArray.init(object: indexPath) as! [NSIndexPath], withRowAnimation: .Automatic)
self.tableView.endUpdates()
}
And my tableView delegate functions and function made for filling my array based on Firebase's database looks like that:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! GameViewCellTableViewCell
if games[indexPath.row].fieldNumber == 0 {
cell.fieldNumberLabel.text = "-"
} else {
cell.fieldNumberLabel.text = String(games[indexPath.row].fieldNumber)
}
cell.firstParticipantLabel.text = games[indexPath.row].firstParticipant
cell.secondParticipantLabel.text = games[indexPath.row].secondParticipant
cell.gameImage.image = UIImage(named: "tenisBall")
if games[indexPath.row].completed != true {
cell.backgroundColor = UIColor.init(red: 1, green: 109.0/255, blue: 95.0/255, alpha: 1)
} else {
cell.backgroundColor = UIColor.init(red: 160/255, green: 1, blue: 86/255, alpha: 1)
}
return cell
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.games.count
}
func getGames() {
let ref = FIRDatabase.database().reference().child("games")
ref.observeEventType(.Value, withBlock: {snapshot in
for item in snapshot.children {
let gameItem = GameItem(snapshot: item as! FIRDataSnapshot)
if(gameItem.tournamentName == self.tournamentName) {
self.games.append(gameItem)
}
}
self.tableView.reloadData()
})
}
It gets duplicated because instead of updating the value in your "games" array, you append the modified value to the array. This happens in the "getgames()" method.
inside the
func getGames()
after
self.games.append(gameItem)
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
Related
How can I change the title of an UIAlertAction when I click the button ?
I want to click that button and from "Enable" to make it "Disable" for example.
I spent a lot of time trying to achieve this but I can't manage to do it.
Here is a small Demo with my issue: https://github.com/tygruletz/ChangeTitleOfAlertAction
Here is my code:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
tableView.tableFooterView = UIView()
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "Row \(indexPath.row)"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
showOptions()
}
func showOptions(){
var enable = "Enable"
let disable = "Disable"
let applyOn = UIAlertAction(title: enable, style: .default, handler: { (action: UIAlertAction!) in
enable = disable
})
let actionSheet = configureActionSheet()
actionSheet.addAction(applyOn)
self.present(actionSheet, animated: true, completion: nil)
}
func configureActionSheet() -> UIAlertController {
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
actionSheet.addAction(cancel)
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad ){
actionSheet.popoverPresentationController?.sourceView = self.view
actionSheet.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
actionSheet.popoverPresentationController?.permittedArrowDirections = []
}
return actionSheet
}
}
And here is a capture of screen:
Thank you if you try to help me !
Please follow below code:
Define property in your UIViewController
var selectedIndexPath:IndexPath!
Add argument in showOptions method
func showOptions(indexPath:IndexPath){
var status = "Enable"
if selectedIndexPath == indexPath{
status = "Disable"
}
let applyOn = UIAlertAction(title: status, style: .default, handler: { (action: UIAlertAction!) in
if self.selectedIndexPath == indexPath{
self.selectedIndexPath = nil
}else{
self.selectedIndexPath = indexPath
}
})
let actionSheet = configureActionSheet()
actionSheet.addAction(applyOn)
self.present(actionSheet, animated: true, completion: nil)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
showOptions(indexPath: indexPath)
}
Note:
If you are going with this approach, Then you will never faced cell usability issue.
When I select a table row and click 'Ok' under city tab, it is highlighting the row but when I change the tab to town, it is highlighting the same row in the town tab even though I did not select it.That is if I highlight second and third row under city tab, it is highlighting second and third row under town tab as well without me doing anything. Following is my code
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let myCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CityCell
switch (segCtrl.selectedSegmentIndex)
{
case 0:
myCell.myLabel.text = cityName[indexPath.row]
break
case 1:
myCell.myLabel.text = townName[indexPath.row]
break
default:break
}
return myCell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
let cell = tableView.cellForRow(at: indexPath)!
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
let ok = UIAlertAction(title: "Ok", style: .default, handler: { (action) -> Void in
let cell = tableView.cellForRow(at: indexPath)!
cell.backgroundColor = UIColor(white: 1.0, alpha:0.5)
})
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Void in
})
alertController.addAction(ok)
alertController.addAction(cancel)
present(alertController, animated: true, completion: nil)
}
How do I prevent this highlighting from happening in next tab and confine it to where I actually selected the row?
I'm working with objective-c. So, sorry if my swift code is wrong.
// global variable which carry selection-indexPath
var citySelectedIndexPaths = [IndexPath]()
var townSelectedIndexPaths = [IndexPath]()
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let myCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CityCell
// add this line
myCell.backgroundColor = UIColor(white: 1.0, alpha:1.0) // default color
switch (segCtrl.selectedSegmentIndex)
{
case 0:
myCell.myLabel.text = cityName[indexPath.row]
if citySelectedIndexPaths.contains(indexPath) {
myCell.backgroundColor = UIColor(white: 1.0, alpha:0.5)
}
break
case 1:
myCell.myLabel.text = townName[indexPath.row]
if townSelectedIndexPaths.contains(indexPath) {
myCell.backgroundColor = UIColor(white: 1.0, alpha:0.5)
}
break
default:break
}
return myCell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
let cell = tableView.cellForRow(at: indexPath)!
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
let ok = UIAlertAction(title: "Ok", style: .default, handler: { (action) -> Void in
let cell = tableView.cellForRow(at: indexPath)!
cell.backgroundColor = UIColor(white: 1.0, alpha:0.5)
// save selection indexPath
switch (segCtrl.selectedSegmentIndex)
{
case 0:
if citySelectedIndexPaths.contains(indexPath) {
let indexValue = citySelectedIndexPaths.indexOf(indexPath)
citySelectedIndexPaths.removeAtIndex(indexValue)
} else {
citySelectedIndexPaths.append(indexPath);
}
break
case 1:
if townSelectedIndexPaths.contains(indexPath) {
let indexValue = townSelectedIndexPaths.indexOf(indexPath)
townSelectedIndexPaths.removeAtIndex(indexValue)
} else {
townSelectedIndexPaths.append(indexPath);
}
break
default:break
}
})
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Void in
})
alertController.addAction(ok)
alertController.addAction(cancel)
present(alertController, animated: true, completion: nil)
}
Now in your code, you set background manually.
cell.backgroundColor = UIColor(white: 1.0, alpha:0.5)
But you did not reset cell.backgroundColor after you select other cell. So you need to store current selected cell's indexPath and call reloadData each time you select new cell in ok UIAlertAction. In cellForRowAtIndexPath, just perform cell with selected or unselected stage.
I want to update my tableview cells after an action is called in the editactionsForRowAtIndexPath function.
I've tried calling self.tableView.reloadData from the action handler, from the viewwillappear function and several other areas but it never reloads after the action is called.
What happens is a user swipes left and then they click the Confirm button which confirms an appointment and updates a value in the database.
The object is to have the function finish updating the value and then update the table by reloading so that in the cellforRowAtIndex can recycle through and color each cell a different color according to the values in the database.
But nothing seems to work.
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction] {
//confirm appointment
let confirm_action = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Confirm", handler: { (action:UITableViewRowAction!, indexPath:NSIndexPath!) -> Void in
self.index_number = indexPath.row
let confirm_menu = UIAlertController(title: nil, message: "Which request?", preferredStyle: .ActionSheet)
let number_1 = UIAlertAction(title: "Choice 1", style: UIAlertActionStyle.Default, handler: self.confirm1)
let number_2 = UIAlertAction(title: "Choice 2", style: UIAlertActionStyle.Default, handler: self.confirm2)
let number_3 = UIAlertAction(title: "Choice 3", style: UIAlertActionStyle.Default, handler: self.confirm3)
let cancel = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil)
confirm_menu.addAction(number_1)
confirm_menu.addAction(number_2)
confirm_menu.addAction(number_3)
confirm_menu.addAction(cancel)
self.presentViewController(confirm_menu, animated: true, completion: nil)
self.tableView.reloadData()
})
return [confirm_action]
}
//confirm choice1
func confirm1(alertAction: UIAlertAction!) -> Void {
tableView.sectionIndexColor = UIColor.greenColor()
//Update database entry to confirmed
let query = PFQuery(className: "Schedule")
query.getObjectInBackgroundWithId(object_ids[index_number]){
(Schedule: PFObject?, error: NSError?) -> Void in
//successfully loaded schedule request
if(error == nil && Schedule != nil) {
Schedule!["confirmed"] = "yes1"
dispatch_async(dispatch_get_main_queue()){
Schedule!.saveInBackground()
}
}
}
//update table
self.tableView.reloadData()
index_number = 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("schedules", forIndexPath: indexPath)
//load cell text depending on confirmed or not
if(confirmed_status[indexPath.row] == "yes1"){
cell.textLabel?.text = "\(users_names[indexPath.row]) \nPAID: \(paid_status[indexPath.row]) \nConfirmed for: \(location1) on \(date1)"
cell.textLabel!.textColor = UIColor.greenColor()
cell.editingStyle
}
else{
cell.textLabel?.text = "\(users_names[indexPath.row]) \nPAID: \(paid_status[indexPath.row]) \n#1 \(location1) on \(date1) \n#2 \(location2) on \(date2) \n#3 \(location3) on \(date3)"
}
//To enable word wrap for long titles
cell.textLabel!.numberOfLines = 0
return cell
}
Hi guys I am using NSFetchedResultController but I am getting issues when I delete a record (even with the first record).
Here is the code of my View Controller :
import UIKit
import CoreData
class FoldersListViewController: UITableViewController, NSFetchedResultsControllerDelegate {
#IBOutlet var myFoldersTableView: UITableView!
// public property that represent the current selected row in a tableview; this will be use in the shouldPerformSegueWithIdentifier
// function because the method doesn't have a parameter for the index path of the selected row.
var selectedRowIndex: NSIndexPath? = nil
//Public property that will be controlling all the manipulation of CoreData.
var fetchedResultController: NSFetchedResultsController!
override func viewDidLoad() {
super.viewDidLoad()
let config = Settings()
config.ReadConfiguration()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
//self.navigationItem.rightBarButtonItem = self.editButtonItem()
self.loadFolders()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return fetchedResultController.sections!.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
let sectionInfo = fetchedResultController.sections![section]
return sectionInfo.numberOfObjects
}
func configureCell(cell: cellFolder,indexPath: NSIndexPath)
{
let folder = fetchedResultController.objectAtIndexPath(indexPath) as! Folder
if(folder.picture.length > 0){
let newSize:CGSize = CGSize(width: 64,height: 64)
let rect = CGRectMake(0,0, newSize.width, newSize.height)
UIGraphicsBeginImageContextWithOptions(newSize, true, 0.0)
let photo = UIImage(data: folder.picture)
UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
photo!.drawInRect(rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
cell.imageView?.contentMode = UIViewContentMode.ScaleAspectFill
cell.imageView?.layer.masksToBounds = true
cell.imageView?.layer.cornerRadius = 15.0
cell.imageView?.clipsToBounds = true
cell.imageView?.image = newImage
}
cell.labelFolderName.text = folder.name
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: cellFolder = tableView.dequeueReusableCellWithIdentifier("cellFolder", forIndexPath: indexPath) as! cellFolder
self.configureCell(cell, indexPath: indexPath)
return cell
}
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the specified item to be editable.
if (tableView.editing){
return false
}
else
{
return true
}
}
func loadFolders() {
let request = NSFetchRequest(entityName: "Folder")
let handler = HACoreDataHandler()
let sortDescriptor = NSSortDescriptor(key: "name",ascending: true)
request.sortDescriptors = [sortDescriptor]
fetchedResultController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: handler.context!, sectionNameKeyPath: nil, cacheName: nil)
fetchedResultController.delegate = self
do
{
try fetchedResultController.performFetch()
} catch let error as NSError {
let alert = UIAlertController(title: "Error", message: error.description, preferredStyle: UIAlertControllerStyle.Alert)
let dismiss = UIAlertAction(title: "Dismiss", style: .Default) { (alertAction: UIAlertAction) ->
Void in
}
alert.addAction(dismiss)
presentViewController(alert, animated: true, completion: nil)
}
}
func controllerWillChangeContent(controller: NSFetchedResultsController) {
tableView.beginUpdates()
}
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType)
{
let indexSet = NSIndexSet(index:sectionIndex)
switch type {
case .Insert:
myFoldersTableView.insertSections(indexSet, withRowAnimation: .Automatic)
case .Delete:
myFoldersTableView.deleteSections(indexSet, withRowAnimation: .Automatic)
default:
break
}
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?)
{
switch type{
case .Insert:
myFoldersTableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Automatic)
case .Delete:
myFoldersTableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
case .Update:
myFoldersTableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
case .Move:
if (indexPath != newIndexPath){
myFoldersTableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
myFoldersTableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Automatic)
}
}
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
myFoldersTableView.endUpdates()
}
override func viewWillAppear(animated: Bool) {
self.loadFolders()
myFoldersTableView.reloadData()
}
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
let item = self.fetchedResultController.objectAtIndexPath(indexPath) as! Folder
let handler = HACoreDataHandler()
handler.context?.deleteObject(item)
var error: NSError?
do {
try handler.context?.save()
} catch let error1 as NSError {
error = error1
}
if(error != nil){
let alert = UIAlertController(title: "Error", message: error?.description, preferredStyle: UIAlertControllerStyle.Alert)
let dismiss = UIAlertAction(title: "Dismiss", style: .Default) { (alertAction: UIAlertAction) ->
Void in
}
alert.addAction(dismiss)
presentViewController(alert, animated: true, completion: nil)
}
self.myFoldersTableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
}
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .Default, title: "Delete") { (action:UITableViewRowAction, indexPath:NSIndexPath) -> Void in
self.selectedRowIndex = indexPath
let folder = self.fetchedResultController.objectAtIndexPath(indexPath) as! Folder
let handler = HACoreDataHandler()
handler.context?.deleteObject(folder)
do {
try handler.context?.save()
} catch let error as NSError {
let alert = UIAlertController(title: "Error", message: error.description, preferredStyle: UIAlertControllerStyle.Alert)
let dismiss = UIAlertAction(title: "Dismiss", style: .Default) { (alertAction: UIAlertAction) ->
Void in
}
alert.addAction(dismiss)
self.presentViewController(alert, animated: true, completion: nil)
}
self.myFoldersTableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
}
delete.backgroundColor = UIColor.redColor()
let details = UITableViewRowAction(style: .Normal, title: "Edit") { (action: UITableViewRowAction, indexPath: NSIndexPath) -> Void in
let tmpFolder = self.fetchedResultController.objectAtIndexPath(indexPath) as! Folder
let destination = self.storyboard?.instantiateViewControllerWithIdentifier("editFolder") as! EditFolderViewController
destination.folder = tmpFolder
let navigationController = self.parentViewController as! UINavigationController
var response: Bool = true
if( tmpFolder.isprotected == true){
let alert = UIAlertController(title: "Password Validation", message: "Please enter the folder password", preferredStyle: .Alert)
//2. Add the text field. You can configure it however you need.
alert.addTextFieldWithConfigurationHandler({ (textField) -> Void in
textField.text = ""
})
alert.addAction(UIAlertAction(title: "Login", style: .Default, handler: { (action) -> Void in
let textField = alert.textFields![0]
if (tmpFolder.password == textField.text){
response = true
} else {
let wrongPasswordAlert = UIAlertController(title: "Error", message: "Invalid password.", preferredStyle: UIAlertControllerStyle.Alert)
let dismiss = UIAlertAction(title: "Dismiss", style: .Default) { (alertAction: UIAlertAction) ->
Void in
}
wrongPasswordAlert.addAction(dismiss)
self.presentViewController(wrongPasswordAlert, animated: true, completion: nil)
response = false
} // else if (folder.password == textField.text)
}))
// 4. Present the alert.
self.presentViewController(alert, animated: true, completion: nil)
}
// 4. Present the alert.
if(response){
navigationController.pushViewController(destination, animated: true)
}
//navigationController.presentViewController(destination, animated: true, completion: nil)
//self.showDetailViewController(destination, sender: self)
}
details.backgroundColor = UIColor.grayColor()
return [delete,details]
}
// Override to support rearranging the table view.
//override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
//
//}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
myFoldersTableView.reloadData()
}
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the item to be re-orderable.
return true
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier=="listOcassions"){
let ocassions = segue.destinationViewController as! DatesViewController
let folder = fetchedResultController.objectAtIndexPath(self.selectedRowIndex!) as! Folder
ocassions.folder = folder
}
}
override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool {
var response: Bool = true
if identifier == "listOcassions" {
self.selectedRowIndex = myFoldersTableView.indexPathForSelectedRow
let folder = fetchedResultController.objectAtIndexPath(self.selectedRowIndex!) as! Folder
if( folder.isprotected == true){
let alert = UIAlertController(title: "Password Validation", message: "Please enter the folder password", preferredStyle: .Alert)
//2. Add the text field. You can configure it however you need.
alert.addTextFieldWithConfigurationHandler({ (textField) -> Void in
textField.text = ""
})
alert.addAction(UIAlertAction(title: "Login", style: .Default, handler: { (action) -> Void in
let textField = alert.textFields![0]
if (folder.password == textField.text){
response = true
self.performSegueWithIdentifier("listOcassions", sender: self)
} else {
let wrongPasswordAlert = UIAlertController(title: "Error", message: "Invalid password.", preferredStyle: UIAlertControllerStyle.Alert)
let dismiss = UIAlertAction(title: "Dismiss", style: .Default) { (alertAction: UIAlertAction) ->
Void in
}
wrongPasswordAlert.addAction(dismiss)
self.presentViewController(wrongPasswordAlert, animated: true, completion: nil)
response = false
} // else if (folder.password == textField.text)
}))
// 4. Present the alert.
self.presentViewController(alert, animated: true, completion: nil)
} //if folder.isprotected == true
}
return response
}
}
I can add records but when I try to delete the record I get the following error message:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete row 0 from section 0 which only contains 0 rows before the update'
I know there are similar questions like this before but none of the answers for those questions (that i have applied and some of them are in the copied code) did not solve my issue.
Thanks a lot in advance.
Julio.
The deleteObject in your commitEditingStyle: method triggers the FRC delegate methods, which then delete the relevant row from the table view. So you can delete this line:
self.myFoldersTableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
from the commitEditingStyle method - it is effectively deleting the same row twice. Hence the error.
Likewise for editActionsForRowAtIndexPath.
I have a UITableView and when I add data, it will only allow me to add one row in the UITableview even though I return goals.count for the amount of rows.
This is what I have.
#IBAction func myAddGoal(sender: AnyObject) {
let ac = UIAlertController(title: "Enter a Goal", message: "It can be anything you want!", preferredStyle: .Alert)
ac.addTextFieldWithConfigurationHandler(nil)
let submit = UIAlertAction(title: "Submit", style: .Default) { [unowned self, ac] (action: UIAlertAction!) in
let goal = ac.textFields![0] as UITextField
self.submitGoal(goal.text)
}
ac.addAction(submit)
ac.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Destructive, handler: nil))
presentViewController(ac, animated: true, completion: nil)
}
func submitGoal(goal: String){
if goal == "" {
println("textfield is empty")
} else {
goals.insert(goal, atIndex: 0)
let indexPath = NSIndexPath(forRow: 0, inSection: 0)
myTableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
println(goals)
}
}
I am able to add only ONE goal and it will animate into the UITableView. If I want to add another goal, it will not let me. The app crashes when I hit submit for a second goal entry.
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return goals.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let object = goals[indexPath.row]
cell.textLabel!.text = object
mySwitch.on = false
mySwitch.tag = indexPath.row as Int
mySwitch.addTarget(self, action: "UISwitchUpdated", forControlEvents: UIControlEvents.TouchUpInside)
cell.selectionStyle = .None
cell.accessoryView = mySwitch
return cell
}