UITableView Using a row as a segue [duplicate] - ios

This question already has answers here:
Swift - add gesture recognizer to object in table cell
(3 answers)
Closed 6 years ago.
So I've been trying to get any row to act like a segue to the next class, kind of like how if you swipe left you can delete the row, after adding the func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)
but instead in stead of deleting it I would like it to show the another class. If anyone could help it would be great thanks

You can add swiprgesturerecognizer something like,
class MyViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
var recognizer = UISwipeGestureRecognizer(target: self, action: "didSwipe")
self.tableView.addGestureRecognizer(recognizer)
}
func didSwipe(recognizer: UIGestureRecognizer) {
if recognizer.state == UIGestureRecognizerState.Ended {
let swipeLocation = recognizer.locationInView(self.tableView)
if let swipedIndexPath = tableView.indexPathForRowAtPoint(swipeLocation) {
if let swipedCell = self.tableView.cellForRowAtIndexPath(swipedIndexPath) {
// Swipe happened. Do stuff!
}
}
}
}
}
This was an example, manage it as your need. you can add swipegesture's direction property for handle particular direction's swipe like UISwipeGestureRecognizerDirection.Left or Right.
You can refer this answer as a reference.
Hope this will help :)

If I'm understanding the question correctly, you would like so that the user would swipe left on a cell, and it would trigger a segue?
If this is the case, you could try adding a UISwipeGestureRecognizer to the cell using the addGestureRecognizer method, within the cellForRow method of the UITableViewDataSource class.
Hope this helps!

Related

Updating CoreData through UISwipeGestureRecognizer on custom UITableViewCell?

I am adding a custom swipe gesture on a UITableViewCell that updates CoreData when a specific cell is swiped. However, I am having trouble passing the indexPath of the swiped cell to the function that will modify the CoreData. I am not using a Table View Swipe Action - I am animating the cell when it is swiped to cross the item out, which means I will need to call an animation on the custom UITableViewCell. So far, I have tried passing the indexPath of the swiped cell to the #selector of the UISwipeGestureRecognizer like so:
The function that handles the gesture:
#objc func handleSwipeGesture(sender: UISwipeGestureRecognizer ,at indexPath: IndexPath) {
itemArray[indexPath.row].complete = !itemArray[indexPath.row].complete
print("\(itemArray[indexPath.row].complete)")
saveItems()
// call animation??
}
In cellForRowAt in the UITableViewDelegate I declare the swipe action and pass the indexPath of the swiped cell as a parameter to the function above.
let swipeToComplete = SwipeCompletion.init(target: self, action: #selector(handleSwipeGesture))
swipeToComplete.indexPath = indexPath
cell.addGestureRecognizer(swipeToComplete)
This is the class that enables me to pass the indexPath through:
class SwipeCompletion: UISwipeGestureRecognizer {
var indexPath: IndexPath!
}
However, this I get the error when I swipe on a cell: EXC_BAD_ACCESS (code=1, address=0xf)
Any ideas on how I could achieve this and how I could call the cell animation on a cell?
On these "#selectors" you can't customize the values passed to the call (As far as I know).
It looks like you have indexPath as a property of your custom recognizer.
Use that indexPath, not the one being passed in. Thats likely not the correct instance.
Something like this might be what your trying to do.
#objc func handleSwipeGesture(sender: SwipeCompletion) {
itemArray[sender.indexPath.row].complete = !itemArray[sender.indexPath.row].complete
print("\(itemArray[sender.indexPath.row].complete)")
saveItems()
//call animation??
}

ONLY double tap on UITableView Swift 3.0

I would like my tableView to only react to double taps and not at all to single taps. I am currently using the following code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(singleTap))
tapGesture.numberOfTapsRequired = 1
view.addGestureRecognizer(tapGesture)
let doubleTapGesture = UITapGestureRecognizer()
doubleTapGesture.numberOfTapsRequired = 2
view.addGestureRecognizer(doubleTapGesture)
tapGesture.require(toFail: doubleTapGesture)
// implement what to do
if userInfo[indexPath.row].identifier == "username" {
editUsername()
}
}
func singleTap() {
// DO NOTHING
}
So basically I have been trying to "redirect" the single tap to a function that does nothing. However, I find that (in the simulator), the tableView sometimes reacts to the single tap, sometimes not. Any help to solve this issue is highly appreciated!
To achieve your goal:
Add tap gesture recognizer on your table view, do not forget to set numberOfTapsRequired = 2
Do not implement didSelectRowAtIndexPath method
To prevent table view cells from changing their background color after single tap, set in interface builder, Attributes Inspector tab, table view "selection" attribute to "No selection" or table view cell "selection" attribute to "None".
If you want to get indexpath of cell being doubletapped, in your gesture recognizer handler method get tap location in tap.view and use indexPathForRowAtPoint method of tableView:
let tapLocationPoint = tap.location(in: tap.view)
let tappedCellIndexPath = tableView.indexPathForRow(at: tapLocationPoint)

Change UIImageView image with swipe action

On my tableview I have a UIImageView, and I need change the image when swipe action is executed. I have a class to row of tableview, so I changed the code to try do it. This is the code but not worked. How can I do it?
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) -> CellTableViewFriends{
// you need to implement this method too or you can't swipe to display the actions
let cell = self.tableViewFriends.dequeueReusableCellWithIdentifier("CellTableViewFriends") as! CellTableViewFriends;
cell.imgArrow.image = UIImage(named: "myImage")
return cell
}
in your cell class, you can add the following methods:
func addSwipeGesture() {
let gestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(self.swipedLeft))
gestureRecognizer.direction = .Left
self.addGestureRecognizer(gestureRecognizer)
}
func swipedLeft(gesture: UIGestureRecognizer!) {
//Change picture here
imgArrow.image = UIImage(named: "myImage")
}
You can change the direction or do the same for adding multiple directions.
Then you should make sure you call the addSwipeGesture command when creating the cell, you can do that in cellForRowAtIndexPath.
Hope this helps!
If that's what you want to do, you should change:
let cell = self.tableViewFriends.dequeueReusableCellWithIdentifier("CellTableViewFriends") as! CellTableViewFriends;
to cellForRowAtIndexPath(_:)
let cell = self.tableViewFriends.cellForRowAtIndexPath(indexPath)
You should add swipegesture recognozer to custom cell class and and handle swipe from that class i think. commitEditingStyle is for editing cell like delete, so you can't use it to swape images in cell.
Hope this will help :)

How to trigger a pickerview when select a cell in a tableView

I have a tableView with 7 cells like this:
I wanna trigger some events when you select a cell. For example, start editing the username when you tap the Username row. And pop up a picker view at the bottom with Male/Female selection inside when you tap the Gender row.
As far as I know, I need to put those events inside this:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
But I have no idea how to accomplish this. Anyone has ideas? Thank you in advance.
Basically, you can make each cell has its own picker view.
open class DatePickerTableViewCell: UITableViewCell {
let picker = UIDatePicker()
open override func awakeFromNib() {
super.awakeFromNib()
picker.datePickerMode = UIDatePickerMode.date
}
open override var canBecomeFirstResponder: Bool {
return true
}
open override var canResignFirstResponder: Bool {
return true
}
open override var inputView: UIView? {
return picker
}
...
}
And then in your didSelectRowAt, just make the cell becomeFirstResponder:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? DatePickerTableViewCell {
if !cell.isFirstResponder {
_ = cell.becomeFirstResponder()
}
}
}
You can check my library for detail:
https://github.com/hijamoya/PickerViewCell
You are correct. Putting the logic in didSelectRowAtIndexPath is a good way to go.
How you do it is to write code. There is no stock answer.
If you want content to appear on top of the current window then you will need to handle that yourself. On iPad, you could use a popover, but popovers are not supported natively on iPhone/iPod touch. You might look at using a 3rd party popover library that offers popover support for iPhone. There are several on Github, and probably several on Cocoa Controls as well. I've used one before, but it had a few issues, so I wouldn't recommend it.
If you are ok presenting a whole new view controller then simply define a new view controller in your storyboard, give it a unique identifier, use instantiateViewControllerWithIdentifier to create it, then presentViewController:animated: to display it modally.
UIPickerView is subclass of UIView, so you can add and use it same like any other UIView object. for your specific recquirment you should create an object of UIPickerView and show and hide it when necessary.
So create a UIPickerView and add above the table view inside view in which you added tableView and in didSelectRowAtIndexPath set pickerView.hidden = false
And also you can animate it from bottom via
UIView.animateWithDuration(1, animations: { () -> Void in
// And set final frame here
})

Swift: get arbitrary info from UITapGestureRecognizer

I have a list of images within a cell, within a UITableView. For reasons I won't go (too much) into, I can't use didSelectRowAtIndexPath to know which one was selected due to the fact that I am using a third party module that adds its own parent Gestures, and I cannot set cancelsTouchesInView = false (which could technically fix my problem).
In either case, is there a way to add arbitrary info to a view, so that when I receive it in as the sender, I could introspect it.
Eg: if this were HTML & JavaScript, you could do this.
$(myImage).data('foo', 'bar')
$(anotherImage.data('foo', 'thunk')
$('img').on('click', function () {
console.log($(this).data('foo')) // could be "foo" or "thunk"
})
In Swift
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = MyCustomTableViewCell()
cell.userInteractionEnabled = true
let tapped = UITapGestureRecognizer(target: self, action: Selector("myCallback:"))
cell.addGestureRecognizer(tapped)
// my imaginary world...
cell.foo = self.extraData[indexPath.row]
return cell
}
func myCallback(sender: AnyObject?) {
println(sender.foo)
}
Obviously, the above doesn't work, but is there a way to achieve what I'm trying to do?
Although I personally don't recommend using that much but you can make use of objc_setAssociatedObject if you want to attach extra data to objects at runtime.
Here is one good resource about how to do it in Swift:
http://nshipster.com/swift-objc-runtime/
Alternatively, UIView classes have a property named tag to where you can assign indexPath.row for getting the cell that was tapped on later:
cell.tag = indexPath.row
BTW, you better not be working on cells. Instead, always operate on its contentView property when you want to add gesture or another sub view etc.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
...
cell.contentView.userInteractionEnabled = true
// Always remove previously added tap gestures because cells are reused
// as you scroll up and down so you'll end up having multiple
// recognizers on the same cell otherwise.
for recognizer in cell.contentView.gestureRecognizers {
cell.contentView.removeGestureRecognizer(recognizer)
}
cell.contentView.addGestureRecognizer(
UITapGestureRecognizer(target: self, action: "myCallback:"))
cell.contentView.tag = indexPath.row
...
return cell
}
It is fairly straightforward to get the cell in call back function:
(Presuming you have only one section so that indexPath.section = 0)
func myCallback(sender: UIGestureRecognizer) {
let indexPath = NSIndexPath(forRow: sender.view.tag , inSection: 0)
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
print("Cell \(cell) has been tapped.")
}
}

Resources