swift - 在 swift 3 中关闭弹出窗口后,如何更新原始 viewController 中的选择器 View ?

标签 swift segue uipickerview viewcontroller popover

按下按钮后,我将显示一个弹出窗口,目的是将汽车品牌添加到原始 viewController 中的选择器 View 中,以便用户可以返回并选择刚刚添加的新品牌该选择器 View ,新车品牌已成功添加到数据库中,但我无法更新选择器 View ,实际上在弹出窗口关闭后,什么也没有发生,我已经尝试在 viewWillAppear、viewDidLoad、viewDidAppear 中添加一个 reloadAllComponentsreloadAllComponents code> 但什么也没发生,有人可以帮助我吗?

请看下面的图片:

弹出框:

enter image description here

按钮继续:

enter image description here

我的代码:

原始 View Controller

    import UIKit
    import CoreData

    class VehicleAddViewController: UIViewController, UITextViewDelegate, UITextFieldDelegate, UIPopoverPresentationControllerDelegate, UIPickerViewDataSource, UIPickerViewDelegate {

    // MARK: - Model

    var managedObjectContext: NSManagedObjectContext? = (UIApplication.shared.delegate as? AppDelegate)?.managedObjectContext

    // MARK: - Properties
    private final var pickerBrandData: [String]?

    private final var pickerBrandResult: String? = nil

    override func viewDidLoad() {
        super.viewDidLoad()
        self.Brand.delegate = self
        self.Brand.dataSource = self
    }

    // MARK: - Outlets
    @IBOutlet weak var Brand: UIPickerView

    //MARK: Data Sources

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        switch pickerView.tag {
            case 1:
                if pickerBrandData == nil {
                    return 0
                } else {
                    return pickerBrandData!.count
                }
            default:
                return 0
        }
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        switch pickerView.tag {
        case 1:
            return pickerBrandData?[row]
        default:
            return nil
        }

    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        switch pickerView.tag {
        case 1:
            pickerBrandResult = pickerBrandData?[row]
        default:
            break
        }
    }
    // MARK: - Navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destinationViewController.
        switch segue.identifier! {
            case "Quick Brand Add Segue":
                let DestViewController = segue.destination as? QuickBrandAddViewController
                let ReceiveViewController = DestViewController?.contentViewController
                    if let PopOverD = ReceiveViewController?.popoverPresentationController {
                        let minimunSize = ReceiveViewController?.view.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
                        ReceiveViewController?.preferredContentSize = CGSize(width: (minimunSize?.width)!, height: (minimunSize?.height)!)
                        PopOverD.delegate = self
                    DestViewController?.newSetOfBrands = pickerBrandData
                }
                break
            default:
                break
            }
            // Pass the selected object to the new view controller.
         }
     }

extension UIViewController {
    var contentViewController: UIViewController {
        if let navcon = self as? UINavigationController {
            return navcon.visibleViewController!
        } else {
            return self
        }
    }
}

弹出 View Controller

import UIKit
import CoreData

class QuickBrandAddViewController: UIViewController, UITextFieldDelegate {

    // MARK: - Model

    var managedObjectContext: NSManagedObjectContext? = (UIApplication.shared.delegate as? AppDelegate)?.managedObjectContext

    var newSetOfBrands: [String]?

    // MARK: - Properties

    private final var activeTextField: UITextField?

    // MARK: - Lifecycle methods

    override func viewDidLoad() {
        super.viewDidLoad()
        self.Brand.delegate = self
        // Do any additional setup after loading the view.
    }

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

    // MARK: - Outlets

    @IBOutlet weak var Brand: UITextField!

    // MARK: - Delegate

    func textFieldDidBeginEditing(_ textField: UITextField) {
        activeTextField = textField
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        if activeTextField != nil {
            updateDatabase(description: (activeTextField!.text)!)
        }
        managedObjectContext?.performAndWait {
            self.newSetOfBrands = Car_Brand.fetchBrand(inManagedObjectContext: self.managedObjectContext!)!
        }
        UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
            self.activeTextField?.resignFirstResponder()
            self.view.endEditing(true)
            }, completion: nil)
        presentingViewController?.dismiss(animated: true, completion: nil)
        return false
    }

    // MARK: - Methods

    private func updateDatabase(description: String) {
        managedObjectContext?.perform {
            _ = Car_Brand.insertNew(brandDescription: description, inManagedObjectContext: self.managedObjectContext!)
            do {
                try self.managedObjectContext?.save()
            } catch let error {
                print ("Core Data Error: \(error)")
            }
        }
        printDatabesesStatistics()
    }

    private func printDatabesesStatistics() {
        managedObjectContext?.perform() {
            do {
                let brandCount = try self.managedObjectContext!.count(for: NSFetchRequest(entityName: "Car_Brand"))
            print (brandCount)
            } catch let error {
                print ("Core Data Error: \(error)")
            }
        }
    }

}

CoreDataClass.swift

import Foundation
import CoreData


public class Car_Brand: NSManagedObject {

    class func insertNew (brandDescription: String, inManagedObjectContext context: NSManagedObjectContext) -> Car_Brand? {
        let request: NSFetchRequest<Car_Brand> = Car_Brand.fetchRequest()
        request.predicate = NSPredicate (format: "brand = %@", brandDescription)
        if let brand = (try? context.fetch(request))?.first {
            return brand
        } else if let brand = NSEntityDescription.insertNewObject(forEntityName: "Car_Brand", into: context) as? Car_Brand {
            brand.brand = brandDescription
            return brand
        }
        return nil
    }

    class func fetchBrand (inManagedObjectContext context: NSManagedObjectContext) -> [String]? {
        let request: NSFetchRequest<Car_Brand> = Car_Brand.fetchRequest()
        request.propertiesToFetch = ["brand"]
        request.sortDescriptors = [NSSortDescriptor(key: "brand", ascending: true)]
        if let preBrandList = try? context.fetch(request) as [Car_Brand] {
            var brandList: [String] = []
            for preBrandList in preBrandList {
                brandList.append(preBrandList.brand!)
            }
            return brandList
        } else {
            return nil
        }

    }

}

CoreDataProperties.swift

import Foundation
import CoreData 

extension Car_Brand {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Car_Brand> {
        return NSFetchRequest<Car_Brand>(entityName: "Car_Brand");
    }

    @NSManaged public var brand: String?
    @NSManaged public var id_brand: NSSet?
    @NSManaged public var id_model: NSSet?

}

// MARK: Generated accessors for id_brand
extension Car_Brand {

    @objc(addId_brandObject:)
    @NSManaged public func addToId_brand(_ value: Vehicle)

    @objc(removeId_brandObject:)
    @NSManaged public func removeFromId_brand(_ value: Vehicle)

    @objc(addId_brand:)
    @NSManaged public func addToId_brand(_ values: NSSet)

    @objc(removeId_brand:)
    @NSManaged public func removeFromId_brand(_ values: NSSet)

}

// MARK: Generated accessors for id_model
extension Car_Brand {

    @objc(addId_modelObject:)
    @NSManaged public func addToId_model(_ value: Model)

    @objc(removeId_modelObject:)
    @NSManaged public func removeFromId_model(_ value: Model)

    @objc(addId_model:)
    @NSManaged public func addToId_model(_ values: NSSet)

    @objc(removeId_model:)
    @NSManaged public func removeFromId_model(_ values: NSSet)

}

最佳答案

经过多次测试,我发现关键是 unwind segue,这样用户回到原来的 segue 后就可以执行操作,所以我将 unwind segue 的 justmiss 策略更改为这样:

在原来的viewController中我添加:

  // MARK: - Navigation
   @IBAction func updateBrandPicker(segue: UIStoryboardSegue) {
    _ = navigationController?.popViewController(animated: true)
    var rowPosition = 0;
    let previousPickerBrandData = pickerBrandData

    // Fetch the new list of Brands
    managedObjectContext?.perform {
        self.pickerBrandData = Car_Brand.fetchBrand(inManagedObjectContext: self.managedObjectContext!)!
        self.Brand.reloadAllComponents()

        // Obtain new brand
        let newSetBrands: Set = Set(self.pickerBrandData!)
        var differencePickerBrandData: Set = Set(newSetBrands)
        differencePickerBrandData.subtract(previousPickerBrandData!)
        let theNewBrand = Array(differencePickerBrandData)

        // Select the new brand in the pickerView
        if theNewBrand.count > 0 {
            for brandName in self.pickerBrandData! {
                if brandName == theNewBrand[0] {
                    self.Brand.selectRow(rowPosition, inComponent: 0, animated: true)
                    break
                }
                rowPosition += 1
            }
        }
    }
}

在弹出 View Controller 中我添加:

override func viewWillDisappear(_ animated: Bool) {
    if Brand != nil {
        updateDatabase(description: (Brand!.text)!)
    }
    self.performSegue(withIdentifier: "updateBrandPicker", sender: Any?.self)
}

// MARK: - Actions

@IBAction func Save(_ sender: UIBarButtonItem) {
    presentingViewController?.dismiss(animated: true, completion: nil)
}

// MARK: - Delegate

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
        self.Brand?.resignFirstResponder()
        self.view.endEditing(true)
        }, completion: nil)
    presentingViewController?.dismiss(animated: true, completion: nil)
    return false
}

在 Storyboard中,只需通过按住 Ctrl 键并拖动到“退出”按钮来添加展开转场,然后编辑标识符字段,检查下一个图像:

enter image description here

enter image description here

pickerView 应该更新并选择刚刚添加的新注册表

关于swift - 在 swift 3 中关闭弹出窗口后,如何更新原始 viewController 中的选择器 View ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40306841/

相关文章:

ios - UITextField 对打开 UIPickerView 无响应

ios - 如何在 Swift 中更改 UIPickerView 组件的字体大小?

ios - 在 Swift 中对从核心数据接收到的数组进行排序

ios - swift searchbar 和 tableview - fatal error : unexpectedly found nil while unwrapping an optional value

ios - AWSMobileHub 使用 Swift 在 IOS 中缓存来自 S3 的图像

ios - int32 不能转换为 int

ios - 转至 SecondViewController 后数据消失

ios - 使用 shouldPerformSegueWithIdentifier 时,必须点击按钮两次才能进入下一个 View

swift - performSegueWithIdentifier 导致崩溃

ios - 以编程方式将按钮添加到 UIToolbar