swift - 线程 1 EXC_BAD_ACCESS 代码 1 地址 0x11d (Swift 4)

标签 swift xcode

我的摩尔斯电码翻译器应用程序在逐个字符转换时崩溃。但只是有时。这真的很奇怪。当它崩溃时,我收到错误 Thread 1 EXC_BAD_ACCESS。有一次它成功完成翻译,它说我的 outputLabel.text 只需要在主线程上更新。我尝试使用 DispatchQueue.main.async 但它没有帮助。我尝试了僵尸对象和保护 malloc,但这些也不起作用。我做错了什么?

import UIKit
import Foundation
import AVFoundation

class ViewController: UIViewController, UITextFieldDelegate {



let alphaNumToMorse = [
    "A": ".-",
    "B": "-...",
    "C": "-.-.",
    "D": "-..",
    "E": ".",
    "F": "..-.",
    "G": "--.",
    "H": "....",
    "I": "..",
    "J": ".---",
    "K": "-.-",
    "L": ".-..",
    "M": "--",
    "N": "-.",
    "O": "---",
    "P": ".--.",
    "Q": "--.-",
    "R": ".-.",
    "S": "...",
    "T": "-",
    "U": "..-",
    "V": "...-",
    "W": ".--",
    "X": "-..-",
    "Y": "-.--",
    "Z": "--..",
    "a": ".-",
    "b": "-...",
    "c": "-.-.",
    "d": "-..",
    "e": ".",
    "f": "..-.",
    "g": "--.",
    "h": "....",
    "i": "..",
    "j": ".---",
    "k": "-.-",
    "l": ".-..",
    "m": "--",
    "n": "-.",
    "o": "---",
    "p": ".--.",
    "q": "--.-",
    "r": ".-.",
    "s": "...",
    "t": "-",
    "u": "..-",
    "v": "...-",
    "w": ".--",
    "x": "-..-",
    "y": "-.--",
    "z": "--..",
    "1": ".----",
    "2": "..---",
    "3": "...--",
    "4": "....-",
    "5": ".....",
    "6": "-....",
    "7": "--...",
    "8": "---..",
    "9": "----.",
    "0": "-----",
    " ": " ",
    ]

@IBOutlet var inputField: UITextField!
@IBOutlet var outputLabel: UILabel!

@objc func dismissKeyboard() {
    view.endEditing(true)
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    self.view.endEditing(true)
    return false
}

let defaultOutputLabelText = "The converted text will show here."

func setOutputLabel(message: String) {
    DispatchQueue.main.async {
        self.outputLabel.text = message
    }
}

func appendOutputLabel(message: String) {
    DispatchQueue.main.async {
        self.outputLabel.text = self.outputLabel.text?.appending(message)
    }
}

func resetOutputLabel() {
    DispatchQueue.main.async {
        self.outputLabel.text = ""
    }
}

// Speaking
func speakLong() {
    let dashSpeaker = try! AVAudioPlayer(contentsOf: #fileLiteral(resourceName: "beep_long.mp3"))
    dashSpeaker.play()

    while dashSpeaker.isPlaying {
        usleep(1000)
    }
}

func speakShort() {
    let dotSpeaker = try! AVAudioPlayer(contentsOf: #fileLiteral(resourceName: "beep_short.mp3"))
    dotSpeaker.play()

    while dotSpeaker.isPlaying {
        usleep(1000)
    }
}

func speakTheCode(message: String) {
    let dash = "-"
    let dot = "."
    let pause = "    "

    resetOutputLabel()

    for character in message.characters {
        if character == dash[dash.startIndex] {
            appendOutputLabel(message: dash)
            speakLong()
        }
        else if character == dot[dot.startIndex] {
            appendOutputLabel(message: dot)
            speakShort()
        }
        else {
            appendOutputLabel(message: pause)
            sleep(1)
        }
    }
}

// Conversion
func convertLetterToMorse(_ input: Character) -> String {
    var returnChar = alphaNumToMorse[String(input)]
    if returnChar == nil {
        returnChar = ""
    }
    return returnChar!
}

var stringToConvert = String()
func convertStringToMorse(_ input: String) -> String {
    stringToConvert = input
    let charsInString = input.characters
    var returnString = ""
    for char in charsInString {
        let returnChar = convertLetterToMorse(char)
        if returnChar != "" {
            returnString += returnChar + ""
        }
    }
    speakTheCode(message: "\(returnString)")
    return returnString
}

let queue = DispatchQueue(label: "queue")
@IBAction func convertButton(_ sender: Any) {

    dismissKeyboard()

    let textFieldText = inputField.text

    setOutputLabel(message: defaultOutputLabelText)

    if textFieldText != nil {
        queue.async {
            let outputText = self.convertStringToMorse(textFieldText!)
            self.outputLabel.text = outputText // this is where the error occurs
        }

    }
}

var shareText = String()

@IBAction func shareButton(_ sender: Any) {

    shareText = "\(outputLabel.text!)"

    let activityVC: UIActivityViewController = UIActivityViewController(activityItems: [shareText], applicationActivities: nil)

    self.present(activityVC, animated: true, completion: nil)

}


override func viewDidLoad() {
    super.viewDidLoad()

    outputLabel.text = defaultOutputLabelText

    let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.dismissKeyboard))
    view.addGestureRecognizer(tap)

    self.inputField.delegate = self
}

override func viewWillAppear(_ animated: Bool) {
    self.navigationController?.setNavigationBarHidden(true, animated: animated)
    super.viewWillAppear(animated)
}

override func viewWillDisappear(_ animated: Bool) {
    self.navigationController?.setNavigationBarHidden(false, animated: animated)
    super.viewWillDisappear(animated)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}


@IBOutlet var welcomeLabel: UILabel!
@IBOutlet var instructionLabel: UILabel!
var window: UIWindow?

}

最佳答案

您正在从backgroundQueue 访问outputLabel,这是UI 元素所不允许的。尝试一下

queue.async {
            let outputText = self.convertStringToMorse(textFieldText!)
            DispatchQueue.main.async{
            self.outputLabel.text = outputText // this is where the error occurs
            }
 }

关于swift - 线程 1 EXC_BAD_ACCESS 代码 1 地址 0x11d (Swift 4),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45525705/

相关文章:

ios - 如何在弹出到 rootView Swift 后立即更改选项卡?

ios - 更改宽度约束会导致冲突

iphone - Xcode 分析 69 个潜在的内存泄漏

ios - 旋转时 UILabel 文本会被截断。怎么修?

swift - 如何更改 xcode 项目中的导航标题按钮文本

ios - 使用 NSBatchInsertRequest 的 CoreData

ios - swift如何处理内存中的nil值

ios - GeoFire 错误 没有这样的模块 GeoFire

c++ - Xcode 项目将不再在调试器中显示 std::string

ios - UIPopoverController popoverControllerDidDismissPopover 不起作用