断言失败:必须为self.form属性分配

时间:2016-03-21 16:28:38

标签: swift

我将这个库用于Swift表单:https://github.com/ortuman/SwiftForms这与Eureka非常相似。

这是对我要做的事情的解释:

我的表格中有2个选择器。 Picker1只是一个普通的选择器,而Picker2依赖于Picker1的值。所以当用户更改Picker1的值时。 Picker2中的选项也应该更改。要做到这一点,这就是我的功能:

func change_data(){
   row4.configuration[FormRowDescriptor.Configuration.Options] = ["hello", "from", "the"]
        row4.value = "hello"
        self.tableView.reloadData()
}

我使用reloadData()查看我的2个选择器值的变化。但不幸的是,我收到错误:assertion failed: self.form property MUST be assigned!

我尝试将该代码放在顶部栏中按钮的操作中并且可以正常工作。

 func submit(_: UIBarButtonItem!) {

        //let message = self.form.formValues().description

        //let alert: UIAlertView = UIAlertView(title: "Form output", message: message, delegate: nil, cancelButtonTitle: "OK")

        //alert.show()
        row4.configuration[FormRowDescriptor.Configuration.Options] = ["hello", "from", "the"]
        row4.value = "hello"
        self.tableView.reloadData()

    }

但我需要在我的功能中调用reloadData(),而不是按下按钮。

这是我的FormViewController的viewDidLoad:

 public override func viewDidLoad() {
        super.viewDidLoad()
        assert(form != nil, "self.form property MUST be assigned!")
        navigationItem.title = form.title
    }

我想要完成的是: enter image description here

我有几个选择器,最后一个选择器将取决于从第2和第3选择的项目。我将这些函数称为更新我上一个选择器的内容。

这是我的FormViewController类:

import UIKit
import CoreData
import SwiftForms

class ExampleFormViewController: FormViewController {

    struct Static {
        static let nameTag = "name"
        static let passwordTag = "password"
        static let lastNameTag = "lastName"
        static let jobTag = "job"
        static let emailTag = "email"
        static let URLTag = "url"
        static let phoneTag = "phone"
        static let enabled = "enabled"
        static let check = "check"
        static let segmented = "segmented"
        static let picker = "picker"
        static let birthday = "birthday"
        static let categories = "categories"
        static let button = "button"
        static let stepper = "stepper"
        static let slider = "slider"
        static let textView = "textview"
    }
    var val_territory = [Int]()
    var val_company = [Int]()
    var val_facility = [Int]()
    var val_specialty = [Int]()
    var putu_company = ""
    var putu_territory = ""
    var putu_facility = ""

    var str_territory = [String]()
    var str_company = [String]()
    var str_facility = [String]()
    var str_specialty = [String]()

    var territory: [Territory] = []
    var company: [Company] = []
    var facility: [Facility] = []
    var specialty: [Specialty] = []
    var row1 = FormRowDescriptor(tag: Static.picker, rowType: .Picker, title: "Territory")
    var row2 = FormRowDescriptor(tag: Static.picker, rowType: .Picker, title: "Company")
    var row3 = FormRowDescriptor(tag: Static.picker, rowType: .Picker, title: "Facility")
    var row4 = FormRowDescriptor(tag: Static.picker, rowType: .Picker, title: "Specialty")


    let name: String
    var form2 = FormDescriptor(title: "Create Shift Entry")

    init(_ coder: NSCoder? = nil) {
        name = "Bar"

        if let coder = coder {
            super.init(coder: coder)
        } else {
            super.init(nibName: nil, bundle:nil)
        }
    }

    required convenience init(coder: NSCoder) {
        self.init(coder)
        load_data()
        self.loadForm()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Save", style: .Plain, target: self, action: "submit:")

        self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: "cancel:")
    }

    // MARK: Actions

    func submit(_: UIBarButtonItem!) {

        //let message = self.form.formValues().description

        //let alert: UIAlertView = UIAlertView(title: "Form output", message: message, delegate: nil, cancelButtonTitle: "OK")

        //alert.show()
        row4.configuration[FormRowDescriptor.Configuration.Options] = ["hello", "from", "the"]
        row4.value = "hello"
        self.tableView.reloadData()

    }

    func cancel(_: UIBarButtonItem!) {

            self.performSegueWithIdentifier("goto_main2", sender: self)
    }

    private func loadForm() {

        let form = FormDescriptor(title: "Create Shift Entry")


        let section1 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)


        row1.configuration[FormRowDescriptor.Configuration.Options] = str_territory
        row1.value = str_territory[0]

        section1.addRow(row1)


        row2.configuration[FormRowDescriptor.Configuration.Options] = str_company
        row2.value = str_company[0]
        section1.addRow(row2)


        row3.configuration[FormRowDescriptor.Configuration.Options] = str_facility
        row3.value = str_facility[0]
        section1.addRow(row3)


        row4.configuration[FormRowDescriptor.Configuration.Options] = str_specialty
        row4.value = str_specialty[0]
        section1.addRow(row4)



        let section2 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)

        var row = FormRowDescriptor(tag: Static.phoneTag, rowType: .Phone, title: "Scheduled Hours")
        row.configuration[FormRowDescriptor.Configuration.CellConfiguration] = ["textField.placeholder" : "e.g. 8", "textField.textAlignment" : NSTextAlignment.Right.rawValue]
        section2.addRow(row)

        let section3 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)
        row = FormRowDescriptor(tag: Static.birthday, rowType: .DateAndTime, title: "Time In")
        section3.addRow(row)

        row = FormRowDescriptor(tag: Static.birthday, rowType: .DateAndTime, title: "Time Out")
        section3.addRow(row)



        let section4 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)

        row = FormRowDescriptor(tag: Static.enabled, rowType: .BooleanSwitch, title: "Missed Lunch")
        section4.addRow(row)


        let section5 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)

        row = FormRowDescriptor(tag: Static.textView, rowType: .MultilineText, title: "Notes")
        section5.addRow(row)


        let section8 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)

        row = FormRowDescriptor(tag: Static.button, rowType: .Button, title: "Add Staff Signature")
        row.configuration[FormRowDescriptor.Configuration.DidSelectClosure] = {
            self.view.endEditing(true)
        } as DidSelectClosure
        section8.addRow(row)

        let section9 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)

        row = FormRowDescriptor(tag: Static.button, rowType: .Button, title: "Add Supervisor Signature")
        row.configuration[FormRowDescriptor.Configuration.DidSelectClosure] = {
            self.view.endEditing(true)
            } as DidSelectClosure
        section9.addRow(row)

        form.sections = [section1, section2, section3, section4, section5, section8, section9]

        self.form = form
        form2 = form
    }

    func load_data(){
        let sortDescriptor = NSSortDescriptor(key: "orig_id", ascending: true)
        let sortDescriptors = [sortDescriptor]
        let facilityPredicate = NSPredicate(format: "facility = %@", NSNumber(integer: 1))

        var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
        var context:NSManagedObjectContext = appDel.managedObjectContext

        let fetchRequest = NSFetchRequest(entityName:"Company")
        fetchRequest.sortDescriptors = sortDescriptors
        let fetchRequestTerritory = NSFetchRequest(entityName:"Territory")
        fetchRequestTerritory.sortDescriptors = sortDescriptors
        let fetchRequestFacility = NSFetchRequest(entityName:"Facility")
        fetchRequestFacility.sortDescriptors = sortDescriptors
        let fetchRequestSpecialty = NSFetchRequest(entityName:"Specialty")
        fetchRequestSpecialty.sortDescriptors = sortDescriptors
        fetchRequestSpecialty.predicate = facilityPredicate
        let error:NSError

        do {
            let company_temp = try context.executeFetchRequest(fetchRequest)
            company = company_temp as! [Company]
            for t in company {
                val_company.append(t.orig_id! as Int)
                str_company.append(t.name! as String)
            }
            print(company.count)

            let territory_temp = try context.executeFetchRequest(fetchRequestTerritory)
            territory = territory_temp as! [Territory]
            for t in territory {
                val_territory.append(Int(t.orig_id!)!)
                str_territory.append(t.name! as String)
            }
            print(territory_temp.count)

            let facility_temp = try context.executeFetchRequest(fetchRequestFacility)
            facility = facility_temp as! [Facility]
            for t in facility {
                val_facility.append(Int(t.orig_id!)!)
                str_facility.append(t.name! as String)
            }
            print(facility_temp.count)

            let specialty_temp = try context.executeFetchRequest(fetchRequestSpecialty)
            specialty = specialty_temp as! [Specialty]
            for t in specialty {
                val_specialty.append(Int(t.orig_id!)!)
                str_specialty.append(t.name! as String)
            }
            print(specialty_temp.count)

        } catch let error as NSError {
            // failure
            print("Fetch failed: \(error.localizedDescription)")
        }

    }
    func get_facility_ter(company: Int!){

        //print("company: " + company)
        //print("territory: " + territory!)
        var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
        var context:NSManagedObjectContext = appDel.managedObjectContext

        let sortDescriptor = NSSortDescriptor(key: "orig_id", ascending: true)
        let sortDescriptors = [sortDescriptor]
        let fetchRequest = NSFetchRequest(entityName:"Territory")
        fetchRequest.sortDescriptors = sortDescriptors
        do {
            let territory_temp = try context.executeFetchRequest(fetchRequest)
            var territory2 = territory_temp as! [Territory]
            for t in territory2 {
                val_territory.append(Int(t.orig_id!)!)
                str_territory.append(t.name! as String)
            }
        } catch let error as NSError {
            // failure
            print("Fetch failed: \(error.localizedDescription)")
        }

        if let company2 = company{
            let companyPredicate = NSPredicate(format: "company = %@", NSNumber(integer: val_territory[str_territory.indexOf(putu_territory)!]))
            let territoryPredicate = NSPredicate(format: "territory = %@", NSNumber(integer: val_territory[company]))
            let predicate = NSCompoundPredicate(type: NSCompoundPredicateType.OrPredicateType, subpredicates: [companyPredicate, territoryPredicate])
            let fetchRequestFacility = NSFetchRequest(entityName:"Facility")

            fetchRequestFacility.predicate = predicate
            print(companyPredicate)

            do {
                let facility_temp = try context.executeFetchRequest(fetchRequestFacility)
                facility = facility_temp as! [Facility]
                str_facility.removeAll()
                val_facility.removeAll()
                for t in facility {
                    val_facility.append(Int(t.orig_id!)!)
                    str_facility.append(t.name! as String)
                }
                row3.configuration[FormRowDescriptor.Configuration.Options] = str_facility
            } catch let error as NSError {
                // failure
                print("Fetch failed: \(error.localizedDescription)")
            }
        }

    }
    func get_facility_com(company: Int!){

        //print("company: " + company)
        //print("territory: " + territory!)
        var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
        var context:NSManagedObjectContext = appDel.managedObjectContext

        let sortDescriptor = NSSortDescriptor(key: "orig_id", ascending: true)
        let sortDescriptors = [sortDescriptor]
        let fetchRequest = NSFetchRequest(entityName:"Company")
        fetchRequest.sortDescriptors = sortDescriptors
        do {
        let company_temp = try context.executeFetchRequest(fetchRequest)
        var company2 = company_temp as! [Company]
        for t in company2 {
            val_company.append(t.orig_id! as Int)
            str_company.append(t.name! as String)
        }
        } catch let error as NSError {
            // failure
            print("Fetch failed: \(error.localizedDescription)")
        }

        print(val_company.count)
        print(str_company.count)
        print(putu_company)
        print(str_company)
        print(str_company.contains(putu_company))
        if let company2 = company{
            let companyPredicate = NSPredicate(format: "company = %@", NSNumber(integer: val_company[company]))
            let territoryPredicate = NSPredicate(format: "territory = %@", NSNumber(integer: val_company[str_company.indexOf(putu_company)!]))
            let predicate = NSCompoundPredicate(type: NSCompoundPredicateType.OrPredicateType, subpredicates: [companyPredicate, territoryPredicate])
            let fetchRequestFacility = NSFetchRequest(entityName:"Facility")

            fetchRequestFacility.predicate = predicate
            print(companyPredicate)

            do {
                let facility_temp = try context.executeFetchRequest(fetchRequestFacility)
                facility = facility_temp as! [Facility]
                str_facility.removeAll()
                val_facility.removeAll()
                for t in facility {
                    val_facility.append(Int(t.orig_id!)!)
                    str_facility.append(t.name! as String)
                }
                row3.configuration[FormRowDescriptor.Configuration.Options] = str_facility
            } catch let error as NSError {
                // failure
                print("Fetch failed: \(error.localizedDescription)")
            }
        }

    }
    func get_specialty(facility_txt: Int!){
        print("VALUE OF FACILITY: " + String(facility_txt))
        var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
        var context:NSManagedObjectContext = appDel.managedObjectContext

        let sortDescriptor = NSSortDescriptor(key: "orig_id", ascending: true)
        let sortDescriptors = [sortDescriptor]


        let facilityPredicate = NSPredicate(format: "facility = %@", NSNumber(integer: val_facility[str_facility.indexOf(putu_facility)!]))
        let fetchRequestSpecialty = NSFetchRequest(entityName:"Specialty")

        fetchRequestSpecialty.sortDescriptors = sortDescriptors
        fetchRequestSpecialty.predicate = facilityPredicate

        do {
            let specialty_temp = try context.executeFetchRequest(fetchRequestSpecialty)
            specialty = specialty_temp as! [Specialty]

            str_specialty.removeAll()
            val_specialty.removeAll()
            for t in specialty {
                val_specialty.append(Int(t.orig_id!)!)
                str_specialty.append(t.name! as String)
            }
            print(str_specialty)
            self.form = form2

            row4.configuration[FormRowDescriptor.Configuration.Options] = str_specialty
            row4.value = "hello"
            self.tableView.reloadData()
        } catch let error as NSError {
            // failure
            print("Fetch failed: \(error.localizedDescription)")
        }
    }
    func put_company(putu: String!, row: Int!){
        print("haler")
        putu_company = putu
        print(putu_company)
        print(row)
        get_facility_com(row)
    }
    func put_territory(putu: String!, row: Int!){
        print("haler")
        putu_territory = putu
        print(putu_territory)
        print(row)
        get_facility_ter(row)
    }
    func put_facility(putu: String!, row: Int!){
        print("haler")
        putu_facility = putu
        print(putu_facility)
        print(row)

        var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
        var context:NSManagedObjectContext = appDel.managedObjectContext

        let sortDescriptor = NSSortDescriptor(key: "orig_id", ascending: true)
        let sortDescriptors = [sortDescriptor]

        let fetchRequestFacility = NSFetchRequest(entityName:"Facility")
        fetchRequestFacility.sortDescriptors = sortDescriptors
        do {
        let facility_temp = try context.executeFetchRequest(fetchRequestFacility)
        facility = facility_temp as! [Facility]
        for t in facility {
            val_facility.append(Int(t.orig_id!)!)
            str_facility.append(t.name! as String)
        }
        } catch let error as NSError {
            // failure
            print("Fetch failed: \(error.localizedDescription)")
        }

        print(val_facility)
        get_specialty(val_facility[row])
    }


}

我在这里调用这些功能:

import UIKit

public class FormPickerCell: FormValueCell, UIPickerViewDelegate, UIPickerViewDataSource {

    // MARK: Properties

    private let picker = UIPickerView()
    private let hiddenTextField = UITextField(frame: CGRectZero)

    struct MyVariables {
        static var mv_territory = 0
        static var mv_company = 0
        static var mv_facility = 0
        static var mv_specialty = 0
    }

    // MARK: FormBaseCell

    public override func configure() {
        super.configure()
        accessoryType = .None

        picker.delegate = self
        picker.dataSource = self
        hiddenTextField.inputView = picker

        contentView.addSubview(hiddenTextField)
    }

    public override func update() {
        super.update()

        titleLabel.text = rowDescriptor.title

        if let value = rowDescriptor.value {
            valueLabel.text = rowDescriptor.titleForOptionValue(value)
            if let options = rowDescriptor.configuration[FormRowDescriptor.Configuration.Options] as? NSArray {
                let index = options.indexOfObject(value)
                if index != NSNotFound {
                    picker.selectRow(index, inComponent: 0, animated: false)
                }
            }
        }
    }

    public override class func formViewController(formViewController: FormViewController, didSelectRow selectedRow: FormBaseCell) {

        if selectedRow.rowDescriptor.value == nil {
            if let row = selectedRow as? FormPickerCell {
                let options = selectedRow.rowDescriptor.configuration[FormRowDescriptor.Configuration.Options] as? NSArray
                let optionValue = options?[0] as? NSObject
                selectedRow.rowDescriptor.value = optionValue
                row.valueLabel.text = selectedRow.rowDescriptor.titleForOptionValue(optionValue!)
                row.hiddenTextField.becomeFirstResponder()

            }
        } else {
            if let row = selectedRow as? FormPickerCell {
                guard let optionValue = selectedRow.rowDescriptor.value else { return }
                row.valueLabel.text = selectedRow.rowDescriptor.titleForOptionValue(optionValue)
                row.hiddenTextField.becomeFirstResponder()
                }
        }
    }

    // MARK: UIPickerViewDelegate

    public func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return rowDescriptor.titleForOptionAtIndex(row)
    }

    public func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        let options = rowDescriptor.configuration[FormRowDescriptor.Configuration.Options] as? NSArray
        let optionValue = options?[row] as? NSObject
        rowDescriptor.value = optionValue
        valueLabel.text = rowDescriptor.titleForOptionValue(optionValue!)
        if(rowDescriptor.title == "Company"){
            print("company")
            print(valueLabel.text)
            ExampleFormViewController().put_company(valueLabel.text, row: row)
        }else if(rowDescriptor.title == "Territory"){
            print("territory")
            print(valueLabel.text)
            ExampleFormViewController().put_territory(valueLabel.text, row: row)
        }
        else if(rowDescriptor.title == "Facility"){
            print("facility")
            print(valueLabel.text)
            ExampleFormViewController().put_facility(valueLabel.text, row: row)
        }

    }

    // MARK: UIPickerViewDataSource

    public func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }

    public func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        if let options = rowDescriptor.configuration[FormRowDescriptor.Configuration.Options] as? NSArray {
            return options.count
        }
        return 0
    }
}

我这样做是为了在其他选择器中的所选项目发生变化时为我的选择器添加新值。

1 个答案:

答案 0 :(得分:2)

我认为错误发生在FormPickerCell方法的pickerView:didSelectRow:inComponent:中:

ExampleFormViewController().put_territory(valueLabel.text, row: row)

在这一行中,您正在创建ExampleFormViewController实例。我假设你想在你现有的控制器实例上调用这个函数。

最简单(也是最糟糕)的解决方案是使用FormBaseCell. formViewController属性:

public func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    let options = rowDescriptor.configuration[FormRowDescriptor.Configuration.Options] as? NSArray
    let optionValue = options?[row] as? NSObject
    rowDescriptor.value = optionValue
    valueLabel.text = rowDescriptor.titleForOptionValue(optionValue!)
    let controller = formViewController as! ExampleFormViewController
    if(rowDescriptor.title == "Company"){
        controller.put_company(valueLabel.text, row: row)
    } else if(rowDescriptor.title == "Territory"){
        controller.put_territory(valueLabel.text, row: row)
    } else if(rowDescriptor.title == "Facility"){
        controller.put_facility(valueLabel.text, row: row)
    }
}

但SwiftForm的正确解决方案是使用标准FormPickerCell(不要仅为一个控制器使用自定义逻辑覆盖它!)并使用row.configuration[FormRowDescriptor.Configuration.DidUpdateClosure]

private func loadForm() {
    let form = FormDescriptor(title: "Create Shift Entry")
    let section1 = FormSectionDescriptor(headerTitle: nil, footerTitle: nil)

    row1.configuration[FormRowDescriptor.Configuration.Options] = str_territory
    row1.value = str_territory[0]
    row1.configuration[FormRowDescriptor.Configuration.DidUpdateClosure] = { [weak self] rowDescriptor in
        guard let value = rowDescriptor.value else { return }
        guard let options = rowDescriptor.configuration[FormRowDescriptor.Configuration.Options] as? NSArray else { return }
        let index = options.indexOfObject(value)
        self?.put_territory(rowDescriptor.titleForOptionValue(value), row: index)
    }
    section1.addRow(row1)

    /// add corresponding DidUpdateClosure for row2 and row3
    /// ...
}