17

I have an identical question to this one , but since I'm new to programming and only really know swift I was wondering if someone could give me its equivalent in swift. Or point me to another question that I may have missed that is in swift.

Thanks!

UPDATE: here's the basic jist of my view controller after I've cut some of the fat away to deal with only the relevant topic. To restate the problem. Not until I have clicked my 'doneButton' to run the createClient() function and navigate back to the client page to edit the freshly created client will the the tap gesture work to dismiss the keyboard.

import UIKit
import CoreData
import Foundation

class NewClientTableViewController: UITableViewController, UINavigationControllerDelegate, UITextFieldDelegate {

let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext

@IBOutlet weak var nameTxt: UITextField!
@IBOutlet weak var ageTxt: UITextField!
@IBOutlet weak var phoneTxt: UITextField!
@IBOutlet weak var emailTxt: UITextField!
@IBOutlet weak var heightTxt: UITextField!
@IBOutlet weak var notesTxt: UITextView!

var client: Client? = nil

override func viewDidLoad() {
    super.viewDidLoad()

    if client != nil {

        nameTxt.text = client?.name
        ageTxt.text = client?.age
        heightTxt.text = client?.height
        phoneTxt.text = client?.phone
        emailTxt.text = client?.email
        notesTxt.text = client?.notes

        self.title = client?.name
        phoneTxt.delegate = self

        let tapGesture = UITapGestureRecognizer(target: self, action: Selector("hideKeyboard"))
        tapGesture.cancelsTouchesInView = true

        tableView.addGestureRecognizer(tapGesture)

    }
}

func hideKeyboard() {
    tableView.endEditing(true)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


@IBAction func doneButton(sender: AnyObject) {
    if client != nil {
        editClient()
    } else {
        createClient()
    }
    dismissViewController()

}

func editClient() {

    client?.name = nameTxt.text
    client?.age = ageTxt.text
    client?.height = heightTxt.text
    client?.phone = phoneTxt.text
    client?.email = emailTxt.text
    client?.notes = notesTxt.text
    client?.clientImage = UIImageJPEGRepresentation(contactImage.image, 1)

    managedObjectContext?.save(nil)
}

func createClient() {

    let entityDescription = NSEntityDescription.entityForName("Client", inManagedObjectContext: managedObjectContext!)
    let client = Client(entity: entityDescription!, insertIntoManagedObjectContext: managedObjectContext)

    if nameTxt.text == "" {
        client.name = "Untitled Client"
    } else {
        client.name = nameTxt.text
    }

    client.age = ageTxt.text
    client.height = heightTxt.text
    client.phone = phoneTxt.text
    client.email = emailTxt.text
    client.notes = notesTxt.text

    client.clientImage = UIImageJPEGRepresentation(contactImage.image, 1)

    managedObjectContext?.save(nil)

}

func dismissViewController() {
    navigationController?.popToRootViewControllerAnimated(true)
    }
}
Community
  • 1
  • 1
Leighton
  • 6,559
  • 7
  • 21
  • 28

7 Answers7

37

You can also do it from Storyboard:

enter image description here

Ben
  • 3,832
  • 1
  • 29
  • 30
  • 1
    THANK YOU SO MUCH FOR THIS. The other solutions, at least one that I tried with the gesture recognizer prevented me from selecting a table cell that segued into another view. The gesture would cancel the touch. – Hedylove Feb 02 '17 at 06:23
  • Mentioned above but there is a fix for that @JozemiteApps - tapGesture.cancelsTouchesInView = true – powerj1984 Aug 30 '17 at 16:11
  • Thankyou. So many answers on the web, over complicating, yet you're the only one who stated the obvious way. – JamMan9 Mar 01 '18 at 22:11
  • This I did not know existed. Thanks. – mondousage Aug 17 '19 at 15:46
32
override func viewDidLoad() {
    super.viewDidLoad()

    let tapGesture = UITapGestureRecognizer(target: self, action: Selector("hideKeyboard"))
    tapGesture.cancelsTouchesInView = true
    tableView.addGestureRecognizer(tapGesture)
}

func hideKeyboard() {
    tableView.endEditing(true)
}

Translating Objective-C code to Swift is not really hard. You just require a basic knowledge in both languages. If you're new to programming I guess you should familiarise with yourself with the basics first.

Isuru
  • 30,617
  • 60
  • 187
  • 303
  • Do I need to have an outlet to my gesture recognizer this way? – Leighton Mar 22 '15 at 15:35
  • Ok, got it to work. But why does it not work until I've actually saved my contact (I have a contact form in my app). I have to go in to edit the contact in order for it to work. – Leighton Mar 22 '15 at 15:43
  • Hard to say with such little information. Please elaborate. Maybe update your original question with more info and the code you have so far. – Isuru Mar 22 '15 at 19:47
  • oh man. I just resolved it. It wasn't until I posted the edit that I realized that the tapGesture was in my if client != nil statement. Brought it outside to the viewDidLoad and it works great now. I must be tired... :) Thanks again. – Leighton Mar 22 '15 at 20:10
  • 1
    I think: tapGesture.cancelsTouchesInView = false – Tai Le Jan 24 '16 at 16:18
  • if you have a conflict with textField.clearButtonMode = .whileEditing then do tap.cancelsTouchesInView = true – Leon Jakonda Mar 16 '21 at 08:27
7

As @Ben already recommended, you can also do this programmatically. Just put this in your viewDidLoad()

tableView.keyboardDismissMode = .onDrag
phitsch
  • 823
  • 13
  • 12
4

Swift 4:

On ViewDidLoad:

    override func viewDidLoad() {
        super.viewDidLoad()
self.yourTableView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:))))

    }

On corresponding function:

@objc func handleTap(_ sender: UITapGestureRecognizer) {
    if sender.state == .ended {
        // Do your thang here!
        self.view.endEditing(true)
        for textField in self.view.subviews where textField is UITextField {
            textField.resignFirstResponder()
        }
    }
    sender.cancelsTouchesInView = false
}
Alvin George
  • 14,148
  • 92
  • 64
3

For some reason, @Isuru's answer crashes in my app (XCode 7.2.1), and thankfully it's just a minor change - just remove the Selector() call:

override func viewDidLoad() {
    super.viewDidLoad()

    let tapGesture = UITapGestureRecognizer(target: self, action: "hideKeyboard")
    tapGesture.cancelsTouchesInView = true
    tableView.addGestureRecognizer(tapGesture)
}

func hideKeyboard() {
    tableView.endEditing(true)
}
StrangeCode
  • 193
  • 1
  • 10
3

override func viewDidLoad() { super.viewDidLoad()

    let tapGesture = UITapGestureRecognizer(target: self, action: Selector("hideKeyboard"))
    tapGesture.cancelsTouchesInView = true
    self.view.addGestureRecognizer(tapGesture)
}


func hideKeyboard()
{
    self.view.endEditing(true)
}

this will work fine compared to the above which didnt work for me

Ullas Pujary
  • 349
  • 4
  • 14
  • In what way does your answer differ from the accepted one? Despite it lacks some good formatting and detailed explanation? – Lepidopteron Jun 12 '17 at 07:33
1

Accepted answer doesn't work for me on XCode 13.1, so I changed the code a little bit:

override func viewDidLoad() {
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.hideKeyboard))
    tapGesture.cancelsTouchesInView = true
    tableView.addGestureRecognizer(tapGesture)
}

@objc func hideKeyboard() {
    tableView.endEditing(true)
}
Suprafen
  • 58
  • 3
  • 9