FUIValuePickerFormCell的Picker视图不会出现

时间:2017-10-31 06:26:00

标签: ios swift3

我已经从SAP Cloud SDK Assistant自动生成了一个应用程序,我想在应用程序的详细视图中使用FUIValuePickerFormCell,但似乎无法这样做。

我使用了SAP Fiori指导者应用程序提供的示例代码,并在main.storyboard中添加了类“FUIValuePickerFormCell”的表格视图单元格,但是当单元格被点击时没有任何反应,挑选者视图没有出现,细胞也不可编辑。有谁知道为什么会这样?以下是我使用的代码

我想在ProductsTypeDetailTableDelegate

中更改的单元格
case 6:
let cell = tableView.dequeueReusableCell(withIdentifier: FUIValuePickerFormCell.reuseIdentifier, for: indexPath) as! FUIValuePickerFormCell
        valuePickerCell = cell
        cell.isEditable = true
        cell.keyName = "Appointment Status"
        cell.valueOptions = ["1", "2", "3"]
        cell.value = 1 //index of first value

        cell.onChangeHandler = { newValue in
            if let option = self.valuePickerCell?.valueOptions[newValue]{
                print("Selected value option \(option)")
            }
        }
        return cell

DetailViewController:

import SAPFoundation
import SAPOData
import SAPFiori
import SAPCommon
class DetailViewController: FUIFormTableViewController, Notifier, LoadingIndicator {

    private let appDelegate = UIApplication.shared.delegate as! AppDelegate

    private var tableDelegate: DetailTableDelegate!
    var tableUpdater: TableUpdaterDelegate?
    var loadingIndicator: FUILoadingIndicatorView?

    private let logger = Logger.shared(named: "DetailViewControllerLogger")
    var services: ServicesDataAccess {
        return appDelegate.services
    }

    // The Entity which will be edited on the Detail View
    var selectedEntity: EntityValue!
    var entityArray: [EntityValue]!
    var entityArray2: [EntityValue]!
    var entityArray3: [EntityValue]!
    var prodimages: [EntityValue]!
    var collectionType: CollectionType = .none {
        didSet {
            if let delegate = self.generatedTableDelegate() {
                self.tableDelegate = delegate
                if self.selectedEntity != nil {
                    self.tableDelegate.entity = self.selectedEntity
                }
                if self.entityArray != nil {
                    self.tableDelegate.arrayEntity = self.entityArray
                }
                if self.entityArray2 != nil {
                    self.tableDelegate.arrayEntity2 = self.entityArray2
                }
                if self.entityArray3 != nil {
                    self.tableDelegate.arrayEntity3 = self.entityArray3
                }
                if self.prodimages != nil{
                    self.tableDelegate.prodimages = self.prodimages
                }
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.allowsSelection = false
        self.tableView.dataSource = tableDelegate
        self.tableView.delegate = tableDelegate

        self.tableView.rowHeight = UITableViewAutomaticDimension
        self.tableView.estimatedRowHeight = 44
    }

    @IBAction func updateEntity(_ sender: AnyObject) {
        self.showIndicator()
        self.view.endEditing(true)
        self.logger.info("Updating entity in backend.")
        self.services.service.updateEntity(self.tableDelegate.entity) { error in
            self.hideIndicator()

            if let error = error {
                self.logger.error("Update entry failed.", error: error)
                self.displayAlert(title: NSLocalizedString("keyErrorEntityUpdateTitle", value: "Update entry failed", comment: "XTIT: Title of alert message about entity update failure."),
                    message: NSLocalizedString("keyErrorEntityUpdateBody", value: error.localizedDescription, comment: "XMSG: Body of alert message about entity update failure."))
                return
            }

            self.logger.info("Update entry finished successfully.")
            FUIToastMessage.show(message: NSLocalizedString("keyUpdateEntityFinishedTitle", value: "Updated", comment: "XTIT: Title of alert message about successful entity update."))
            self.tableUpdater?.updateTable()
        }
    }

    func createEntity() {
        self.showIndicator()
        self.view.endEditing(true)
        self.logger.info("Creating entity in backend.")
        self.services.service.createEntity(self.tableDelegate.entity) { error in
            self.hideIndicator()

            if let error = error {
                self.logger.error("Create entry failed.", error: error)
                self.displayAlert(title: NSLocalizedString("keyErrorEntityCreationTitle", value: "Create entry failed", comment: "XTIT: Title of alert message about entity creation error."),
                    message: NSLocalizedString("keyErrorEntityCreationBody", value: error.localizedDescription, comment: "XMSG: Body of alert message about entity creation error."))
                return
            }

            self.logger.info("Create entry finished successfully.")
            DispatchQueue.main.async {
                self.dismiss(animated: true) {
                    FUIToastMessage.show(message: NSLocalizedString("keyEntityCreationBody", value: "Created", comment: "XMSG: Title of alert message about successful entity creation."))
                    self.tableUpdater?.updateTable()
                }
            }
        }
    }

    func cancel() -> Void {
        DispatchQueue.main.async {
            self.dismiss(animated: true, completion: nil)
        }
    }

    // Test code
    private func updateTable(completionHandler: @escaping() -> Void) {

        self.tableDelegate?.requestEntities { error in

            defer {
                completionHandler()
            }

            if let error = error {
                self.displayAlert(title: NSLocalizedString("keyErrorLoadingData", value: "Loading data failed!", comment: "XTIT: Title of loading data error pop up."),
                    message: error.localizedDescription)
                self.logger.error("Could not update table.", error: error)
                return
            }

            DispatchQueue.main.async {
                self.tableView.reloadData()
                self.logger.info("Table updated successfully!")
            }
        }
    }

    private func configureView() {
        if self.collectionType != .none {
            self.title = collectionType.rawValue
            if let tableDelegate = self.generatedTableDelegate() {
                self.tableDelegate = tableDelegate
                if let tableView = self.tableView {
                    tableView.delegate = tableDelegate
                    tableView.dataSource = tableDelegate
                    self.updateTable()
                }
            }
        }
    }

    func updateTable() {
        self.showIndicator()
        DispatchQueue.global().async {
            self.updateTable() {
                self.hideIndicator()
            }
        }
    }

    // test code ends
}

DetailTableDelegate:

import SAPOData
import SAPFiori
import SAPFoundation

protocol DetailTableDelegate: UITableViewDelegate, UITableViewDataSource {
    var entity: EntityValue { get set }
    var arrayEntity: [EntityValue] { get set }
    var arrayEntity2: [EntityValue] { get set }
    var arrayEntity3: [EntityValue] { get set }
    var prodimages: [EntityValue] { get set}
}

extension DetailTableDelegate {
}

extension DetailViewController {

    func generatedTableDelegate() -> DetailTableDelegate? {
        switch self.collectionType {
        case .customers:
            return CUSTOMERSTypeDetailTableDelegate(dataAccess: self.services, rightBarButton: self.navigationItem.rightBarButtonItem!)
        case .suppliers:
            return SUPPLIERSTypeDetailTableDelegate(dataAccess: self.services, rightBarButton: self.navigationItem.rightBarButtonItem!)
        case .orders:
            return ORDERSTypeDetailTableDelegate(dataAccess: self.services, rightBarButton: self.navigationItem.rightBarButtonItem!, count: Int())
        case .products:
            return PRODUCTSTypeDetailTableDelegate(dataAccess: self.services, rightBarButton: self.navigationItem.rightBarButtonItem!)
        default:
            return nil
        }
    }
}

ProductsTypeDetailTableDelegate:

import Foundation
import UIKit
import SAPOData
import SAPCommon
import SAPFiori

class PRODUCTSTypeDetailTableDelegate: NSObject, DetailTableDelegate {

    private let dataAccess: ServicesDataAccess
    private var _entity: PRODUCTSType?
    // test code
    private var _arrayEntity: [PRODUCTSType] = [PRODUCTSType]()
    private var _arrayEntity2: [PRODUCTSType] = [PRODUCTSType]()
    private var _arrayEntity3: [PRODUCTSType] = [PRODUCTSType]()
    private var _prodimages: [PRODIMGType] = [PRODIMGType]()
    var valuePickerCell: FUIValuePickerFormCell?

    var prodimages: [EntityValue] {
        get {
            return _prodimages
        }
        set {
            self._prodimages = newValue as! [PRODIMGType]
        }
    }
    var arrayEntity: [EntityValue] {
        get {
            return _arrayEntity
        }
        set {
            self._arrayEntity = newValue as! [PRODUCTSType]
        }
    }
    var arrayEntity2: [EntityValue] {
        get {
            return _arrayEntity2
        }
        set {
            self._arrayEntity2 = newValue as! [PRODUCTSType]
        }
    }
    var arrayEntity3: [EntityValue] {
        get {
            return _arrayEntity3
        }
        set {
            self._arrayEntity3 = newValue as! [PRODUCTSType]
        }
    }
    // test code ends
    var entity: EntityValue {
        get {
            if _entity == nil {
                _entity = createEntityWithDefaultValues()
            }
            return _entity!
        }
        set {
            _entity = newValue as? PRODUCTSType
        }
    }
    var rightBarButton: UIBarButtonItem
    private var validity = Array(repeating: true, count: 8)

    init(dataAccess: ServicesDataAccess, rightBarButton: UIBarButtonItem) {
        self.dataAccess = dataAccess
        self.rightBarButton = rightBarButton
        self.rightBarButton.isEnabled = false
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let currentEntity = self.entity as? PRODUCTSType else {
            return cellForDefault(tableView: tableView, indexPath: indexPath)
        }
        switch indexPath.row {
        case 0:
            var value = ""
            let name = "Product ID"
            if currentEntity.hasDataValue(for: PRODUCTSType.prodid) {
                value = "\(currentEntity.prodid)"
            }
            return cellForProperty(tableView: tableView, indexPath: indexPath, property: PRODUCTSType.prodid, value: value, name: name, changeHandler: { (newValue: String) -> Bool in
                if let validValue = TypeValidator.validInteger(from: newValue) {
                    currentEntity.prodid = validValue
                    self.validity[0] = true
                } else {
                    self.validity[0] = false
                }
                self.barButtonShouldBeEnabled()
                return self.validity[0]
            })
        case 1:
            var value = ""
            let name = "Name"
            if currentEntity.hasDataValue(for: PRODUCTSType.prodname) {
                if let prodname = currentEntity.prodname {
                    value = "\(prodname)"
                }
            }
            return cellForProperty(tableView: tableView, indexPath: indexPath, property: PRODUCTSType.prodname, value: value, name: name, changeHandler: { (newValue: String) -> Bool in
                // The property is optional, so nil value can be accepted
                if newValue.isEmpty {
                    currentEntity.prodname = nil
                    self.validity[1] = false
                } else {
                    if let validValue = TypeValidator.validString(from: newValue, for: PRODUCTSType.prodname) {
                        currentEntity.prodname = validValue
                        self.validity[1] = true
                    } else {
                        self.validity[1] = false
                    }
                }
                self.barButtonShouldBeEnabled()
                return self.validity[1]
            })
        case 2:
            var value = ""
            let name = "Description"
            if currentEntity.hasDataValue(for: PRODUCTSType.proddesc) {
                if let proddesc = currentEntity.proddesc {
                    value = "\(proddesc)"
                }
            }
            return cellForProperty(tableView: tableView, indexPath: indexPath, property: PRODUCTSType.proddesc, value: value, name: name, changeHandler: { (newValue: String) -> Bool in
                // The property is optional, so nil value can be accepted
                if newValue.isEmpty {
                    currentEntity.proddesc = nil
                    self.validity[2] = false
                } else {
                    if let validValue = TypeValidator.validString(from: newValue, for: PRODUCTSType.proddesc) {
                        currentEntity.proddesc = validValue
                        self.validity[2] = true
                    } else {
                        self.validity[2] = false
                    }
                }
                self.barButtonShouldBeEnabled()
                return self.validity[2]
            })
        case 3:
            var value = ""
            let name = "Current Stock"
            if currentEntity.hasDataValue(for: PRODUCTSType.currstock) {
                if let currstock = currentEntity.currstock {
                    value = "\(currstock)"
                }
            }
            return cellForProperty(tableView: tableView, indexPath: indexPath, property: PRODUCTSType.currstock, value: value, name: name, changeHandler: { (newValue: String) -> Bool in
                // The property is optional, so nil value can be accepted
                if newValue.isEmpty {
                    currentEntity.currstock = 0
                    self.validity[3] = true
                } else {
                    if let validValue = TypeValidator.validInteger(from: newValue) {
                        currentEntity.currstock = validValue
                        self.validity[3] = true
                    } else {
                        self.validity[3] = false
                    }
                }
                self.barButtonShouldBeEnabled()
                return self.validity[3]
            })
        case 4:
            var value = ""
            let name = "Minimum Stock"
            if currentEntity.hasDataValue(for: PRODUCTSType.minstock) {
                if let minstock = currentEntity.minstock {
                    value = "\(minstock)"
                }
            }
            return cellForProperty(tableView: tableView, indexPath: indexPath, property: PRODUCTSType.minstock, value: value, name: name, changeHandler: { (newValue: String) -> Bool in
                // The property is optional, so nil value can be accepted
                if newValue.isEmpty {
                    currentEntity.minstock = 0
                    self.validity[4] = true
                } else {
                    if let validValue = TypeValidator.validInteger(from: newValue) {
                        currentEntity.minstock = validValue
                        self.validity[4] = true
                    } else {
                        self.validity[4] = false
                    }
                }
                self.barButtonShouldBeEnabled()
                return self.validity[4]
            })
        case 5:
            var value = ""
            let name = "Price"
            if currentEntity.hasDataValue(for: PRODUCTSType.price) {
                if let price = currentEntity.price {
                    value = "\(price)"
                }
            }
            return cellForProperty(tableView: tableView, indexPath: indexPath, property: PRODUCTSType.price, value: value, name: name, changeHandler: { (newValue: String) -> Bool in
                // The property is optional, so nil value can be accepted
                if newValue.isEmpty {
                    currentEntity.price = nil
                    self.validity[5] = false
                } else {
                    if let validValue = TypeValidator.validBigDecimal(from: newValue) {
                        currentEntity.price = validValue
                        self.validity[5] = true
                    } else {
                        self.validity[5] = false
                    }
                }
                self.barButtonShouldBeEnabled()
                return self.validity[5]
            })
        case 6:
//            var value = ""
//            let name = "Category"
//            if currentEntity.hasDataValue(for: PRODUCTSType.cat) {
//                if let cat = currentEntity.cat {
//                    value = "\(cat)"
//                }
//            }
//            return cellForProperty(tableView: tableView, indexPath: indexPath, property: PRODUCTSType.cat, value: value, name: name, changeHandler: { (newValue: String) -> Bool in
//                // The property is optional, so nil value can be accepted
//                if newValue.isEmpty {
//                    currentEntity.cat = nil
//                    self.validity[6] = false
//                } else {
//                    if let validValue = TypeValidator.validString(from: newValue, for: PRODUCTSType.cat) {
//                        currentEntity.cat = validValue
//                        self.validity[6] = true
//                    } else {
//                        self.validity[6] = false
//                    }
//                }
//                self.barButtonShouldBeEnabled()
//                return self.validity[6]
//            })
            let cell = tableView.dequeueReusableCell(withIdentifier: FUIValuePickerFormCell.reuseIdentifier, for: indexPath) as! FUIValuePickerFormCell
            valuePickerCell = cell
            cell.isEditable = true
            cell.keyName = "Appointment Status"
            cell.valueOptions = ["1", "2", "3"]
            cell.value = 1 //index of first value

            cell.onChangeHandler = { newValue in
                if let option = self.valuePickerCell?.valueOptions[newValue]{
                    print("Selected value option \(option)")
                }
            }
            return cell

        case 7:
            var value = ""
            let name = "Supplier ID"
            if currentEntity.hasDataValue(for: PRODUCTSType.suppid) {
                if let suppid = currentEntity.suppid {
                    value = "\(suppid)"
                }
            }
            return cellForProperty(tableView: tableView, indexPath: indexPath, property: PRODUCTSType.suppid, value: value, name: name, changeHandler: { (newValue: String) -> Bool in
                // The property is optional, so nil value can be accepted
                if newValue.isEmpty {
                    currentEntity.suppid = nil
                    self.validity[7] = true
                } else {
                    if let validValue = TypeValidator.validInteger(from: newValue) {
                        currentEntity.suppid = validValue
                        self.validity[7] = true
                    } else {
                        self.validity[7] = false
                    }
                }
                self.barButtonShouldBeEnabled()
                return self.validity[7]
            })
        default:
            return cellForDefault(tableView: tableView, indexPath: indexPath)
        }
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 8
    }

    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        return true
    }

    func createEntityWithDefaultValues() -> PRODUCTSType {
        let newEntity = PRODUCTSType()
        newEntity.prodid = self._arrayEntity.count + 1
        return newEntity
    }

    // Check if all text fields are valid
    private func barButtonShouldBeEnabled() {
        let anyFieldInvalid = self.validity.first { (field) -> Bool in
            return field == false
        }
        self.rightBarButton.isEnabled = anyFieldInvalid == nil
    }

    func cellForProperty(tableView: UITableView, indexPath: IndexPath, property: Property, value: String, name: String, changeHandler: @escaping((String) -> Bool)) -> UITableViewCell {
        let cell: UITableViewCell!

        if property.dataType.isBasic {
            // The property is a key or we are creating new entity
            if (!property.isKey || self.entity.isNew) {
                // .. that CAN be edited
                cell = self.cellWithEditableContent(tableView: tableView, indexPath: indexPath, property: property, with: value, with: name, changeHandler: changeHandler)
            } else {
                // .. that CANNOT be edited
                cell = self.cellWithNonEditableContent(tableView: tableView, indexPath: indexPath, for: property.name, with: value, with: name)
            }
        } else {
            // A complex property
            cell = self.cellWithNonEditableContent(tableView: tableView, indexPath: indexPath, for: property.name, with: "...", with: name)
        }
        return cell
    }

    func cellForDefault(tableView: UITableView, indexPath: IndexPath) -> FUISimplePropertyFormCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: FUISimplePropertyFormCell.reuseIdentifier, for: indexPath) as! FUISimplePropertyFormCell
        cell.textLabel!.text = ""
        cell.textLabel!.numberOfLines = 0
        cell.textLabel!.lineBreakMode = NSLineBreakMode.byWordWrapping
        cell.keyName = "default"

        return cell
    }

    private func cellWithEditableContent(tableView: UITableView, indexPath: IndexPath, property: Property, with value: String, with name: String, changeHandler: @escaping((String) -> Bool)) -> FUISimplePropertyFormCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: FUISimplePropertyFormCell.reuseIdentifier, for: indexPath) as! FUISimplePropertyFormCell

        cell.isEditable = true
        cell.keyName = name
        cell.value = value

        if !property.isOptional {
            cell.valueTextField!.placeholder = NSLocalizedString("keyRequiredPlaceholder", value: "Required", comment: "XSEL: Placeholder text for required but currently empty textfield.")
        }

        cell.onChangeHandler = { (newValue) -> Void in
            if !changeHandler(newValue) {
                cell.valueTextField.textColor = UIColor.red
            } else {
                cell.valueTextField.textColor = UIColor.gray
            }
        }

        return cell
    }

    private func cellWithNonEditableContent(tableView: UITableView, indexPath: IndexPath, for key: String, with value: String, with name: String) -> FUISimplePropertyFormCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: FUISimplePropertyFormCell.reuseIdentifier, for: indexPath) as! FUISimplePropertyFormCell

        cell.keyName = name
        cell.value = value

        return cell
    }

    private func selectKeyboardFor(_ type: DataType) -> UIKeyboardType {
        switch type.code {
        case DataType.byte, DataType.short, DataType.integer, DataType.int:
            return .decimalPad
        case DataType.decimal, DataType.double, DataType.localDateTime, DataType.globalDateTime:
            return .numbersAndPunctuation
        default:
            return .`default`
        }
    }

    func defaultValueFor(_ property: Property) -> Double {
        if let defaultValue = property.defaultValue {
            return Double(defaultValue.toString())!
        } else {
            return Double()
        }
    }

    func defaultValueFor(_ property: Property) -> BigDecimal {
        if let defaultValue = property.defaultValue {
            return (defaultValue as! DecimalValue).value
        } else {
            return BigDecimal.fromDouble(Double())
        }
    }

    func defaultValueFor(_ property: Property) -> Int {
        if let defaultValue = property.defaultValue {
            return Int(defaultValue.toString())!
        } else {
            return Int()
        }
    }

    func defaultValueFor(_ property: Property) -> BigInteger {
        if let defaultValue = property.defaultValue {
            return BigInteger(defaultValue.toString())
        } else {
            return BigInteger.fromInt(Int())
        }
    }

    func defaultValueFor(_ property: Property) -> Int64 {
        if let defaultValue = property.defaultValue {
            return Int64(defaultValue.toString())!
        } else {
            return Int64()
        }
    }

    func defaultValueFor(_ property: Property) -> Float {
        if let defaultValue = property.defaultValue {
            return Float(defaultValue.toString())!
        } else {
            return Float()
        }
    }

    func defaultValueFor(_ property: Property) -> LocalDateTime {
        if let defaultValue = property.defaultValue {
            return LocalDateTime.parse(defaultValue.toString())!
        } else {
            return LocalDateTime.now()
        }
    }

    func defaultValueFor(_ property: Property) -> GlobalDateTime {
        if let defaultValue = property.defaultValue {
            return GlobalDateTime.parse(defaultValue.toString())!
        } else {
            return GlobalDateTime.now()
        }
    }

    func defaultValueFor(_ property: Property) -> GuidValue {
        if let defaultValue = property.defaultValue {
            return GuidValue.parse(defaultValue.toString())!
        } else {
            return GuidValue.random()
        }
    }

    func defaultValueFor(_ property: Property) -> String {
        if let defaultValue = property.defaultValue {
            return defaultValue.toString()
        } else {
            return ""
        }
    }

    func defaultValueFor(_ property: Property) -> Bool {
        if let defaultValue = property.defaultValue {
            return defaultValue.toString().toBool()!
        } else {
            return Bool()
        }
    }
}

1 个答案:

答案 0 :(得分:0)

根据您的描述,我假设您使用的是UITableViewController,而不是FUIFormTableViewController。 “FUI * FormCells”的事件仅由FUIFormTableViewController处理,而不是由UITableViewController处理。