hello guys I want to ask I want to select row in tableview section, when I select row of section it will show an alertController. but it not showing, I have another method in section 0 and it work but why it's not work in section I want to select. can you help me?
func numberOfSections(in tableView: UITableView) -> Int {
return 5
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 0 {
let selectSchoolVC = SelectSchoolPopUpVC()
selectSchoolVC.modalPresentationStyle = .fullScreen
selectSchoolVC.modalTransitionStyle = .crossDissolve
present(selectSchoolVC, animated: true, completion: nil)
} else if indexPath.section == 1 {
} else if indexPath.section == 2 {
} else if indexPath.section == 3 {
}
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Log Out", style: .destructive, handler: { (_) in
ProfileServices.shared.signOutUser()
let signInVC = SigninViewController()
let navController = UINavigationController(rootViewController: signInVC)
self.present(navController, animated: true)
}))
tableView.deselectRow(at: indexPath, animated: true)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "selectId", for: indexPath) as! SelectSchoolCell
return cell
} else if indexPath.section == 1 {
return UITableViewCell()
} else if indexPath.section == 2 {
let cell = tableView.dequeueReusableCell(withIdentifier: "BadgedCell", for: indexPath) as! BadgeCell
cell.accessoryType = .disclosureIndicator
let item = infoArray[indexPath.row]
cell.nameLbl.text = item["title"]
cell.badgeString = item["badge"] ?? ""
cell.badgeTextColor = .white
cell.badgeColor = .red
return cell
} else if indexPath.section == 3 {
let cell = tableView.dequeueReusableCell(withIdentifier: "helpId", for: indexPath)
let helpsArray = helpArray[indexPath.row]
cell.textLabel?.text = helpsArray
cell.textLabel?.textColor = #colorLiteral(red: 0.2, green: 0.2, blue: 0.2, alpha: 1)
cell.textLabel?.font = UIFont(name: "NunitoSans-SemiBold", size: 16)
cell.accessoryType = .disclosureIndicator
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "signOutId", for: indexPath)
return cell
}
You never actually present the alert:
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Log Out", style: .destructive, handler: { (_) in
ProfileServices.shared.signOutUser()
let signInVC = SigninViewController()
let navController = UINavigationController(rootViewController: signInVC)
self.present(navController, animated: true)
}))
You need to present the alert here, by doing something like:
self.present(alert, animated: true)
self.navigationController?.present(alert, animated: true, completion: nil)
You have created an instance of UIAlertController but didn't present it anywhere. You should've presented that. Try,
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 0 {
let selectSchoolVC = SelectSchoolPopUpVC()
selectSchoolVC.modalPresentationStyle = .fullScreen
selectSchoolVC.modalTransitionStyle = .crossDissolve
present(selectSchoolVC, animated: true, completion: nil)
} else if indexPath.section == 1 {
} else if indexPath.section == 2 {
} else if indexPath.section == 3 {
}
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Log Out", style: .destructive, handler: { (_) in
ProfileServices.shared.signOutUser()
let signInVC = SigninViewController()
let navController = UINavigationController(rootViewController: signInVC)
self.present(navController, animated: true)
}))
self.present(alert, animated: true)
tableView.deselectRow(at: indexPath, animated: true)
}
You need to present your alert controller in didSelect at the end
self.present(alert, animated: true)
tableView.deselectRow(at: indexPath, animated: true)
Related
I have created an alert view that shows up with a text field. I want to be able to change the placeholder of the text field to "Enter something here" when user clicks on the "Add Item" button if the string entered is empty. Any idea how to achieve this effect?
This is my code:
import UIKit
class TodoListViewController: UITableViewController {
var itemArray = ["A", "B", "C"]
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white, .font: UIFont.systemFont(ofSize: 25, weight: .bold)]
self.navigationController?.view.backgroundColor = UIColor(red: 0.29, green: 0.63, blue: 0.82, alpha: 1)
}
//MARK: - TableView DataSource Methods
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ToDoItemCell", for: indexPath)
cell.textLabel?.text = itemArray[indexPath.row]
return cell
}
//MARK: - TableView Delegate Methods
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView.cellForRow(at: indexPath)?.accessoryType == .checkmark{
tableView.cellForRow(at: indexPath)?.accessoryType = .none
} else {
tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}
tableView.deselectRow(at: indexPath, animated: true)
}
//MARK: - Add New Items
#IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
var textField = UITextField()
let alert = UIAlertController(title: "Add New Item:", message: "", preferredStyle: .alert)
let action = UIAlertAction(title: "Add Item", style: .default) { action in
if textField.text != "" {
self.itemArray.append(textField.text!)
self.tableView.reloadData()
} else {
//change name of placeholder here
}
}
alert.addTextField { alertTextField in
alertTextField.placeholder = "Create new item"
textField = alertTextField
}
alert.addAction(action)
present(alert, animated: true, completion: nil)
}
}
Get the textfield from the alert
} else {
alert.textFields?.first?.placeholder = "Enter something here"
}
but you have to again present the alert controller.
Like this
let alert = UIAlertController(title: "Add New Item:", message: "", preferredStyle: .alert)
#IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
var textField = UITextField()
let action = UIAlertAction(title: "Add Item", style: .default) { action in
if textField.text != "" {
self.itemArray.append(textField.text!)
self.tableView.reloadData()
} else {
alert.textFields?.first?.placeholder = "Enter something here"
present(alert, animated: true, completion: nil)
}
}
alert.addTextField { alertTextField in
alertTextField.placeholder = "Create new item"
textField = alertTextField
}
alert.addAction(action)
present(alert, animated: true, completion: nil)
}
Code Below doesn't result in Logout Button to Work, what is wrong?!?
import UIKit
import FirebaseAuth
class ProfileViewController: UIViewController {
// Set Log Out Button
#IBOutlet var tableView: UITableView!
// Data option
let data = ["Log Out"]
// Supply Data Source and Delegate Self
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.delegate = self
tableView.dataSource = self
}
}
// Add an externsion to inform Data Source and Delegate
extension ProfileViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
// Deque row and style text
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = data[indexPath.row]
cell.textLabel?.textAlignment = .center
cell.textLabel?.textColor = .red
return cell
}
// Make logout to occur when user log outs - unhighlight cell
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
// Create an alert to Log Out
let actionsheet = UIAlertController(title: "",
message: "",
preferredStyle: .actionSheet)
actionsheet.addAction(UIAlertAction(title: "Log Out",
style: .destructive,
handler: { [weak self] _ in
guard let strongSelf = self else {
return
}
do {
try FirebaseAuth.Auth.auth().signOut()
let vc = LogInViewController()
let nav = UINavigationController(rootViewController: vc)
nav.modalPresentationStyle = .fullScreen
strongSelf.present(nav, animated: true)
}
catch {
print("Failed to log out")
}
}))
actionsheet.addAction(UIAlertAction(title: "Cancel",
style: .cancel,
handler: nil))
present(actionsheet, animated: true)
}
}
Seems like you have used didDeselectRowAt instead of didSelectRowAt. didSelectRowAt is what gets called when user taps on cell and selects it, didDeselectRowAt gets called when cell is deselected.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let actionsheet = UIAlertController(title: "",
message: "",
preferredStyle: .actionSheet)
actionsheet.addAction(UIAlertAction(title: "Log Out",
style: .destructive,
handler: { [weak self] _ in
guard let strongSelf = self else {
return
}
do {
try FirebaseAuth.Auth.auth().signOut()
let vc = LogInViewController()
let nav = UINavigationController(rootViewController: vc)
nav.modalPresentationStyle = .fullScreen
strongSelf.present(nav, animated: true)
}
catch {
print("Failed to log out")
}
}))
actionsheet.addAction(UIAlertAction(title: "Cancel",
style: .cancel,
handler: nil))
present(actionsheet, animated: true)
}
How can I change the title of an UIAlertAction when I click the button ?
I want to click that button and from "Enable" to make it "Disable" for example.
I spent a lot of time trying to achieve this but I can't manage to do it.
Here is a small Demo with my issue: https://github.com/tygruletz/ChangeTitleOfAlertAction
Here is my code:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
tableView.tableFooterView = UIView()
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "Row \(indexPath.row)"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
showOptions()
}
func showOptions(){
var enable = "Enable"
let disable = "Disable"
let applyOn = UIAlertAction(title: enable, style: .default, handler: { (action: UIAlertAction!) in
enable = disable
})
let actionSheet = configureActionSheet()
actionSheet.addAction(applyOn)
self.present(actionSheet, animated: true, completion: nil)
}
func configureActionSheet() -> UIAlertController {
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
actionSheet.addAction(cancel)
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad ){
actionSheet.popoverPresentationController?.sourceView = self.view
actionSheet.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
actionSheet.popoverPresentationController?.permittedArrowDirections = []
}
return actionSheet
}
}
And here is a capture of screen:
Thank you if you try to help me !
Please follow below code:
Define property in your UIViewController
var selectedIndexPath:IndexPath!
Add argument in showOptions method
func showOptions(indexPath:IndexPath){
var status = "Enable"
if selectedIndexPath == indexPath{
status = "Disable"
}
let applyOn = UIAlertAction(title: status, style: .default, handler: { (action: UIAlertAction!) in
if self.selectedIndexPath == indexPath{
self.selectedIndexPath = nil
}else{
self.selectedIndexPath = indexPath
}
})
let actionSheet = configureActionSheet()
actionSheet.addAction(applyOn)
self.present(actionSheet, animated: true, completion: nil)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
showOptions(indexPath: indexPath)
}
Note:
If you are going with this approach, Then you will never faced cell usability issue.
When I select a table row and click 'Ok' under city tab, it is highlighting the row but when I change the tab to town, it is highlighting the same row in the town tab even though I did not select it.That is if I highlight second and third row under city tab, it is highlighting second and third row under town tab as well without me doing anything. Following is my code
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let myCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CityCell
switch (segCtrl.selectedSegmentIndex)
{
case 0:
myCell.myLabel.text = cityName[indexPath.row]
break
case 1:
myCell.myLabel.text = townName[indexPath.row]
break
default:break
}
return myCell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
let cell = tableView.cellForRow(at: indexPath)!
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
let ok = UIAlertAction(title: "Ok", style: .default, handler: { (action) -> Void in
let cell = tableView.cellForRow(at: indexPath)!
cell.backgroundColor = UIColor(white: 1.0, alpha:0.5)
})
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Void in
})
alertController.addAction(ok)
alertController.addAction(cancel)
present(alertController, animated: true, completion: nil)
}
How do I prevent this highlighting from happening in next tab and confine it to where I actually selected the row?
I'm working with objective-c. So, sorry if my swift code is wrong.
// global variable which carry selection-indexPath
var citySelectedIndexPaths = [IndexPath]()
var townSelectedIndexPaths = [IndexPath]()
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let myCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CityCell
// add this line
myCell.backgroundColor = UIColor(white: 1.0, alpha:1.0) // default color
switch (segCtrl.selectedSegmentIndex)
{
case 0:
myCell.myLabel.text = cityName[indexPath.row]
if citySelectedIndexPaths.contains(indexPath) {
myCell.backgroundColor = UIColor(white: 1.0, alpha:0.5)
}
break
case 1:
myCell.myLabel.text = townName[indexPath.row]
if townSelectedIndexPaths.contains(indexPath) {
myCell.backgroundColor = UIColor(white: 1.0, alpha:0.5)
}
break
default:break
}
return myCell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
let cell = tableView.cellForRow(at: indexPath)!
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
let ok = UIAlertAction(title: "Ok", style: .default, handler: { (action) -> Void in
let cell = tableView.cellForRow(at: indexPath)!
cell.backgroundColor = UIColor(white: 1.0, alpha:0.5)
// save selection indexPath
switch (segCtrl.selectedSegmentIndex)
{
case 0:
if citySelectedIndexPaths.contains(indexPath) {
let indexValue = citySelectedIndexPaths.indexOf(indexPath)
citySelectedIndexPaths.removeAtIndex(indexValue)
} else {
citySelectedIndexPaths.append(indexPath);
}
break
case 1:
if townSelectedIndexPaths.contains(indexPath) {
let indexValue = townSelectedIndexPaths.indexOf(indexPath)
townSelectedIndexPaths.removeAtIndex(indexValue)
} else {
townSelectedIndexPaths.append(indexPath);
}
break
default:break
}
})
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Void in
})
alertController.addAction(ok)
alertController.addAction(cancel)
present(alertController, animated: true, completion: nil)
}
Now in your code, you set background manually.
cell.backgroundColor = UIColor(white: 1.0, alpha:0.5)
But you did not reset cell.backgroundColor after you select other cell. So you need to store current selected cell's indexPath and call reloadData each time you select new cell in ok UIAlertAction. In cellForRowAtIndexPath, just perform cell with selected or unselected stage.
I have a UITableView and when I add data, it will only allow me to add one row in the UITableview even though I return goals.count for the amount of rows.
This is what I have.
#IBAction func myAddGoal(sender: AnyObject) {
let ac = UIAlertController(title: "Enter a Goal", message: "It can be anything you want!", preferredStyle: .Alert)
ac.addTextFieldWithConfigurationHandler(nil)
let submit = UIAlertAction(title: "Submit", style: .Default) { [unowned self, ac] (action: UIAlertAction!) in
let goal = ac.textFields![0] as UITextField
self.submitGoal(goal.text)
}
ac.addAction(submit)
ac.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Destructive, handler: nil))
presentViewController(ac, animated: true, completion: nil)
}
func submitGoal(goal: String){
if goal == "" {
println("textfield is empty")
} else {
goals.insert(goal, atIndex: 0)
let indexPath = NSIndexPath(forRow: 0, inSection: 0)
myTableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
println(goals)
}
}
I am able to add only ONE goal and it will animate into the UITableView. If I want to add another goal, it will not let me. The app crashes when I hit submit for a second goal entry.
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return goals.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let object = goals[indexPath.row]
cell.textLabel!.text = object
mySwitch.on = false
mySwitch.tag = indexPath.row as Int
mySwitch.addTarget(self, action: "UISwitchUpdated", forControlEvents: UIControlEvents.TouchUpInside)
cell.selectionStyle = .None
cell.accessoryView = mySwitch
return cell
}