Ios 快速字符串操作导致EXC\u访问错误

Ios 快速字符串操作导致EXC\u访问错误,ios,string,crash,swift,exc-bad-access,Ios,String,Crash,Swift,Exc Bad Access,我正在开发一个时间计算器,试图学习Swift,但我遇到了一个问题,即格式化用户的输入会导致错误的访问 下面是导致崩溃的代码(最初包含在一个循环中,但为了找到问题而分解): 用户的输入存储在字符串数组中(小时/分钟/秒/毫秒)。上面的代码应该用0来填补空白(因此2变为02,空字符串变为00,等等),并在每次更新用户输入时运行 输入第一个或第二个字符后,上述代码崩溃。将prefixString从let更改为var会使其正常工作稍长一点,因此它会在第三个字符之后崩溃 我是做错了什么,还是这是Swift

我正在开发一个时间计算器,试图学习Swift,但我遇到了一个问题,即格式化用户的输入会导致错误的访问

下面是导致崩溃的代码(最初包含在一个循环中,但为了找到问题而分解):

用户的输入存储在字符串数组中(小时/分钟/秒/毫秒)。上面的代码应该用0来填补空白(因此2变为02,空字符串变为00,等等),并在每次更新用户输入时运行

输入第一个或第二个字符后,上述代码崩溃。将prefixString从let更改为var会使其正常工作稍长一点,因此它会在第三个字符之后崩溃

我是做错了什么,还是这是Swift中的错误

编辑(其他信息):

以下是整个结构:

struct TimeCalcInput
{
    var timeIntervalInput : String[] = ["", "", "", ""]
    var timeIntervalIndex : Int = 0
    var decimalInput : String = ""
    var timeType : TimeTypeEnum = TimeTypeEnum.AM
    var potentialInput : String = ""

    var label : String {
        get {

            if (self.timeType == TimeTypeEnum.Decimal) {
                return self.decimalInput
            } else {
//              var outputString : String = ""
//              for (var i : Int = 0; i < 3; i++) {
//                  let prefixString : String = "00"
//                  var combinedString : String = ""
//                  combinedString += prefixString + self.timeIntervalInput[i]
//                  combinedString = combinedString.substringFromIndex(countElements(combinedString) - 2)
//                  outputString = outputString + "\(combinedString)"
//              }
                var outputString : String = ""
                let prefixString : String = "00"

                let combinedString1 : String = prefixString + self.timeIntervalInput[0]
                let combinedString1a : String = combinedString1.substringFromIndex(countElements(combinedString1) - 2)
                outputString += combinedString1a

                let combinedString2 : String = prefixString + self.timeIntervalInput[1]
                let combinedString2a : String = combinedString2.substringFromIndex(countElements(combinedString2) - 2)
                outputString += combinedString2a    // CRASH USUALLY HAPPENS HERE

                let combinedString3 : String = prefixString + self.timeIntervalInput[2]
                let combinedString3a : String = combinedString3.substringFromIndex(countElements(combinedString3) - 2)
                outputString += combinedString3a

                return ""
                let test : String = "000"
                var asd : String = test + self.timeIntervalInput[3]
                asd = asd.substringFromIndex(countElements(asd) - 3)
                outputString += asd

                if (self.timeType == TimeTypeEnum.AM) {
                    outputString += " AM"
                } else if (self.timeType == TimeTypeEnum.PM) {
                    outputString += " PM"
                }

                println(outputString)

                return outputString
            }
        }
    }


    mutating func validateNewInput(inputString : String) -> Bool
    {
        switch (self.timeType)
            {
        case TimeTypeEnum.Decimal:
            return self.validateNewInputForDecimal(inputString)
        case TimeTypeEnum.Interval:
            //                  return self.validateNewInputForInterval(inputString)
            return false
        case TimeTypeEnum.AM, TimeTypeEnum.PM:
            var temp : Bool = self.validateNewInputForRawTime(inputString, isMilitaryTime:false)
            println(self.timeIntervalInput)
            return temp
        case TimeTypeEnum.Military:
            var temp : Bool =  self.validateNewInputForRawTime(inputString, isMilitaryTime:true)
            println(self.timeIntervalInput)
            return temp
        default:
            return false
        }
    }


    mutating func validateNewInputForDecimal(inputString : String) -> Bool
    {
        let combinedString : String = self.decimalInput + inputString

        // note: this regex fails on letters-only strings.  not an issue now but something to watch
        let predicate : NSPredicate = NSPredicate(format: "SELF MATCHES '^[0-9]*(\\.[0-9]*)'")
        let stringTest : Bool = predicate.evaluateWithObject(combinedString)

        if (stringTest) {
            self.decimalInput = combinedString
            return true
        }
        return false
    }

    // used to evaluate an incoming string when the string is assumed to represent a raw time (e.g. 5:30am)
    // since the string is being built one character at a time, each character needs to be evaluated separately
    // to ensure that the final time is valid
    mutating func validateNewInputForRawTime(inputString : String, isMilitaryTime : Bool) -> Bool
    {
        let currentString = self.timeIntervalInput[self.timeIntervalIndex]

        // if the incoming value is a ":" assume the user wants to move on to the next section
        // (e.g. hours --> minutes).  Fill in any gaps in the current section, then advance to the next section
        if (inputString == ":") {
            // check to make sure there is a "next" section
            if (self.timeIntervalIndex < self.timeIntervalInput.count - 1)
            {
                // if the current section is incomplete, fill any gaps with 0s
                let prefixString = "00"
                var combinedString = prefixString + currentString
                combinedString = combinedString.substringFromIndex(countElements(combinedString) - 2)
                self.timeIntervalInput[self.timeIntervalIndex] = combinedString

                // go to the next section
                self.timeIntervalIndex++
                return true
            }
            // if the incoming value is a number, evaluate it to make sure it's valid, and if so, add it
        } else {

            let combinedString = currentString + inputString

            // each section (hours, minutes, etc, has its own rules for whether the input is valid
            switch (self.timeIntervalIndex)
            {
                // hours
                case 0:
                    // if empty, accept any number
                    if (countElements(currentString) == 0) {
                        self.timeIntervalInput[self.timeIntervalIndex] = combinedString
                        return true
                        // if one digit exists, make sure total value is less than 12/24 (format depending)
                    } else if (countElements(currentString) == 1) {
                        if ((combinedString.toInt() < 24 && isMilitaryTime) || (combinedString.toInt() < 12)) {
                            self.timeIntervalInput[self.timeIntervalIndex] = combinedString
                            return true
                        }
                        // if both digits exist, skip to the next section and add it
                    } else {
                        self.timeIntervalIndex++
                        self.timeIntervalInput[self.timeIntervalIndex] = inputString
                        return true
                    }
                // minutes, seconds
                case 1, 2:
                    // if empty, accept any number
                    if (countElements(currentString) == 0) {
                        self.timeIntervalInput[self.timeIntervalIndex] = combinedString
                        return true
                        // if one digit exists, make sure total value is less than 60
                    } else if (countElements(currentString) == 1) {
                        if (combinedString.toInt() < 60) {
                            let combinedString = currentString + inputString
                            self.timeIntervalInput[self.timeIntervalIndex] = combinedString
                            return true
                        }
                        // if both digits exist, skip to the next section and add it
                    } else {
                        self.timeIntervalIndex++
                        self.timeIntervalInput[self.timeIntervalIndex] = inputString
                        return true
                    }
                // milliseconds
                case 3:
                    // accept any combined total less than 1000
                    if (combinedString.toInt() < 1000) {
                        let combinedString = currentString + inputString
                        self.timeIntervalInput[self.timeIntervalIndex] = combinedString
                        return true
                    }
                default:
                    break
            }
        }
        return false
    }
}
崩溃发生在用户第一次输入数字时。我在没有更新标签的情况下对其进行了测试,timeIntervalInputs数组设置得非常完美(输入“1”后,数组读取[1,,],然后输入0,它将变为[10,,])

崩溃时的错误消息为

线程1:EXC\U错误访问(代码=1,地址=0x12aff2cf0)

崩溃前的combinedString2a正在存储正确的值(“00”)。崩溃后,Quick Look显示值为“(无)”,打印描述会显示以下消息:

(字符串)组合字符串2A=偏移量8的DW_OP_段:堆栈顶部为 一块也没有


我一直在犯同样的错误,我只能认为这是Swift中的一个错误。这里有一个非常简单的例子。txtName是一个文本字段的IBOutlet,用户在其中键入自己的名称,labResult是放置结果的标签。在下面的代码中,每次尝试调用.lowercaseString方法时,我们都会在modifyString中遇到错误。(我对Swift和iOS编程非常陌生,所以我可能会犯一些愚蠢的错误,但我不知道是什么)


我已经向苹果公司提交了一份缺陷报告。同时,我找到了一个解决方法,用NSStrings替换组合字符串,并使用方法的NSString版本

var outputString : String = ""
let prefixString : String = "00"

let combinedString1 : NSString = prefixString.stringByAppendingString(self.timeIntervalInput[0])
let combinedString1a : NSString = combinedString1.substringFromIndex(combinedString1.length - 2)
outputString += combinedString1a

let combinedString2 : NSString = prefixString.stringByAppendingString(self.timeIntervalInput[1])
let combinedString2a : NSString = combinedString2.substringFromIndex(combinedString2.length - 2)
outputString += combinedString2a

let combinedString3 : NSString = prefixString.stringByAppendingString(self.timeIntervalInput[2])
let combinedString3a : NSString = combinedString3.substringFromIndex(combinedString3.length - 2)
outputString += combinedString3a

return outputString

combinedString2a在崩溃之前崩溃的地方的值是多少?另外,你能发布崩溃的错误消息吗?还有
timeIntervalInput
的值会有帮助。你能与我们共享
timeIntervalInput
数组吗?我想你需要发布整个类。事实上,这段代码在操场上运行得很好。也许是某种方式收集了timeIntervalInput(弱引用等),请尝试
myName=txtName.text!as String
-NSString似乎与Swift的字符串不完全兼容。
// -----------------------------------------------------------------------------------------------------------------
    @IBAction func addInputCharacter(#sender : UIButton)
    {
        let inputChar : String = String(sender.tag)
        self.inputs[self.currentInput].validateNewInput(inputChar)
        self.updateLabelsAfterInput()
    }

    // -----------------------------------------------------------------------------------------------------------------
    func updateLabelsAfterInput()
    {
        self.lblMainLabel.text = self.inputs[self.currentInput].label
        if (self.currentInput == 0) {
            self.lblSecondaryLabel.text = ""
        } else {
            self.lblSecondaryLabel.text = self.inputs[0].label
        }
    }
@IBAction func butDoIt_Clicked(sender : UIButton) {
    var myName = "Fred Bloggs"
    labResult.text = modifyString(myName) //this works just fine

    if txtName.text
    {
        myName = txtName.text!
        labResult.text = modifyString(myName) //this crashes with EXC-BAD-ACCESS
    }
   }

func modifyString(aName:String) ->String
{
    let lowername = aName.lowercaseString
    let uppername = aName.uppercaseString
    return lowername + "-" + uppername
}
var outputString : String = ""
let prefixString : String = "00"

let combinedString1 : NSString = prefixString.stringByAppendingString(self.timeIntervalInput[0])
let combinedString1a : NSString = combinedString1.substringFromIndex(combinedString1.length - 2)
outputString += combinedString1a

let combinedString2 : NSString = prefixString.stringByAppendingString(self.timeIntervalInput[1])
let combinedString2a : NSString = combinedString2.substringFromIndex(combinedString2.length - 2)
outputString += combinedString2a

let combinedString3 : NSString = prefixString.stringByAppendingString(self.timeIntervalInput[2])
let combinedString3a : NSString = combinedString3.substringFromIndex(combinedString3.length - 2)
outputString += combinedString3a

return outputString