My Morse Code翻译器应用程序在逐个字符转换时崩溃。但有时候只是。这真的很奇怪。当它崩溃时,我得到错误线程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?
}
答案 0 :(得分:0)
您正在从backgroundQueue访问outputLabel,UI元素不允许这样做。试试那个
queue.async {
let outputText = self.convertStringToMorse(textFieldText!)
DispatchQueue.main.async{
self.outputLabel.text = outputText // this is where the error occurs
}
}