I want to have a table view, where you can add a new element when you click on the last cell. I can't find out, how I save whats put in the textfield, after you click "ok".
As you can probably see from my code, I'm very new to programming and it is likely way to complicated. It would be super cool, if someone could help me out.
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var companyTableView: UITableView!
var psgTextField: UITextField?
var emTextField: UITextField?
var passengers = [""]
var button: UILabel?
override func viewDidLoad() {
super.viewDidLoad()
configureButton()
companyTableView.delegate = self
companyTableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return passengers.count
}
#objc func buttonTapped(sender: UITapGestureRecognizer) {
let alertController = UIAlertController(title: "Enter name and email",
message: nil,
preferredStyle: .alert)
alertController.addTextField(configurationHandler: psgTextField)
alertController.addTextField(configurationHandler: emTextField)
let okAction = UIAlertAction(title: "Submit", style: .default, handler: self.okHandler)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alertController.addAction(okAction)
alertController.addAction(cancelAction)
self.present(alertController, animated: true)
}
func psgTextField(textField: UITextField!) {
psgTextField = textField
psgTextField?.placeholder = "Name"
}
func emTextField(textField: UITextField!) {
emTextField = textField
emTextField?.placeholder = "Email"
}
func okHandler(alert: UIAlertAction!) {
let psgStr = (psgTextField?.text)!
passengers.removeLast()
passengers.append(psgStr)
passengers.append("")
}
func configureButton() {
button = UILabel()
let frame = CGRect(x: 0, y: 5, width: 300, height: 30)
button?.frame = frame
button?.text = " Add Passenger"
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(buttonTapped(sender:)))
button?.addGestureRecognizer(tapGesture)
button?.isUserInteractionEnabled = true
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let passenger = passengers[indexPath.row]
if let cell = companyTableView.dequeueReusableCell(withIdentifier: "cell") {
cell.textLabel?.text = passenger
if cell.textLabel?.text == "" {
cell.contentView.addSubview(button!)
} else {
// Nothing
}
return cell
}
return UITableViewCell()
}
}
When I now click on "Submit", the alert just goes of and nothing changed.
You need to call companyTableView.reloadData() in your okHandler method.
Related
I want to make some blog or forum app.I made a home page to see other users's posts.I used tableview and prototype cell to do that.But when i run my app, i can not see all my items in my prototype cell.And they seem like default cells but they are not.I debugged it with changing cell's background color.I can see it but not completely true.
Here is my Home Page View Controller
import UIKit
import Parse
class FeedViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var postDizisi = [Post]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
verileriAl()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return postDizisi.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "protCell", for: indexPath) as! FeedTableViewCell
cell.textView.text = postDizisi[indexPath.row].content
cell.usernameLabel.text = postDizisi[indexPath.row].username
return cell
}
#objc func verileriAl() {
print("done")
let query = PFQuery(className: "Post")
query.addDescendingOrder("createdAt")
query.findObjectsInBackground { (objects, error) in
if error != nil {
self.createAlert(title: "HATA", message: error?.localizedDescription ?? "HATA")
}else {
if objects!.count > 0 {
self.postDizisi.removeAll(keepingCapacity: false)
for object in objects! {
if let username = object.object(forKey: "username") as? String {
if let userContent = object.object(forKey: "content") as? String {
let post = Post(username: username, content: userContent)
self.postDizisi.append(post)
}
}else {
print("hata aldık")
}
}
self.tableView.reloadData()
}
}
}
}
func createAlert(title : String , message : String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert)
let okBut
ton = UIAlertAction(title: "OK", style: UIAlertAction.Style.default)
alert.addAction(okButton)
present(alert, animated: true)
}
override func viewWillAppear(_ animated: Bool) {
NotificationCenter.default.addObserver(self, selector: #selector(verileriAl), name: NSNotification.Name(rawValue: "veriGirildi"), object: nil)
}
}
Here is my upload View Controller
import UIKit
import Parse
class UploadViewController: UIViewController {
#IBOutlet weak var shareButton: UIButton!
#IBOutlet weak var usernameLabel: UILabel!
#IBOutlet weak var postTextView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
usernameLabel.text = PFUser.current()?.username
}
#IBAction func shareButtonClicked(_ sender: Any) {
let post = PFObject(className: "Post")
if PFUser.current() != nil {
post["username"] = PFUser.current()?.username
post["content"] = postTextView.text
post.saveInBackground { (success, error) in
if error != nil {
let alert = UIAlertController(title: "HAT", message: error?.localizedDescription ?? "HATA", preferredStyle: UIAlertController.Style.alert)
let okButton = UIAlertAction(title: "OK", style: UIAlertAction.Style.default)
alert.addAction(okButton)
self.present(alert, animated: true)
}else {
self.postTextView.text = ""
self.tabBarController?.selectedIndex = 0
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "veriGirildi"), object: nil)
}
}
}
}
}
I want to see like this
But when i runned my app it seems like this
Atil and ibrahimmbyrrm is just usernameLabel contents.Why it doesn't display other items on prototype cell
I want to see other users's posts on Home Page but my cell doesn't work successfully.I need help to fix it.I have this problem at all my projects.
My table tap gesture recogniser calls a method that displays a message informing that no row values are present, and some should be added. This happens when user touches anywhere inside the table view.
The error is in tableTapped inside the if let statement.
I've tried deleting and recreating the tableView in story builder. Also tried 'homework' instead of 'tableView' and the parameter name. Also tried removing 'self.' before 'tableView'.
I have this exact same method on another class, and it works fine so I guess there's something different about the class it's not working in. I just can't pinpoint it!
import UIKit
class homeworkViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var clear: UIButton!
#IBOutlet weak var all: UIButton!
#IBOutlet weak var chosen: UIButton!
var languages = [String]()
var chosenLanguage = String()
var chosenLanguageRemoved = false
var homeworkWords = [String]()
var chosenLanguageEnabled = false
let wordString = "words"
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .play, target: self, action: #selector(test))
let tap = UITapGestureRecognizer(target: self, action: #selector(tableTapped))
self.tableView.backgroundView = UIView()
self.tableView.backgroundView?.addGestureRecognizer(tap)
// Do any additional setup after loading the view.
}
#objc func tableTapped(tap:UITapGestureRecognizer) {
let location = tap.location(in: self.tableView)
let path = self.tableView.indexPathForRow(at: location)
if let indexPathForRow = path {
self.tableView(self.tableView, didSelectRowAt: indexPathForRow)
} else {
if homeworkWords.isEmpty == true {
let ac = UIAlertController(title: "Add Homework!", message: nil, preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default)
ac.addAction(okAction)
present(ac, animated: true)
}
}
}
#IBAction func chosen(_ sender: UIButton) {
let ac = UIAlertController(title: "Use Chosen Language", message: "Add or clear choosen language words to quickly set homework.", preferredStyle: .alert)
// add user actions, "Cancel" to abort
if chosenLanguageEnabled == false {
ac.addAction(UIAlertAction(title: "Set", style: .default, handler: chosenLanguage))
}
if chosenLanguageEnabled == true {
ac.addAction(UIAlertAction(title: "Clear", style: .default, handler: clearChosenLanguage))
}
ac.addAction(UIAlertAction(title: "Cancel", style: .cancel))
}
func chosenLanguage(action: UIAlertAction!) {
homeworkWords.removeAll()
if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {
if var savedWords = defaults.object(forKey: "\(chosenLanguage)\(wordString)") as? [String] {
print("savedWords in chosenLanguage in homeworkViewController are: \(savedWords)")
homeworkWords = savedWords
saveWords()
savedWords.removeAll()
chosenLanguageEnabled = true
print("chosenLanguageEnabled in chosenLanguage method in homeworkViewController is: \(chosenLanguageEnabled)")
print("homeworkWords in chosenLanguage method in homeworkViewController are: \(homeworkWords)")
print("savedWords after clear all in chosenLanguage method in homeworkViewController are: \(savedWords)")
}
}
}
func clearChosenLanguage(action: UIAlertAction!) {
homeworkWords.removeAll()
saveWords()
chosenLanguageEnabled = false
}
#IBAction func allWords(_ sender: UIButton) {
homeworkWords.removeAll()
for language in languages {
if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {
if var savedWords = defaults.object(forKey: "\(language)\(wordString)") as? [String] {
print("savedWords array is: \(savedWords)")
homeworkWords.append(contentsOf: savedWords)
saveWords()
savedWords.removeAll()
print("allWords method homeworkWords are: \(homeworkWords)")
print("allWords savedWords after clear all: \(savedWords)")
}
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .default, title: "Delete") { (action, indexPath) in
self.homeworkWords.remove(at: indexPath.row)
self.saveWords()
tableView.beginUpdates()
tableView.deleteRows(at: [indexPath], with: .left)
tableView.endUpdates()
// delete item at indexPath
if self.homeworkWords.isEmpty == true {
self.clear.isEnabled = false
self.clear.alpha = 0.25
}
}
delete.backgroundColor = UIColor.red
if let cell = tableView.cellForRow(at: indexPath) {
cell.isHighlighted = true
}
return [delete]
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//print("In cellForRowAt function")
let cell = tableView.dequeueReusableCell(withIdentifier: "homework", for: indexPath)
let word = homeworkWords[indexPath.row]
cell.textLabel?.text = word.capitalized
//print(cell)
return cell
}
func loadHomeworkWords() {
if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {
if var savedHomeWorkWords = defaults.object(forKey: "homeworkWords") as? [String] {
print("savedLanguages array is: \(savedHomeWorkWords)")
homeworkWords.removeAll()
homeworkWords = savedHomeWorkWords
savedHomeWorkWords.removeAll()
print("savedHomeWorkWords after removeAll: \(savedHomeWorkWords)")
print("loadHomeworkWords homeworkWords are: \(homeworkWords)")
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadHomeworkWords()
tableView.reloadData()
}
func saveWords() {
if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {
defaults.set(homeworkWords, forKey: "homeworkWords")
print("saveWords homeworkWords homeworkViewController are: \(homeworkWords)")
}
}
}
I expect to see a UIAlertAction message telling the user they need to add some table row values by tapping on either the 'All words' button or 'chosen language' button, if there are no values in any of the table rows.
Instead I get the pre-compile error message:
Cannot call value of non-function type 'UITableView?'
I want to be able to present a UIAlertAction when the user taps a UINavigationController UINavigationTabBar Item to remind them they need to enter some information before they can proceed to the next UIViewController that would otherwise be called from such a tap. The code that is called from the tap would check if an array is empty, if so, then display the UIAlertAction.
I've tried to create an instance of the UINavigationController's UINavigationTabBar item, to try and detect it being pushed, but this is messy as the UIViewController to be called has already been setup as a segue when the UINavigationTabBar item is tapped.
Do I need to backtrack and remove the existing segue and create the transition in a different way that allows my desired array checking code to be callable on the user's tap?
If you're pushing the next view controller using a segue, you would intercept that segue, do all your checks, and then inform the segue whether to go on or cancel the pushing. Basically in your view controller:
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
if identifier == "NextViewControllerID" {
var isValid = true
// example of validation, do your stuff here
if myTextField.text?.count ?? 0 < 5 {
isValid = false
}
return isValid
}
// otherwise delegates the superclass
return super.shouldPerformSegue(withIdentifier: identifier, sender: sender)
}
import UIKit
class WordsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
// write button selector method to check if there are any words.
var words = [String]()
var languages = [String]()
var chosenLanguage = String()
var textField: UITextField?
let wordString = "Words"
override func viewDidLoad() {
super.viewDidLoad()
chosenLanguageLoad()
loadInitialValues()
//let titleAttributes = [NSAttributedString.Key.font: UIFont(name: "AmericanTypewriter", size: 22)!]
//navigationController?.navigationBar.titleTextAttributes = titleAttributes
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .play, target: self, action: #selector(test))
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addNewWord))
print("languages array is: \(languages)")
}
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
if identifier == "Words" {
print("inside identifier == words if")
var isValid = true
if languages.isEmpty == true {
print("languages is empty is true")
isValid = false
}
return isValid
}
// otherwise delegates the superclass
return super.shouldPerformSegue(withIdentifier: identifier, sender: sender)
}
#objc func test() {
if words.isEmpty == true {
let ac = UIAlertController(title: "Add Some Words", message: nil, preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default)
ac.addAction(okAction)
present(ac, animated: true)
} else {
self.performSegue(withIdentifier: "Test", sender: self)
}
}
func chosenLanguageLoad() {
if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.polyglot") {
if let loadChosenLanguage = defaults.object(forKey: "languageChosen") as? String {
chosenLanguage = loadChosenLanguage
print("Chosen language is: \(chosenLanguage)")
}
}
}
#objc func loadInitialValues() {
if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.polyglot") {
words.removeAll()
tableView.reloadData()
print("Words array after clear all: \(words)")
print("chosenLanguage in loadInitialValues: \(chosenLanguage)")
print("\(chosenLanguage)\(wordString)")
if var savedWords = defaults.object(forKey: "\(chosenLanguage)\(wordString)") as? [String] {
print("savedWords array is: \(savedWords)")
words = savedWords
savedWords.removeAll()
print("savedWords array after clear all: \(savedWords)")
} else {
saveInitialWordValues(to: defaults)
}
print("Words is : \(words)")
print("Number of words: \(words.count)")
tableView.reloadData()
}
}
func saveInitialWordValues(to defaults: UserDefaults) {
switch chosenLanguage {
case "german":
words.append("Bear::Baissespekulant::0")
words.append("Camel::Kamel::0")
words.append("Cow::Rind::0")
words.append("Fox::Fuchs::0")
words.append("Goat::Geiß::0")
words.append("Monkey::Affe::0")
words.append("Pig::Schwein::0")
words.append("Rabbit::Karnickel::0")
words.append("Sheep::Schaf::0")
//words.append("::")
print(words)
defaults.set(words, forKey: "germanWords")
print("At end of saveInitialGermanValues")
case "french":
words.append("Bear::l'ours::0")
words.append("Camel::le chameau::0")
words.append("Cow::la vache::0")
words.append("Fox::le renard::0")
words.append("Goat::la chèvre::0")
words.append("Monkey::le singe::0")
words.append("Pig::le cochon::0")
words.append("Rabbit::le lapin::0")
words.append("Sheep::le mouton::0")
//words.append("::")
print(words)
defaults.set(words, forKey: "frenchWords")
print("At end of saveInitialFrenchValues")
default:
break
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
chosenLanguageLoad()
loadInitialValues()
}
override func viewDidAppear(_ animated: Bool) {
navigationController?.setToolbarHidden(true, animated: false)
super.viewDidAppear(animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
}
#objc func addNewWord() {
// create our alert controller
let ac = UIAlertController(title: "Add new word", message: nil, preferredStyle: .alert)
// add two text fields, one for English and one for French or German.
ac.addTextField { textField in
textField.placeholder = "English"
}
ac.addTextField { (textField) in
textField.placeholder = "\(self.chosenLanguage.capitalized)"
}
// create an "Add Word" button that submits the user's input
let submitAction = UIAlertAction(title: "Add Word", style: .default) { [unowned self, ac] (action: UIAlertAction!) in
// pull out the English and French words, or an empty string if there was a problem
let firstWord = ac.textFields?[0].text ?? ""
let secondWord = ac.textFields?[1].text ?? ""
let zeroTimesWrong = "0"
// submit the English and French word to the insertFlashcard() method
self.insertFlashcard(first: firstWord, second: secondWord, third: zeroTimesWrong)
}
// add the submit action, plus a cancel button
ac.addAction(submitAction)
ac.addAction(UIAlertAction(title: "Cancel", style: .cancel))
// present the alert controller to the user
present(ac, animated: true)
}
func insertFlashcard(first: String, second: String, third: String) {
guard first.count > 0 && second.count > 0 else { return }
let newIndexPath = IndexPath(row: words.count, section: 0)
words.append("\(first)::\(second)::\(third)")
tableView.insertRows(at: [newIndexPath], with: .automatic)
saveWords()
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .default, title: "Delete") { action, indexPath in
self.words.remove(at: indexPath.row)
tableView.beginUpdates()
tableView.deleteRows(at: [indexPath], with: .left)
tableView.endUpdates()
// delete item at indexPath
}
let edit = UITableViewRowAction(style: .normal, title: "Edit") { (action, indexPath) in
let ac = UIAlertController(title: "Edit word", message: nil, preferredStyle: .alert)
// add two text fields, one for English and one for French
ac.addTextField { textField in
let word = self.words[indexPath.row]
let split = word.components(separatedBy: "::")
let englishWord = split[0]
textField.placeholder = "\(englishWord)"
}
ac.addTextField { (textField) in
let word = self.words[indexPath.row]
let split = word.components(separatedBy: "::")
let foreignWord = split[1]
textField.placeholder = "\(foreignWord)"
}
// create an "Add Word" button that submits the user's input
let submitAction = UIAlertAction(title: "Edit Word", style: .default) { [unowned self, ac] (action: UIAlertAction!) in
// pull out the English and French words, or an empty string if there was a problem
let firstWord = ac.textFields?[0].text ?? ""
let secondWord = ac.textFields?[1].text ?? ""
guard firstWord.count > 0 && secondWord.count > 0 else { return }
// edit item at indexPath
self.words.remove(at: indexPath.row)
self.words.insert("\(firstWord)::\(secondWord)", at: indexPath.row)
tableView.beginUpdates()
tableView.deleteRows(at: [indexPath], with: .automatic)
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
self.saveWords()
}
// add the submit action, plus a cancel button
ac.addAction(submitAction)
ac.addAction(UIAlertAction(title: "Cancel", style: .cancel))
// present the alert controller to the user
self.present(ac, animated: true)
}
edit.backgroundColor = UIColor.blue
return [delete, edit]
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return words.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//print("In cellForRowAt function")
let cell = tableView.dequeueReusableCell(withIdentifier: "Word", for: indexPath)
let word = words[indexPath.row]
if word != "::" {
let split = word.components(separatedBy: "::")
print(split[0])
cell.textLabel?.text = split[0]
cell.detailTextLabel?.text = ""
//print(cell)
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if let cell = tableView.cellForRow(at: indexPath) {
if cell.detailTextLabel?.text == "" {
let word = words[indexPath.row]
let split = word.components(separatedBy: "::")
cell.detailTextLabel?.text = split[1]
} else {
cell.detailTextLabel?.text = ""
}
}
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
words.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
saveWords()
}
func saveWords() {
if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.polyglot") {
defaults.set(words, forKey: "\(chosenLanguage)\(wordString)")
}
}
}
I trying to code long press gesture on the cell in collection view but I haven't found about similar... I suppose I do to code something in the 'didSelectItemAt'.
Now works only if I tap in the first cell...
And then I have found on web to different solution based on swift 3.
Every one help me please? Thank you so much!
The image show when tap long on the first cell the action sheet. But don't work when I tap to other cell...
import UIKit
class RecipeCollViewController: UICollectionViewController, UITextFieldDelegate
{
struct Storyboard
{
static let leftAndRightPaddings: CGFloat = 2.0
static let numberOfItemsPerRow: CGFloat = 2.0
}
override func viewDidLoad() {
super.viewDidLoad()
RecipeDataManager.shared.recipeController = self
title = loc("TITLE_RECIPECOLL")
navigationController?.navigationBar.prefersLargeTitles = true
let collectionViewWidth = collectionView?.frame.width
let itemWidth = (collectionViewWidth! - Storyboard.leftAndRightPaddings) / Storyboard.numberOfItemsPerRow
let layout = collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize(width: itemWidth, height: 250)
}
override func numberOfSections(in collectionView: UICollectionView) -> Int
{
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return RecipeDataManager.shared.recipes.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RecipeCell", for: indexPath) as! RecipeViewCell
let recipe = RecipeDataManager.shared.recipes[indexPath.item]
cell.labelNameRecipe.text = recipe.titleRecipe
cell.imageViewRecipe.image = recipe.imageRecipe
cell.labelPrepareTime.text = String(recipe.recipeTimeInt)
cell.labelPeopleFor.text = recipe.peopleRecipe
return cell
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
}
// MARK: - NAVIGAZIONE
// Metodo che scatta quando l'utente tocca una delle celle della collectionView e apre il dettaglio
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "RecipeDetail"
{
if let indexPath = self.collectionView!.indexPathsForSelectedItems?.first
{
let recipeDetailVC = segue.destination as! DetailRecipeViewController
recipeDetailVC.recipe = RecipeDataManager.shared.recipes[indexPath.item]
}
}
}
// MARK: - UILongPressGestureRecognizer function for the cell recipe
#IBAction func popUpActionCell(longPressGesture : UILongPressGestureRecognizer)
{
let alertActionCell = UIAlertController(title: "Action Recipe Cell", message: "Choose an action for the selected recipe", preferredStyle: .actionSheet)
// Configure Remove Item Action
let deleteAction = UIAlertAction(title: "Delete", style: .destructive, handler: { action in
// Delete selected Cell
let deleteRecipe: [RecipeDataManager] = []
if let indexPath = self.collectionView?.indexPathsForSelectedItems?.first
{
RecipeDataManager.shared.recipes.remove(at: indexPath.item)
RecipeDataManager.shared.salva()
self.collectionView?.deleteItems(at: [indexPath])
}
print("Cell Removed")
})
// Configure Cancel Action Sheet
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: { acion in
print("Cancel actionsheet")
})
alertActionCell.addAction(deleteAction)
alertActionCell.addAction(cancelAction)
self.present(alertActionCell, animated: true, completion: nil)
self.collectionView!.reloadData()
}
}
With my pleausure, I have found the finally solution at my problem.
Post the code for other new developer needs help!
// MARK: - Long Press Gesture Action Sheet
#IBAction func popUpActionCell(longPressGesture : UILongPressGestureRecognizer)
{
// Delete selected Cell
let point = longPressGesture.location(in: self.collectionView)
let indexPath = self.collectionView?.indexPathForItem(at: point)
// let cell = self.collectionView?.cellForItem(at: indexPath!)
if indexPath != nil
{
let alertActionCell = UIAlertController(title: "Action Recipe Cell", message: "Choose an action for the selected recipe", preferredStyle: .actionSheet)
// Configure Remove Item Action
let deleteAction = UIAlertAction(title: "Delete", style: .destructive, handler: { action in
RecipeDataManager.shared.recipes.remove(at: indexPath!.row)
print("Cell Removed")
self.collectionView!.reloadData()
})
// Configure Cancel Action Sheet
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: { acion in
print("Cancel actionsheet")
})
alertActionCell.addAction(deleteAction)
alertActionCell.addAction(cancelAction)
self.present(alertActionCell, animated: true, completion: nil)
}
}
I'm attempting to build an app using Swift that's similar to the Notes app, but I'd like to have an Alert pop up when the user presses the "+" button to add a new Note - and the Alert would prompt the user to enter a name. The name is then added as a new row in the underlying table. So far, I've been able to do this, but every time i click the "+" sign, the buttons I've added to the Alert get re-added. In other words, the Alert should have an "OK" & a "Cancel" button. But on the 2nd time the Alert pops up, there are 2 "OK" buttons, and 2 "Cancel" buttons, and so on. Any ideas how i can fix this? Thanks for your help!
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var table: UITableView!
var data:[String] = []
//create alert controller
var alert = UIAlertController(title: "Name", message: "Enter a name", preferredStyle: .alert)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.title = "Notes"
//create "add" button
let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addAlert))
self.navigationItem.rightBarButtonItem = addButton
//create edit button so we can delete rows
self.navigationItem.leftBarButtonItem = editButtonItem
load()
}
//function to add new note. This code is executed when the "Add" button is clicked
func addNote()
{
//code to prevent being able to add rows while in edit mode
if (table.isEditing) {
return
}
let textField = self.alert.textFields![0] as UITextField
let name:String = textField.text!
data.insert(name, at: 0)
let indexPath:IndexPath = IndexPath(row: 0, section: 0)
table.insertRows(at: [indexPath], with: .automatic)
save()
}
func addAlert()
{
alert.addTextField(configurationHandler: { (textField) -> Void in
textField.placeholder = "Enter Name"})
self.present(alert, animated: true, completion: nil)
//grab value from the text field and print when user clicks OK
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (UIAlertAction) in
let textField = self.alert.textFields![0] as UITextField
print("Text Field: \(textField.text!)")
self.addNote()
}))
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell")!
cell.textLabel?.text = data[indexPath.row]
return cell
}
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
//puts table in edit mode
table.setEditing(editing, animated: animated)
}
//function to delete rows from table
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
data.remove(at: indexPath.row)
table.deleteRows(at: [indexPath], with: .fade)
save()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "detail", sender: nil)
}
func save()
{
UserDefaults.standard.set(data, forKey: "notes")
UserDefaults.standard.synchronize()
}
func load()
{
if let loadedData = UserDefaults.standard.value(forKey: "notes") as? [String]
{
data = loadedData
table.reloadData()
}
}
Put alert.addAction before presenting the alert. Try this code in addAlert() method
func addAlert()
{
var alert = UIAlertController(title: "Name", message: "Enter a name", preferredStyle: .alert)
alert.addTextField(configurationHandler: { (textField) -> Void in
textField.placeholder = "Enter Name"})
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (UIAlertAction) in
let textField = self.alert.textFields![0] as UITextField
print("Text Field: \(textField.text!)")
self.addNote()
}))
self.present(alert, animated: true, completion: nil)
}
You have to present the alert only after adding the actions(Buttons).
func addAlert()
{
alert.addTextField(configurationHandler: { (textField) -> Void in
textField.placeholder = "Enter Name"})
//grab value from the text field and print when user clicks OK
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (UIAlertAction) in
let textField = self.alert.textFields![0] as UITextField
print("Text Field: \(textField.text!)")
self.addNote()
}))
self.present(alert, animated: true, completion: nil)
}