在Swift中点击返回键时,如何解除UIAlertController?

时间:2018-04-19 15:51:24

标签: ios swift uitextfield uialertcontroller

我有一个带有两个按钮和一个文本字段的UIAlertController。点击保存按钮时,执行segue。我还在textFieldShouldReturn中设置了返回键。但是,当点击返回键时,警报控制器不会解除。它向上移动到视图的左上角,并在返回视图时导致动画挂起。我还尝试使用myAlertController.dismiss(animated: false, completion: nil)关闭警报控制器,但这会引发"尝试在UIAlertController上呈现UINavigationController,其视图不在窗口层次结构中。错误。如果点击返回键并仍执行segue,如何关闭警报控制器?感谢。

Note the alert controller goes up to the top left corner

import UIKit
import CoreData

var albumNameFromTextfield: String = ""

class AlbumViewController: UIViewController, UITextFieldDelegate {

// MARK: - Properties
@IBOutlet weak var albumCollectionView: UICollectionView!
@IBOutlet weak var noAlbumsView: UIView!

var albums: [NSManagedObject] = []

let newAlbumAlert = UIAlertController(title: "Create New Album", message: "Enter a name for your new album.", preferredStyle: UIAlertControllerStyle.alert)

// MARK: - Actions

@IBAction func unwindToAlbumsScreen(sender: UIStoryboardSegue) {
}

@IBAction func newAlbumTapped(_ sender: UIBarButtonItem) {
    createNewAlbum()
}

func createNewAlbum() {
    let nAA = newAlbumAlert
    present(nAA, animated: true, completion: nil)
}

// Alert controller setup
func createNewAlbumAlert() {
    let saveAction = UIAlertAction(title: "Save", style: .default, handler: { (action) in
        guard let textField = self.newAlbumAlert.textFields?[0],
            let nameToSave = textField.text else {
                return
        }
        print("Album name has been inputted; save button tapped.")
        self.save(name: nameToSave)
        self.albumCollectionView.reloadData()
        self.performSegue(withIdentifier: "showNewAlbumViewController", sender: self)
    })

    newAlbumAlert.addTextField{ (textField: UITextField) in
        textField.placeholder = "Album Name"
        textField.keyboardType = .default
        textField.autocorrectionType = .default
        textField.returnKeyType = .done
        textField.delegate = self
        textField.enablesReturnKeyAutomatically = true
    }

    newAlbumAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
    newAlbumAlert.addAction(saveAction)

}

//Text field functions
func textFieldDidBeginEditing(_ textField: UITextField) {
    self.newAlbumAlert.actions[1].isEnabled = false
    textField.text = ""
}

func textFieldDidEndEditing(_ textField: UITextField) {
    albumNameFromTextfield = textField.text!
    print("Album name for nav title set.")
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    let TFNameToSave = textField.text
    self.save(name: TFNameToSave!)
    self.albumCollectionView.reloadData()
    textField.resignFirstResponder()
    self.performSegue(withIdentifier: "segueForTF", sender: self)
    print("Album name has been inputted; return button tapped.")
    return true
}

@objc func editingChanged(_ textField: UITextField) {
    if textField.text?.count == 1 {
        if textField.text?.first == " " {
            textField.text = ""
            return
        }
    }
    guard
        let alertControllerText = newAlbumAlert.textFields![0].text, !alertControllerText.isEmpty
    else {
        newAlbumAlert.actions[1].isEnabled = false
        return
    }
    newAlbumAlert.actions[1].isEnabled = true
}

// ViewDidLoad and ViewWillAppear
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    //Core Date functions
    guard let appDelegate =
        UIApplication.shared.delegate as? AppDelegate else {
            return
    }
    let managedContext =
        appDelegate.persistentContainer.viewContext
    let fetchRequest =
        NSFetchRequest<NSManagedObject>(entityName: "Album")
    do {
        albums = try managedContext.fetch(fetchRequest)
    } catch let error as NSError {
        print("Could not fetch. \(error), \(error.userInfo)")
    }

    //Setup to do when the view will appear
    self.albumCollectionView.reloadData()

    if albums.count == 0 {
        noAlbumsView.alpha = 1
    } else {
        noAlbumsView.alpha = 0
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    createNewAlbumAlert()
    newAlbumAlert.textFields![0].addTarget(self, action: #selector(editingChanged), for: .editingChanged)
}

//Core Data functions
func save(name: String) {
    guard let appDelegate =
        UIApplication.shared.delegate as? AppDelegate else {
            return
    }
    let managedContext =
        appDelegate.persistentContainer.viewContext
    let entity =
        NSEntityDescription.entity(forEntityName: "Album",
                                   in: managedContext)!
    let albumName = NSManagedObject(entity: entity,
                                    insertInto: managedContext)
    albumName.setValue(name, forKeyPath: "albumName")
    do {
        try managedContext.save()
        albums.append(albumName)
    } catch let error as NSError {
        print("Could not save. \(error), \(error.userInfo)")
    }
  }
}

1 个答案:

答案 0 :(得分:2)

不要在dismiss上拨打myAlertController,而是在dismiss上拨打AlbumViewController。我已在下面编辑了您的textFieldShouldReturn功能:

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    let TFNameToSave = textField.text
    self.save(name: TFNameToSave!)
    self.albumCollectionView.reloadData()
    textField.resignFirstResponder()
    // ViewController should dismiss the alert controller
    dismiss(animated: true) {
        self.performSegue(withIdentifier: "segueForTF", sender: self)
        print("Album name has been inputted; return button tapped.")
    }
    return true
}

来自the docs

  

呈现视图控制器负责解除视图   它呈现的控制器。

此处,呈现视图控制器应为AlbumViewController呈现myAlertController

希望有效!