I have an action that creates an alert when the button is tapped.
This alert consists of two textfields and two actions (add and dismiss).
Is there any simple way for me to disable the add button if the textfields are empty (I'll later check if the second one is really an URL but let's keep things focused on the action here)?
Here is my code and what I tried so far:
#IBAction func addSourceTapped(_ sender: Any) {
let alert = UIAlertController(title: "Add a News Source", message: nil, preferredStyle: .alert)
alert.addTextField { (textField) in
textField.placeholder = "Name"
}
alert.addTextField { (textField) in
textField.placeholder = "Link"
}
let name = alert.textFields!.first!.text!
let link = alert.textFields!.last!.text!
if name != "" && link != "" {
alert.actions[0].isEnabled = true
}
let action = UIAlertAction(title: "Add", style: .default) { (_) in
let name = alert.textFields!.first!.text!
let link = alert.textFields!.last!.text!
if name != "" && link != "" {
alert.actions[0].isEnabled = true //doesn't do anything yet..
if CoreDataHandler.saveSource(name: "\(name)", link: "\(link)") {
for _ in CoreDataHandler.fetchSource()! {
}
}
}
self.tableView.reloadData()
}
let action2 = UIAlertAction(title: "Dismiss", style: .default)
alert.addAction(action)
alert.actions[0].isEnabled = false
alert.addAction(action2)
present(alert, animated: true, completion: nil)
}
You should better use actions, it's simpler than the other answers. If you try to use delegate, methods didBeginEditing & didEndEditing will not handle it correctly. Neither do shouldChangeCharactersIn range, it performs before the input occurs in textfield, so it's not correct to check textField's text property there.
private var action: UIAlertAction!
#IBAction func addSourceTapped(_ sender: Any) {
////////
let alert = UIAlertController(title: "Add a News Source", message: nil, preferredStyle: .alert)
alert.addTextField { (textField) in
textField.placeholder = "Name"
textField.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged) // <---
}
action = UIAlertAction(title: "Add", style: .default) { (_) in
/////
}
action.isEnabled = false
alert.addAction(action)
////////
}
#objc private func textFieldDidChange(_ field: UITextField) {
action.isEnabled = field.text?.count ?? 0 > 0
}
You can't write UITextField validating code (Code to enable/ disable Action) any where!!. This Validation must be done each time UItextfield update. So for doing that you need to get the delegate from UITextField for its updates
You need to save the textfield globally and assign delegate of textfields to your ViewController. By doing that you can code for validating code for textfields in your UIViewController and programmatically Enable or disable your actions
class YOUR_CLASS_NAME:UIViewController,UITextFieldDelegate {
var alert: UIAlertController!
var action: UIAlertAction!
var action2: UIAlertAction!
var nameTextFeld:UITextField!
var linkTextFeld:UITextField!
#IBAction func addSourceTapped(_ sender: Any) {
alert = UIAlertController(title: "Add a News Source", message: nil, preferredStyle: .alert)
alert.addTextField { (textField) in
self.nameTextFeld = textField
self.nameTextFeld.placeholder = "Name"
self.nameTextFeld.delegate = self
}
alert.addTextField { (textField) in
self.linkTextFeld = textField
self.linkTextFeld.placeholder = "Link"
self.linkTextFeld.delegate = self
}
action = UIAlertAction(title: "Add", style: .default) { (_) in
let name = self.alert.textFields!.first!.text!
let link = self.alert.textFields!.last!.text!
if CoreDataHandler.saveSource(name: "\(name)", link: "\(link)") {
for _ in CoreDataHandler.fetchSource()! {
}
}
self.tableView.reloadData()
}
action.isEnabled = false
action2 = UIAlertAction(title: "Dismiss", style: .default)
alert.addAction(action)
alert.actions[0].isEnabled = false
alert.addAction(action2)
present(alert, animated: true, completion: nil)
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if !((nameTextFeld.text?.isEmpty)! && (linkTextFeld.text?.isEmpty)!) {
action.isEnabled = true
}
return true
}
}
Do that by configuring the text field when adding it
alert.addTextField(configurationHandler: { (textField) -> Void in
textField.placeholder = "Name"
// Other configuration such as textField.autocapitalizationType = .words
NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextFieldTextDidChange, object: textField, queue: OperationQueue.main) { (notification) in
let nameField = alert.textFields![0] as UITextField
let linkField = alert.textFields![1] as UITextField
action.isEnabled = self.getTextFieldContent(nameField) != "" && self.getTextFieldContent(linkField) != ""
}
})
You need to do this separately for both text fields (though you could do that by reusing the same code). Note also, that if you reference the textfields directly in the action's handler block, it will create a strong reference cycle and your controller will not be deinited. To avoid that do the reference to the text field with a local nullable variable like this
var tf: UITextField?
let action = UIAlertAction(title: "Add", style: .default) { (_) in
guard let textField = tf else {
return;
}
let name = textField.text!
// Rest the action here
}
alertController.addTextField { (textField) in
// Configure textField here
tf = textField
}
Programmatic solution with the usage of the actions.
Add button to class and continue to change its status according to the change made in the text field.
import UIKit
final class ViewWithConfirmationController: UIViewController {
private let askButton = UIButton()
private let deleteAction = UIAlertAction(
title: "Confirm",
style: .default
) { _ in
// Confirmed
}
init() {
super.init(nibName: nil, bundle: nil)
view.addSubview(askButton)
askButton.setTitle("Call alert", for: .normal)
askButton.addTarget(
self,
action: #selector(callAlert),
for: .touchUpInside
)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
#objc func callAlert() {
let alert = UIAlertController(
title: "Confirmation alert",
message: """
Do you really want to do that?
Please type in the magic word to confirm.
""",
preferredStyle: .alert
)
alert.addTextField { textField in
textField.placeholder = "Magic word"
textField.addTarget(
self,
action: #selector(self.textFieldDidChange(_:)),
for: .editingChanged
)
}
alert.addAction(
UIAlertAction(
title: "Cancel",
style: .cancel,
handler: { _ in }
))
alert.addAction(deleteAction)
// Confirm button will disabled until user type current organisation name
deleteAction.isEnabled = false
present(alert, animated: true, completion: nil)
}
#objc private func textFieldDidChange(_ field: UITextField) {
guard let text = field.text else {
print("Can't get text from text field in \(#function)")
return
}
deleteAction.isEnabled = !text.isEmpty
}
}
Related
How to make if someone writes "admin,"(the password I want) in textfield, and clicks login, it checks if that is correct or not, for further functions based on results
class ViewController: UIViewController {
var name:String?
var login:String?
#objc private func openSecretMenu() {
let alert = UIAlertController(title: "Login", message: "password", preferredStyle: .alert)
// Login button
let loginAction = UIAlertAction(title: "Login", style: .default, handler: { (action) -> Void in
// Get TextFields text
let passwordTxt = alert.textFields![1]
//Asign textfileds text to our global varibles
self.login = passwordTxt.text
print("PASSWORD: \(self.login!)")
})
// Cancel button
let cancel = UIAlertAction(title: "Cancel", style: .destructive, handler: { (action) -> Void in })
//2nd textField for password
alert.addTextField { (textField: UITextField) in
textField.placeholder = "Enter password"
textField.isSecureTextEntry = false
}
// Add actions
alert.addAction(cancel)
alert.addAction(loginAction)
self.present(alert, animated: true, completion: nil)
}
}
}
You have a choice to validate user either with server-side or with static content.
class ViewController: UIViewController {
var name:String?
var login:String?
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton()
button.frame = CGRect(x: 32, y: self.view.frame.midY, width: self.view.frame.width - 64, height: 60)
button.addTarget(self, action: #selector(openSecretMenu), for: .touchUpInside)
button.setTitle("Open Popup", for: .normal)
button.backgroundColor = .green
button.titleLabel?.font = .boldSystemFont(ofSize: 21)
self.view.addSubview(button)
}
#objc private func openSecretMenu() {
let alert = UIAlertController(title: "Login", message: "password", preferredStyle: .alert)
// Login button
let loginAction = UIAlertAction(title: "Login", style: .default, handler: { (action) -> Void in
// Get TextFields text
let passwordTxt = alert.textFields![0]
//Asign textfileds text to our global varibles
self.login = passwordTxt.text
// api call for login with fetched password, then server will process
// if login success then you can move forward (push view controller) from here
// for static case
print("PASSWORD: \(self.login!)")
if self.login == "admin" {
print("succeed")
} else {
print("password not matched")
}
})
// Cancel button
let cancel = UIAlertAction(title: "Cancel", style: .destructive, handler: { (action) -> Void in })
//2nd textField for password
alert.addTextField { (textField: UITextField) in
textField.placeholder = "Enter password"
textField.isSecureTextEntry = false
}
// Add actions
alert.addAction(cancel)
alert.addAction(loginAction)
self.present(alert, animated: true, completion: nil)
}
}
The problem with UIAlertController is that it always closes if you press one of its buttons. Also the action callback isn't triggered until after the closing animation (~0.25s), which is annoying too.
So what happens is the user enters a password, presses send, the alert closes, after 0.25s the password gets actually checked. If it is wrong you could just show a new alert, but it's not ideal.
var textFD = UITextField.init()
var tempStr : String!
var datax = [Tasks]()
var tempArr = [NSManagedObject]()
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = UIBarButtonItem.init(title: "Add", style: UIBarButtonItemStyle.plain, target: self, action:#selector(myTableViewController.addFunc))
print("Hello")
fetchData()
}
func addFunc(){
let alertO = UIAlertController.init(title: "Add", message: "Add what you want", preferredStyle: .alert)
let saveAct=UIAlertAction.init(title: "Save", style: .default, handler:saveHandler)
let cancelAct=UIAlertAction.init(title: "Cancel", style: .default, handler: nil)
alertO.addAction(saveAct)
alertO.addAction(cancelAct)
alertO.addTextField(configurationHandler: { (textFD) in
textFD.placeholder="Hey therer"
print("textfd text1 is \n\n\n" ,textFD.text!)
self.tempStr=textFD.text!
})
print("textfd text2 is \n\n\n",textFD.text! )
self.present(alertO, animated: true, completion: nil)
self.tableView.reloadData()
self.tempStr=textFD.text!
}
func saveHandler(alert:UIAlertAction){
print("textfd text3 is \n\n\n",textFD.text! )
print("Value of tempStr \n\n ",tempStr)
let taskX = Tasks(context: context)
taskX.mydata = tempStr
appDelegate.saveContext()
self.tableView.reloadData()
print("Value of tempStr \n\n ",tempStr)
}
When i click on button addFunc will call for alert and from an textfield over alert controller , later the text of textfield is stored in a string .
Alertcontroller, textfield over alert and placeholder of textfield is appear but when i trying to store textfield text into a string ( tempStr )
it can't stored !
Property textFD of this class is not the one that shows on alertO, The configurationHandler of textField just provide a closure to help user customize textField on UIAlertController.
To get text of textField on UIAlertController, first you need use property textFields of UIAlertController instance to get which textFiled you want, then use .text to get text of this textFiled.
alertO.addTextField(configurationHandler: { (textFD) in
textFD.placeholder="Hey therer"
print("textfd text1 is \n\n\n" ,textFD.text!)
self.tempStr=textFD.text!
})
textfield is initializing with no text (blank default), tempStr is storing a blank value. you will have to save string on save action.
let saveAct = UIAlertAction.init(title: "Save", style: .default, handler:{
alertAction in
let textField = alertO.textFields![0] as UITextField
self.tempStr = textField.text
})
try this
EDIT
func addFunc(){
let alert = UIAlertController(title: "MESSAGE".localized, message: "ENTER_YOUR_MESSAGE".localized, preferredStyle: .alert)
alert.addTextField { (textField) in
// textField.placeholder = "Enter your message".localized
}
alert.addAction(UIAlertAction(title: "TITLE".localized, style: .default, handler: { (action:UIAlertAction!) in
let textField = alert.textFields![0] // Force unwrapping because we know it exists.
//print("Text field: \(String(describing: textField?.text))")
if (textField.text?.characters.count)! > 0
{
self.tempStr = textField.text
}
else
{
print("empty text")
}
}))
self.present(alert, animated: true, completion: nil)
}
I make an AlertViewController with textField that asks user to type a name of new item for data model.
So I want to keep submit button disabled while text field is empty. In other case, when I create #IBOutlet in ViewController for textfield from storyboard I could just use some methods from UITextFieldDelegate protocol and solve problem without your help.
But now I can't.
Register for the text field change notifications and validate the text fields there:
#IBAction func showAlert(sender: AnyObject) {
var alert = UIAlertController(title: "New user",
message: "Add a new user",
preferredStyle: .Alert)
let saveAction = UIAlertAction(title: "Save",
style: .Default) { (action: UIAlertAction!) -> Void in
println("do your stuff here")
}
saveAction.enabled = false
let cancelAction = UIAlertAction(title: "Cancel",
style: .Default) { (action: UIAlertAction!) -> Void in
}
alert.addTextFieldWithConfigurationHandler {
(textFieldName: UITextField!) in
textFieldName.placeholder = "Enter full name"
}
alert.addTextFieldWithConfigurationHandler {
(textFieldEmail: UITextField!) in
textFieldEmail.placeholder = "Enter valid email adress"
textFieldEmail.keyboardType = .EmailAddress
}
// adding the notification observer here
NSNotificationCenter.defaultCenter().addObserverForName(UITextFieldTextDidChangeNotification, object:alert.textFields?[0],
queue: NSOperationQueue.mainQueue()) { (notification) -> Void in
let textFieldName = alert.textFields?[0] as! UITextField
let textFieldEmail = alert.textFields![1] as! UITextField
saveAction.enabled = self.isValidEmail(textFieldEmail.text) && !textFieldName.text.isEmpty
}
NSNotificationCenter.defaultCenter().addObserverForName(UITextFieldTextDidChangeNotification, object:alert.textFields?[1],
queue: NSOperationQueue.mainQueue()) { (notification) -> Void in
let textFieldEmail = alert.textFields?[1] as! UITextField
let textFieldName = alert.textFields?[0] as! UITextField
saveAction.enabled = self.isValidEmail(textFieldEmail.text) && !textFieldName.text.isEmpty
}
alert.addAction(saveAction)
alert.addAction(cancelAction)
presentViewController(alert,
animated: true,
completion: nil)
}
// email validation code method
func isValidEmail(testStr:String) -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
if let emailTest = NSPredicate(format:"SELF MATCHES %#", emailRegEx) as NSPredicate? {
return emailTest.evaluateWithObject(testStr)
}
return false
}
New Swift 4.2 Update
NotificationCenter.default.addObserver(
forName: UITextField.textDidChangeNotification,
object: alert.textFields?.first,
queue: .main) { (notification) -> Void in
guard let textFieldText = alert.textFields?.first?.text else { return }
saveAction.enabled = self.isValidEmail(textFieldText) && !textFieldText.isEmpty
}
add this code in viewDidLoad method
let notificationCenter = NSNotificationCenter.defaultCenter()
notificationCenter.addObserver(
self,
selector: "textFieldTextChanged:",
name:UITextFieldTextDidChangeNotification,
object: nil
)
and this method in ViewController
func textFieldTextChanged(sender : AnyObject) {
//your code
}
I have alert, that write to iOS 8+, I must write same alert to the iOS 7.0 (I'm use four alert's with other request)
There are my code:
func AlertForNumber () {
var alertController: UIAlertController?
//
alertController = UIAlertController(title: "First", message: "Enter number", preferredStyle: .Alert)
alertController!.addTextFieldWithConfigurationHandler({(textField: UITextField!) in
textField.text = "38"
})
let action = UIAlertAction(title: "Next", style: UIAlertActionStyle.Default, handler: {[weak self]
(paramAction: UIAlertAction!) in
if let textFields = alertController?.textFields {
let textFields = textFields as! [UITextField]
let enterText = textFields[0].text
if (count(enterText) < 12){
self?.ErrorForNumber()
} else {
self!.data.numberID = enterText
self!.data.SaveData(enterText, codetext: self!.data.codeID)
self!.json.UfR()
}
}
})
alertController?.addAction(action)
dispatch_async(dispatch_get_main_queue(), {
self.presentViewController(alertController!, animated: true, completion: nil)
})
}
At that alert I must input my number, and send to the server.
I must use only alert with text field
After I must input code at next alert:
func AlertForCode () {
var alertController: UIAlertController?
alertController = UIAlertController(title: "Second", message: "Enter code", preferredStyle: .Alert)
alertController!.addTextFieldWithConfigurationHandler({(textField: UITextField!) in
textField.placeholder = code_text
})
let action = UIAlertAction(title: "Next", style: UIAlertActionStyle.Default, handler: {[weak self]
(paramAction: UIAlertAction!) in
if let textFields = alertController?.textFields {
let textFields = textFields as! [UITextField]
let enterText = textFields[0].text
self!.data.codeID = enterText
self!.data.SaveData(self!.data.numberID, codetext: enterText)
self!.json.UfR()
}
})
alertController?.addAction(action)
dispatch_async(dispatch_get_main_queue(), {
self.presentViewController(alertController!, animated: true, completion: nil)
})
}
So that I must write to the iOS 7.0
func AlertForNumber () {
let alertView = UIAlertView(title: "First", message: "Enter number", delegate: self, cancelButtonTitle: "Next")
alertView.alertViewStyle = UIAlertViewStyle.PlainTextInput
alertView.textFieldAtIndex(0)?.text = "38"
alertView.show()
}
func alertView(alertView: UIAlertView, clickedButtonAtIndex buttonIndex: Int) {
println("next")
let enterText = alertView.textFieldAtIndex(0)!.text
if (count(enterText) < 12){
self?.ErrorForNumber()
} else {
self!.data.numberID = enterText
self!.data.SaveData(enterText, codetext: self!.data.codeID)
self!.json.UfR()
}
}
I have an AlertController with a text field and two button: CANCEL and SAVE. This is the code:
#IBAction func addTherapy(sender: AnyObject)
{
let addAlertView = UIAlertController(title: "New Prescription", message: "Insert a name for this prescription", preferredStyle: UIAlertControllerStyle.Alert)
addAlertView.addAction(UIAlertAction(title: "Cancel",
style: UIAlertActionStyle.Default,
handler: nil))
addAlertView.addAction(UIAlertAction(title: "Save",
style: UIAlertActionStyle.Default,
handler: nil))
addAlertView.addTextFieldWithConfigurationHandler({textField in textField.placeholder = "Title"})
self.presentViewController(addAlertView, animated: true, completion: nil)
}
What I want to do is implement a check on the textfield for disabling the SAVE button when the textfield is empty just like Pictures Application of iOS when you want create a NewAlbum. Please someone can explain me what to do?
There is a much simpler way without using notification center, in swift:
weak var actionToEnable : UIAlertAction?
func showAlert()
{
let titleStr = "title"
let messageStr = "message"
let alert = UIAlertController(title: titleStr, message: messageStr, preferredStyle: UIAlertControllerStyle.alert)
let placeholderStr = "placeholder"
alert.addTextField(configurationHandler: {(textField: UITextField) in
textField.placeholder = placeholderStr
textField.addTarget(self, action: #selector(self.textChanged(_:)), for: .editingChanged)
})
let cancel = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: { (_) -> Void in
})
let action = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: { (_) -> Void in
let textfield = alert.textFields!.first!
//Do what you want with the textfield!
})
alert.addAction(cancel)
alert.addAction(action)
self.actionToEnable = action
action.isEnabled = false
self.present(alert, animated: true, completion: nil)
}
func textChanged(_ sender:UITextField) {
self.actionToEnable?.isEnabled = (sender.text! == "Validation")
}
I would first create the alertcontroller with the save action initially disabled. Then when adding the textfield inculde a Notification to observe its change in the handler and in that selector just toggle the save actions enabled property.
Here is what I am saying:
//hold this reference in your class
weak var AddAlertSaveAction: UIAlertAction?
#IBAction func addTherapy(sender : AnyObject) {
//set up the alertcontroller
let title = NSLocalizedString("New Prescription", comment: "")
let message = NSLocalizedString("Insert a name for this prescription.", comment: "")
let cancelButtonTitle = NSLocalizedString("Cancel", comment: "")
let otherButtonTitle = NSLocalizedString("Save", comment: "")
let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
// Add the text field with handler
alertController.addTextFieldWithConfigurationHandler { textField in
//listen for changes
NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleTextFieldTextDidChangeNotification:", name: UITextFieldTextDidChangeNotification, object: textField)
}
func removeTextFieldObserver() {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UITextFieldTextDidChangeNotification, object: alertController.textFields[0])
}
// Create the actions.
let cancelAction = UIAlertAction(title: cancelButtonTitle, style: .Cancel) { action in
NSLog("Cancel Button Pressed")
removeTextFieldObserver()
}
let otherAction = UIAlertAction(title: otherButtonTitle, style: .Default) { action in
NSLog("Save Button Pressed")
removeTextFieldObserver()
}
// disable the 'save' button (otherAction) initially
otherAction.enabled = false
// save the other action to toggle the enabled/disabled state when the text changed.
AddAlertSaveAction = otherAction
// Add the actions.
alertController.addAction(cancelAction)
alertController.addAction(otherAction)
presentViewController(alertController, animated: true, completion: nil)
}
//handler
func handleTextFieldTextDidChangeNotification(notification: NSNotification) {
let textField = notification.object as UITextField
// Enforce a minimum length of >= 1 for secure text alerts.
AddAlertSaveAction!.enabled = textField.text.utf16count >= 1
}
I am doing this in another project - I got this pattern directly from apple examples. They have a very good example project outlining a few of these patterns in the UICatalog examples: https://developer.apple.com/library/content/samplecode/UICatalog/Introduction/Intro.html
Swift 3.0 Updated Solution given By #spoek
func showAlert()
{
let titleStr = "title"
let messageStr = "message"
let alert = UIAlertController(title: titleStr, message: messageStr, preferredStyle: UIAlertControllerStyle.alert)
let placeholderStr = "placeholder"
alert.addTextField(configurationHandler: {(textField: UITextField) in
textField.placeholder = placeholderStr
textField.addTarget(self, action: #selector(self.textChanged(_:)), for: .editingChanged)
})
let cancel = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: { (_) -> Void in
})
let action = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: { (_) -> Void in
let textfield = alert.textFields!.first!
//Do what you want with the textfield!
})
alert.addAction(cancel)
alert.addAction(action)
self.actionToEnable = action
action.isEnabled = false
self.present(alert, animated: true, completion: nil)
}
func textChanged(_ sender:UITextField) {
self.actionToEnable?.isEnabled = (sender.text! == "Validation")
}
I implemented a subclass of UIAlertController for conveniently adding text fields and associated enabling and disabling of buttons. The basic logic is similar to that Sourabh Sharma but everything is encapsulated in this subclass for tidiness. This should be helpful if your project involves a lot of such alert functionalities.
public class TextEnabledAlertController: UIAlertController {
private var textFieldActions = [UITextField: ((UITextField)->Void)]()
func addTextField(configurationHandler: ((UITextField) -> Void)? = nil, textChangeAction:((UITextField)->Void)?) {
super.addTextField(configurationHandler: { (textField) in
configurationHandler?(textField)
if let textChangeAction = textChangeAction {
self.textFieldActions[textField] = textChangeAction
textField.addTarget(self, action: #selector(self.textFieldChanged), for: .editingChanged)
}
})
}
#objc private func textFieldChanged(sender: UITextField) {
if let textChangeAction = textFieldActions[sender] {
textChangeAction(sender)
}
}
}
To use it, just provide a textChangeAction block when adding the text fields:
alert.addTextField(configurationHandler: { (textField) in
textField.placeholder = "Your name"
textField.autocapitalizationType = .words
}) { (textField) in
saveAction.isEnabled = (textField.text?.characters.count ?? 0) > 0
}
For the full example, see the git page.