gpt4 book ai didi

ios - Swift 字符串操作导致 EXC_BAD_ACCESS

转载 作者:行者123 更新时间:2023-11-28 05:35:01 25 4
gpt4 key购买 nike

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

这是导致崩溃的代码(最初包含在一个循环中但被分解以试图找到问题):

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

用户的输入存储在一个字符串数组中(小时/分钟/秒/毫秒)。上面的代码应该用 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
}
}

这是它被使用的地方(输入是上述结构的数组):

// -----------------------------------------------------------------------------------------------------------------
@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
}
}

崩溃发生在用户第一次输入数字时。我在没有更新标签的情况下对其进行了测试,并且 timeIntervalInputs 数组设置完美(输入“1”后,数组读取 [1, , , ],然后输入 0 变为 [10, , , ])

崩溃时的错误信息是

Thread 1: EXC_BAD_ACCESS (code=1, address=0x12aff2cf0)

combinedString2a,就在崩溃之前,正在存储正确的值(“00”)。崩溃后,Quick Look 显示该值为“(None)”并打印描述给出以下消息:

(String) combinedString2a = DW_OP_piece for offset 8: top of stack is not a piece

最佳答案

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

@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
}

关于ios - Swift 字符串操作导致 EXC_BAD_ACCESS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24208594/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com