tableView.addGestureRecognizer for one section of the tableViewController - ios

I'm new to iOS, swift. I have two sections in my tableView. I want to be able to do a longPressGesture on the second section, and not the first, enabling the user to reorder tableview cells in the second section. How would I do that in swift? Would anyone kindly provide a simple sample code in Swift?
Thanks for your help, much appreciated!

If you just want to reorder move the cell for the particular you may add some button/action to enable/disable reorder , there is delegate which you can use
Your code can be like this:
//enable editing in the tableview to true when you want to enable reorder in your case may on the UILongPressGestureRecognizer action
//In viewDidLoad()
tblView.editing = true//set it to false to complete the reorder
The delegate methods can be use like this:
func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.None
}
func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
//get the reorder change in the path, you can do operation on the array
let itemToMove:String = arrData[fromIndexPath.row]//get the old path of item
arrData.removeAtIndex(fromIndexPath.row)//remove item from old path
arrData.insert(itemToMove, atIndex: toIndexPath.row)//at item at new path in array
}
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
//write code to allow reorder in the particular section/indexpath
if indexPath.section == 0 {
return false
} else {
return true
}
// Return false if you do not want the item to be re-orderable.
}
func tableView(tableView: UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath, toProposedIndexPath proposedDestinationIndexPath: NSIndexPath) -> NSIndexPath {
//check if the reorder is allow in the particular section/indexpath before the reorder is done, return the old path if you don't want to move at Proposed path
if sourceIndexPath.section != proposedDestinationIndexPath.section {
return sourceIndexPath
} else {
return proposedDestinationIndexPath
}
}
the UILongPressGestureRecognizer can be implemented on the tableview or the tableview cell based on the requirements
let longpress = UILongPressGestureRecognizer(target:self, action:#selector(HomeScreenTableViewController.longPressGestureRecognized))
tblView.addGestureRecognizer(longpress)
func longPressGestureRecognized() {
NSLog("Detected")
tblView.editing = true
}
or in tableview cell with same method as above
let longpress = UILongPressGestureRecognizer(target:self, action:#selector(HomeScreenTableViewController.longPressGestureRecognized))
cell.addGestureRecognizer(longpress)

Related

Using Tableview of a UISplitViewController as a filter

I'm putting UISplitViewControllers in UITabBarController.
I'm Trying to use the master view as a filter. So I used cellAccessoryType as check mark . Only one among all can be selected. the code that i wrote for this is
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.selectedIndex = indexPath.row
let cell:UITableViewCell = self.tableView.cellForRowAtIndexPath(indexPath)!
cell.accessoryType = .Checkmark
self.performSegueWithIdentifier("dispAccounts", sender: self)
}
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
let cell:UITableViewCell = self.tableView.cellForRowAtIndexPath(indexPath)!
cell.accessoryType = .None
}
override func viewDidLoad() {
super.viewDidLoad()
filterList = ["All Accounts","Business Accounts","Person Accounts"]
self.tableView.allowsMultipleSelection = false
//self.splitViewController?.maximumPrimaryColumnWidth = 140; //This line is to restrict the width of master View of UISplitVC
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 3
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("accountCell", forIndexPath: indexPath)
cell.textLabel?.text = filterList[indexPath.row]
return cell
}
Now Once I select 'All Account' cell,Then I move to another tab 'Call'
Then I comeback to 'Account' tab, then I select 'Business Accounts' it is getting selected and checkmark is also updating but the problem is 'All accounts' cell's check mark is not getting vanished.
This bug occurs due to the optimisations that have been implemented into UITableView and UITableViewCell. These two views are highly efficient and one way that Apple has made them so efficient is by reusing the cells instead of instantiating new cells all the time (that's why you are calling dequeueReusableCellWithIdentifier instead of instantiating a new cell every time).
In order to overcome this bug, then you have to reset the cells every time they are used.
This can be done in two ways:
OverwritingprepareForReuse if you were subclassing UITableViewCell (but this is not an option for you since you are using the standard UITableViewCell)
Resetting the properties directly in cellForRowAtIndexPath
So a possible solution for you could look like the following:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Getting the cell
let cell = tableView.dequeueReusableCellWithIdentifier("accountCell", forIndexPath: indexPath)
// Resetting the cell
cell.textLabel?.text = ""
cell.selected = false
// Configuring the cell
cell.textLabel?.text = filterList[indexPath.row]
// Returning the finished cell
return cell
}

How to restrict deleting rows in TableView only to certain users?

My problem is as follows. I created an app that allows users to add posts to rows in TableViewController. It also lets them delete only their posts with UITableViewCellEditingStyle by checking if the current user has the same id as the id of the user who created the post. Unfortunately, this way of editing the cells also allows to try to delete others users posts. I would like to make that the delete button only appears when users swipe their posts. I attach an image of the button I have been talking about.
You can do something like this:
If you don't have a custom class for UITableViewCell:
override func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
if owner[indexPath.row] == me {
return .Delete
}
else {
return .None
}
}
Or if you have a custom class for UITableViewCell then this:
override func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
if (tableView.cellForRowAtIndexPath(indexPath) as! YourTableViewCell).owner == me {
return .Delete
}
else {
return .None
}
}
Simply do the check for matching user ids in the tableview's delegate editingStyleForRowAtIndexPath, returning UITableViewCellEditingStyle.None if the user is invalid.
Reference for editingStyleForRowAtIndexPath
You can also try this, remember to set the default editingStyle for cell
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return owner[indexPath.row] == me
}

Swift TableView pass selected Cell

I have two TablewViewControllers: ListTableViewController which holds my list of items and a SortTableViewController where I store sort options for the ListTableView. I need to find a way to highlight the active (if user clicked a sort option) sort option (Cell) when the SortTableViewController loads.Any ideas how to do this?
Screenshot
If you need the sort selection to persist, you can try this.
Use NSUserDefaults to store the selected row index (this assumes your sort options list is fixed)
class SortTableViewController : UITableViewController {
let selectedRowIdx = NSUserDefaults.standardUserDefaults().integerForKey("PLACE_YOUR_KEY_HERE")
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = // your implementation here
if indexPath.row == selectedRowIdx {
cell.textLabel?.textColor = UIColor.redColor()
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
NSUserDefaults.standardUserDefaults().setInteger(indexPath.row, forKey: "PLACE_YOUR_KEY_HERE")
}
}
You ca try this
class SortTableViewController: UITableViewController {
var highlightedIndexPath: NSIndexPath? //TODO: populate this
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = //TODO: populate this
cell.textLabel?.textColor = indexPath == highlightedIndexPath ? .redColor() : .blackColor()
return cell
}
}

NSIndexPath starts with 1

I have the following problem:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// ...
println(indexPath.row)
}
My output goes like this:
1
0
1
0
The numberOfRowsInSection tells me that I've got 10 items:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.actionDto != nil){
println(self.actionDto?.count)
return self.actionDto!.count
}
return 0
}
I have checked this indexpath.row is starting from 1 instead of 0? but can't really follow the answer or solve my problem.
Actually i just want to tap a Label in the cell and do some other stuff. But i have to know exactly which row it was.
I thought about using didSelectRowAtIndexPath method. Then i have problem that if i tap on the label the didSelectRowAtIndexPath method isn't called. (I think because of more than one observer on this label. -> i have delegate method on this cell and the other one i suppose is the tableview.)
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let indexPath = tableView.indexPathForSelectedRow()
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as! TimelineCell
println("The number of cell is \(currentCell.numberOfRowAtIndexPath)")
}
If i click into the cell but not on labels or images all works fine and i get the right number of row. Perhaps someone knows how i can add more than one "observer" on a label for example. So that my Selectormethod and didSelectRowAtIndexPath both knew about the label tapped in the cell. I think this could solve my problem that i can do my own Selectormethod with the knowledge of the right row.
For people who want to know what i mean with Selectormethod:
let gestureRecognizer = UITapGestureRecognizer(target: self, action: Selector("labelPressed")) <-
label.addGestureRecognizer(gestureRecognizer)
func labelPressed() {
delegate?.switchToOwnProfil!()
}
The mysterious thing is, that the first output shows me first 1 and not 0 but perhaps i overlooked something.
Thanks in advance!
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// ...
yourLabel.tag = indexPath.row
let gestureRecognizer = UITapGestureRecognizer(target: self, action: Selector("labelPressed:")) <-
yourLabel.addGestureRecognizer(gestureRecognizer)
println(indexPath.row)
}
and in your function
func labelPressed(label:UILable) {
println(label.tag)
delegate?.switchToOwnProfil!()
}

Create Action For Static Cell Clicked in UITableView

How can I make a static table view to create an action when one of the cells is clicked in Swift?
I have created a static table like a general menu of the app, I can directly create a push segue when one of the cells are clicked. But at the same time when I click to one of the seques, I want the below function to be run. By draging a cell to the UITableView in storyboard the create action option is not appearing.
var goToProfiles = PFObject(className: "goToProfile")
goToProfiles["user"] = PFUser.currentUser()!.username
goToProfiles["goToUser"] = usernameLbl.text
goToProfiles.save()
If you use sections you will also need to query them.
override func tableView(tableView: UITableView,
didSelectRowAtIndexPath indexPath: NSIndexPath) {
print(indexPath.section)
print(indexPath.row)
if indexPath.section == 1 && indexPath.row == 1 {
// do something
}
}
I found the solution with the code below:
override func tableView(tableView: UITableView,
didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 1 {
//here you can enter the action you want to start when cell 1 is clicked
}
}
For swift 3 compatibility:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//Your action here
}

Resources