setEditing method delete button doesn't work - swift

In my UIViewController, I have an UITableView which contains different cells with saved contents by using the NSUserDefaults. I also have a custom UIBarButtonItem which causes the UITableView to enter and leave editing mode.
This all works, but the problem is when I tap the round red button and on the right side of the cell appears the delete button, the delete button doesn't work... I can tap on it as much as I want but the cell does not get deleted.
#IBAction func EditListButton(sender: UIBarButtonItem) {
if ShoppingListTable.editing {
ShoppingListTable.setEditing(false, animated: true)
self.EditListButton.title = "Edit"
} else {
ShoppingListTable.setEditing(true, animated: true)
self.EditListButton.title = "Done"
}
}

Use UITableViewDataSource's tableView:commitEditingStyle:forRowAtIndexPath: to detect a tap on the delete button.
Then in the implementation delete the row from your data source (NSUserDefaults in your case).
So in your tableView's dataSource (ie. in the class you implemented numberOfSectionsInTableView: for example), add your custom implementation of tableView:commitEditingStyle:forRowAtIndexPath: where you delete the underlying data.

Related

Saving Changes from an Unwind. Working in conjunction with <Back

I have a problem understanding what I can do with the default Back BarButtonItem and how I can instigate a rewind.
The following shows a simplified layout. I embed a ViewController in a Navigation controller and add a BarButtonItem ("Show") and connect to a second VC. This adds the "Back" button to the second controller as shown below.
In the first VC I will show the user some details, in the second VC greater details will be shown. With the show button and the default back button the user can easily navigate back and forth with expected behavior.
My problem comes in that the user will be allowed to modify the "More Details Here" and I will need to pass that to the first VC after the user unwinds back.
I cannot control-drag from the Back to the Exit icon but I have determined I can do this with a "Save" button on the navigation bar as shown. (First dragging an Navigation Item to the top, then the BarButtonItem) then control-drag to Exit icon.
With the Save button, I can initiate a segue unwind and capture the changes back in my first VC with code like the following.
#IBAction func unwindFromSecondVC(_ sender: UIStoryboardSegue) {
if sender.source is AddCharacterViewController {
if let senderVC = sender.source as? SecondViewController {
details = senderVC.newDetails
}
}
}
This creates a problem when the user makes a change and then clicks the back button thereby loosing the changes.
My preferred solution would be to have the back button initiate a segue and transfer the changes. But this does not appear to be possible. My second solution would be to have the back button notice a transfer has not been made and stop the unwind seque. Neither approach appears possible based on my research.
How should I best handle this problem while giving the user the common Back navigation?
If you want to save any changes the user has made in the second VC, you could create a SecondVCDelegate:
protocol SecondVCDelegate : class {
func detailsDidChange(newDetails: String)
}
In SecondVC, declare a delegate property:
weak var delegate: SecondVCDelegate?
And whenever the details change (the text field's value changed, or whatever event happened), you call
delegate?.detailsDidChange(newDetails: newDetails)
In FirstVC.prepareForSegue, you should set self as the delegate of SecondVC:
if let vc = segue.destination as? SecondVC {
vc.delegate = self
}
// ...
extension FirstVC : SecondVCDelegate {
func detailsDidChange(newDetails: String) {
details = newDetails
}
}
This way, whenever the newDetails change, FirstVC will be notified.
If you just want to notify FirstVC when the user leaves SecondVC, you could instead call the delegate in SecondVC.viewWillDisappear or a method like that.

Is it possible use different instance of UIMenuController for UITextField in Swift?

According to link we should use a singleton UIMenuController instance which is referred to the editing menu.
The problem is I want to show extra items in different situations. For instance, I want to just show "copy" item when keyboard is up. and show "copy" and "reply" when tapping on a tableview row.
When I add "reply" to the UIMenuController instance it is shown when tapping on UITextField too. therefore, I added these codes:
func textViewDidBeginEditing(_ textView: UITextView) {
var nonReplyMenuItems: [UIMenuItem] = []
if let allMenuItems = UIMenuController.shared.menuItems {
for menuItem in allMenuItems {
if menuItem.title != "reply".localized {
nonReplyMenuItems.append(menuItem)
}
}
}
UIMenuController.shared.menuItems = nonReplyMenuItems
UIMenuController.shared.setMenuVisible(true, animated: true)
}
It fixed the problem in most situations, but not all.
when keyboard is up and tapping on a row in tableview "reply" will be added. Then when I tap on UITextView the reply will be shown there too.
It seems your scenario is like it:
tap on textfield ----> shows copy
tap on tableview ---> shows copy and reply
tab on textfield ----> shows copy and reply (you want only copy shows)
As I know the textViewDidBeginEditing calls when your text filed is not editing and you tap on that; So if you have two textfileds by switching on that method calls every time but when you are switching between a text filed and another action base object your text field is editing and its state has not changed.
When you touch on tableview you must call textfield.resignFirstResponder() so when you tap on text field again the textViewDidBeginEditing calls again, the problem of this is hiding keyboard; The better way I preferÙˆ is adding function to touch down of text field or on gesture to do what you write on textViewDidBeginEditing method

make NSTableView row stay selected Swift

how would I go about making a previously selectedRow of an NSTableView stay selected after the user presses a button calling a method to work with that selectedRow?
It worked in a previous programm looking like this:
selecting it gives it the OSX selection color, clicking the save button makes the textField becomeFirstResponder() which makes the row go grey automatically and doesnt change the selectedRow property. This is not done by my code, so im happy it just works.
Now in a similar program I want to achieve exactly this, but after clicking a button (calling a method making the textField becomeFirstResponder()) the visual selection is gone and also the tableView property selectedRow goes back to -1 (no row selected).
I tried a lot of ideas, most answers online are objective-C. Here is my most recent code (beeing called by the same button and pretty much faking what worked automatically before):
the NSTableViewAction method and the selectedRowCache variable:
var selectedRowCache = -1
#IBAction func alarmDataTableView(_ sender: NSTableView) {
selectedRowCache = alarmDataTableView.selectedRow
}
the buttonAction:
#IBAction func editAlarmButton(_ sender: NSButton) {
let row = alarmDataTableView.rowView(atRow: self.selectedRowCache, makeIfNecessary: false)
row?.backgroundColor = .blue
}
the selectedRowCache is just a variable that saves the selectedRow whenever the user selects a row (i dont want this).
no with this code the background color of the row doesnt do a thing (besides losing its selection after the button method is called).
the NSTableView is view based.
Thank you for any help!

NSUserDefaults changing every segue

Sorry for the newbie question but i am really stuck.
I have a UIViewController and 4 tableviews in an app. When i click on a button on the UIViewcontroller it segues to a UITableviewController called "Beach". When the user clicks on a cell of the table, it segues back to the UIViewController and displays the selected cells title as the buttons title. The problem that i am having is when i click on a nother button to a tableview and then clicks on the cell, the previous buttons title sets back to the previous title.
i have a prepare for segue function in the tables view controllers and this returns the selected table title (named : Titleoftable) to the main VC which, the strings.
the way i am currently doing it is to make a NSUserDefault below but the problem still remains the same - The value changes top "" every time i click on another table V---
let path = tableView.indexPathForSelectedRow
let cell = tableView.cellForRowAtIndexPath(path!)
let persistenceStoreKey = "MyStringKey"
let stringToStore = "\((cell?.textLabel?.text!)!)"
// Store data
NSUserDefaults.standardUserDefaults().setObject(stringToStore, forKey: persistenceStoreKey)
NSUserDefaults.standardUserDefaults().synchronize()
// Get data
let myStringt = NSUserDefaults.standardUserDefaults().stringForKey(persistenceStoreKey)
destination.textOfBeach = (myStringt)!
destination.isBeachSelected = true
}
I have been stuck on this problem for ages now! PLEASE HELP!!
PS- I am using swift-2 and Xcode7
Make sure that you are not pushing a new ViewController after you click on the tableview's cell. It gives me the impression that it might be the case since you are seeing only the title of the last cell you pressed.. Make sure you actually pop the tableview's controller instead of pushing a new one.
If you want to keep using NSUserDefaults, you could just call
navigationController?.popViewController(animated: true)
in your cellSelection function, and read the defaults value in the viewWillAppear of the main ViewController.
override func viewWillAppear(_ animated: Bool) {
let userDefault = NSUserDefaults.standard()
if let beachSelection = userDefault.string(forKey: "BeachControllerSelection") {
textOfBeach = beachSelection
isBeachSelected = true
}
//same for the rest of the other table view's selections
}

Table with static cells won't scroll when I set delaysContentTouches = false

The problem: HIGHLIGHT vs SCROLLING
My buttons inside the cell where not getting highlighted when I lightly tap on them. I had to tap hard and for a long time to be able to see the tap state of the button.
So I did this in order to set the delaysContentTouches to false (I didn't manage other way to do it) inside viewDidLoad():
for index in tableView.subviews {
if (index.isKindOfClass(UIScrollView)) {
let scrollViewFound = index as! UIScrollView
scrollViewFound.delegate = self
scrollViewFound.delaysContentTouches = false
scrollViewFound.canCancelContentTouches = true
scrollViewFound.scrollEnabled = true
}
}
This way the buttons highlight correctly but then I cannot scroll the table up or down, unless I start dragging from one of the empty cells --> userInteractionEnable = false in the empty cells
What I need:
To be able to highlight the buttons but also to scroll the table.
Is it even possible to have both, scrollable view and highlighted buttons?
What I have tried
I tried calling this function:
func touchesShouldCancelInContentView(view: UIView) -> Bool {
print("touchesShouldCancelInContentView happening---------")
return true
}
Which never gets called. I tried overriding But it gives an error:
Method does not override any method from its superclass
Which is weird, because UITableViewController inherits from UIScrollView. I also tried adding UIScrollViewDelegate to the class definition, but of course it gives another error that this is redundant.
Extra Information
The class is declared like this:
class Settings: UITableViewController, UITextFieldDelegate { ...
The tableView is made of Static Cells
The cells:
Some are empty: where UserInteractionEnable = false
Some have buttons with text field: I want these buttons to get highlighted. UserInteractionEnable = true. The button action is called by .TouchUpInside
Some have labels and a check image: Their action gets called in didSelectRowAtIndexPath which will change the labels colour and check images
Maybe it is relevant to say that when user clicks on any cell didSelectRowAtIndexPath it will
call a function to dismiss the keyboard.
You tried to subclass the wrong class, that's why it doesn't work. You have to subclass the UITableView class itself, and not the UITableViewController.
Can you try the following ?
- First
Subclass the TableView class in order to override the touchesShouldCancelInContentView function.
class UIDraggableTableView: UITableView {
override func touchesShouldCancelInContentView(view: UIView) -> Bool {
if (view.isKindOfClass(UIButton)) {
return true
}
return super.touchesShouldCancelInContentView(view)
}
}
- Second
In your TableViewController class, when viewDidLoad() is called, append the following right after super.viewDidLoad():
self.tableView = DraggableTableView()
This should solve your issue.
Part of this answer was taken from this StackOverflow post.