2017-08-05 50 views
0

我的莫尔斯电码转换器应用程序在转换字符时会崩溃。但只是有时候。这真的很奇怪。当它崩溃时,我得到错误线程1 EXC_BAD_ACCESS。有一次,它成功地完成了翻译,它说我的outputLabel.text需要在主线程上更新。我曾尝试使用DispatchQueue.main.async,但它没有帮助。我尝试了僵尸对象并守卫malloc,但那些也不起作用。我究竟做错了什么?线程1 EXC_BAD_ACCESS代码1地址0x11d(Swift 4)

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

您从backgroundQueue访问outputLabel这是不符合UI元素允许的。试试

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

这没有奏效。我得到了同样的错误。 –

相关问题