I have the following function in Swift and am looking to improve the readability. The function takes from the deviceData object which holds maps of data like [String:Double], [String:Int], and sometimes just regular String. The function is meant to format the data in the maps into Strings and return an array of Strings. Adding the variables to the Array below all of the let variables seems kind of funky to me and I was thinking maybe it would be good to declare an empty array above, get rid of the variable declarations and just add each value to the array but I'm not sure if that would be better or worse for performance. How can I improve the readability of this function without sacrificing performance?

func createFormattedDataStrings(deviceData: DeviceData, timeMilli: Double) -> Array<String?> {
    let formattedBmsVersion = (deviceData.bmsVersion?.first!.key)! + " \(deviceData.bmsVersion!.first!.value)"
    let formattedBoardVersion = (deviceData.boardVersion?.first!.key)! + " \(deviceData.boardVersion!.first!.value)"
    let formattedCellOne = (deviceData.cellOne?.first?.key)! + String(format: "%.2f", deviceData.cellOne!.first!.value) + "V"
    let formattedCellTwo = (deviceData.cellTwo?.first!.key)! + String(format: "%.2f", deviceData.cellTwo!.first!.value) + "V"
    let formattedCellThree = (deviceData.cellThree?.first!.key)! + String(format: "%.2f", deviceData.cellThree!.first!.value) + "V"
    let formattedCellFour = (deviceData.cellFour?.first!.key)! + String(format: "%.2f", deviceData.cellFour!.first!.value) + "V"
    let formattedCellFive = (deviceData.cellFive?.first!.key)! + String(format: "%.2f", deviceData.cellFive!.first!.value) + "V"
    let formattedCellSix = (deviceData.cellSix?.first!.key)! + String(format: "%.2f", deviceData.cellSix!.first!.value) + "V"
    let formattedCellSeven = (deviceData.cellSeven?.first!.key)! + String(format: "%.2f", deviceData.cellSeven!.first!.value) + "V"
    let formattedCellEight = (deviceData.cellEight?.first!.key)! + String(format: "%.2f", deviceData.cellEight!.first!.value) + "V"
    let formattedCellNine = (deviceData.cellNine?.first!.key)! + String(format: "%.2f", deviceData.cellNine!.first!.value) + "V"
    let formattedCellTen = (deviceData.cellTen?.first!.key)! + String(format: "%.2f", deviceData.cellTen!.first!.value) + "V"
    let formattedCellEleven = (deviceData.cellEleven?.first!.key)! + String(format: "%.2f", deviceData.cellEleven!.first!.value) + "V"
    let formattedCellTwelve = (deviceData.cellTwelve?.first!.key)! + String(format: "%.2f", deviceData.cellTwelve!.first!.value) + "V"
    let formattedCellThirteen = (deviceData.cellThirteen?.first!.key)! + String(format: "%.2f", deviceData.cellThirteen!.first!.value) + "V"
    let formattedCellFourteen = (deviceData.cellFourteen?.first!.key)! + String(format: "%.2f", deviceData.cellFourteen!.first!.value) + "V"
    let formattedPackVoltage = (deviceData.packVoltage?.first!.key)! + String(format: "%.1f", deviceData.packVoltage!.first!.value) + "V"
    let formattedPackSoc = (deviceData.packSoc?.first!.key)! + String(deviceData.packSoc!.first!.value) + "%"
    let formattedChargeTemp = (deviceData.chargeTemp?.first!.key)! + " \(deviceData.chargeTemp!.first!.value)°F"
    let formattedDischargeTemp = (deviceData.dischargeTemp?.first!.key)! + " \(deviceData.dischargeTemp!.first!.value)°F"
    let formattedChargeCurrent = (deviceData.chargeCurrent?.first!.key)! + " \(deviceData.chargeCurrent!.first!.value)A"
    let formattedChargeCircuitState = (deviceData.chargeCircuitState?.first!.key)! + " \(deviceData.chargeCircuitState!.first!.value)"
    let formattedDischargeCircuitState = (deviceData.dischargeCircuitState?.first!.key)! + " \(deviceData.dischargeCircuitState!.first!.value)"
    let formattedBalanceCircuitState = (deviceData.balanceCircuitState?.first!.key)! + " \(deviceData.balanceCircuitState!.first!.value)"
    let formattedEmptyCircuitState = (deviceData.emptyCircuitState?.first!.key)! + " \(deviceData.emptyCircuitState!.first!.value)"
    let formattedRestMode = deviceData.restMode
    let formattedMisbalancedMode = deviceData.misbalancedMode
    let formattedLeftChargedMode = deviceData.leftChargedMode
    let formattedHighVoltageMode = deviceData.highVoltageMode
    let formattedHighTempMode = deviceData.highTempMode
    let formattedLowTempMode = deviceData.lowTempMode
    let formattedLowVoltageMode = deviceData.lowVoltageMode
    let formattedHibernationMode = deviceData.hibernationMode
    let formattedOverDischargeMode = deviceData.overDischargeMode
    let formattedShipMode = deviceData.shipMode
    let formattedStateError = deviceData.stateError
    let formattedFinalCharge = deviceData.finalCharge
    let formattedFinalDischarge = deviceData.finalDischarge
    let formattedFinalBalance = deviceData.finalBalance
    let formattedFinalEmpty = deviceData.finalEmpty
    var dataStringArray: Array<String?> = [formattedBmsVersion, formattedBoardVersion, formattedCellOne, formattedCellTwo, formattedCellThree, formattedCellFour, formattedCellFive, formattedCellSix, formattedCellSeven, formattedCellEight, formattedCellNine, formattedCellTen, formattedCellEleven, formattedCellTwelve, formattedCellThirteen, formattedCellFourteen, formattedPackVoltage, formattedPackSoc, formattedChargeTemp, formattedDischargeTemp, formattedChargeCurrent, formattedChargeCircuitState, formattedDischargeCircuitState, formattedBalanceCircuitState, formattedEmptyCircuitState, formattedRestMode, formattedMisbalancedMode, formattedLeftChargedMode, formattedHighVoltageMode, formattedHighTempMode, formattedLowTempMode, formattedLowVoltageMode, formattedHibernationMode, formattedOverDischargeMode, formattedShipMode, formattedStateError, formattedFinalCharge, formattedFinalDischarge, formattedFinalBalance, formattedFinalEmpty]
    if (deviceData.bmsVersion?.first?.value)! >= 3634 {
        let formattedHotChargerMode = deviceData.hotChargerMode
        let formattedBadCharger = deviceData.badCharger
        dataStringArray.insert(formattedHotChargerMode!, at: 30)
        dataStringArray.insert(formattedBadCharger!, at: 41)
    return dataStringArray

Here is the deviceData specification:

import Foundation

public struct DeviceData {
    var bmsVersion: [String:Int]?
    var boardVersion: [String:Double]?
    var cellOne: [String:Double]?
    var cellTwo: [String:Double]?
    var cellThree: [String:Double]?
    var cellFour: [String:Double]?
    var cellFive: [String:Double]?
    var cellSix: [String:Double]?
    var cellSeven: [String:Double]?
    var cellEight: [String:Double]?
    var cellNine: [String:Double]?
    var cellTen: [String:Double]?
    var cellEleven: [String:Double]?
    var cellTwelve: [String:Double]?
    var cellThirteen: [String:Double]?
    var cellFourteen: [String:Double]?
    var packVoltage: [String:Double]?
    var packSoc: [String:Int]?
    var chargeTemp: [String:Int]?
    var dischargeTemp: [String:Int]?
    var chargeCurrent: [String:Int]?
    var chargeCircuitState: [String:String]?
    var dischargeCircuitState: [String:String]?
    var balanceCircuitState: [String:String]?
    var emptyCircuitState: [String:String]?
    var restMode: String?
    var misbalancedMode: String?
    var leftChargedMode: String?
    var highVoltageMode: String?
    var highTempMode: String?
    var hotChargerMode: String?
    var lowTempMode: String?
    var lowVoltageMode: String?
    var hibernationMode: String?
    var overDischargeMode: String?
    var shipMode: String?
    var stateError: String?
    var finalCharge: String?
    var finalDischarge: String?
    var finalBalance: String?
    var finalEmpty: String?
    var badCharger: String?
    var dischargeShort: String?

    func getDeviceDataCount() -> Int {
        if (hotChargerMode == nil) {
            return 40
        } else {
            return 43
  • \$\begingroup\$ Can you add the exact definition of DeviceData? Is there some specification of the data? \$\endgroup\$
    – Martin R
    Aug 7 at 15:16
  • \$\begingroup\$ @MartinR I just added it. \$\endgroup\$ Aug 8 at 17:09
  • \$\begingroup\$ I just wonder why all the members are dictionaries, and only one entry of each dictionary is used. Is that intentional? \$\endgroup\$
    – Martin R
    Aug 8 at 18:25
  • \$\begingroup\$ @MartinR Yes, I intended to do that to accomplish what felt like easier data formatting for the display. I have data that I wanted to access and manipulate but I also had strings to describe that data so I just put them together with a data structure I was familiar with. Should I have used a different data structure? \$\endgroup\$ Aug 8 at 19:06
  • \$\begingroup\$ Also, both members of the dictionary are being used in the formatting strings. \$\endgroup\$ Aug 8 at 19:08


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.