iosswiftstringuipasteboard

App crashes when trying to copy text on iPhone


I program an "encryption app" that encrypts texts in a simple way. This is the code:

let smallLetters: String = "abcdefghijklmnopqrstuvwxyz"
let bigLetters: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

let input: String = encryptTextField.text!
    
    encryptTextField.text! = ""
    
    var value: String = ""
    
    for c in input {
        let otherChars: String = " !§$%&/()=?´`#+'*-_.:,;<>^°@€{}≠¿|][¢¶“¡≤≈ç√∫~µ@€öäüÜÖÄ"
        
        for i in otherChars {
            if c == i {
                value += String(i)
                print("i")
            }
        }
        
        var dCount: Int = 0
        var eCount: Int = 0
        
        var dFound: Bool = false
        var eFound: Bool = false
        
        for d in smallLetters {
            if !dFound {
                if c == d {
                    dFound.toggle()
                    
                    let y: Int = smallCount - dCount
                    var z: Int = 1
                    
                    for i in smallLetters {
                        if y == z {
                            print("[\(c) -> \(i)]")
                            value += String(i)
                        }
                        
                        z += 1
                    }
                } else {
                    dCount += 1
                }
            }
        }
        for e in bigLetters {
            if !eFound {
                
                if c == e {
                    eFound.toggle()
                    
                    let y: Int = bigCount - eCount
                    var z: Int = 1
                    
                    for i in bigLetters {
                        if y == z {
                            print("[\(c) -> \(i)]")
                            
                            value += String(i)
                        }
                        
                        z += 1
                    }
                } else {
                    eCount += 1
                }
            }
        }
    }
    
    let maximumChars: Int = 15
    
    var string: String = ""
    var i: Int = 1
    
    var b: Bool = false
    
    for c in value {
        if !b {
            if i <= maximumChars {
                string += String(c)
            } else {
                string += "..."
                b = true
            }
            
            i += 1
        }
    }
    
    let alert: UIAlertController = UIAlertController(title: "Encoded!", message: "Your input is now encrypted / decrypted.", preferredStyle: UIAlertController.Style.alert)
    let cancel: UIAlertAction = UIAlertAction(title: "OK", style: UIAlertAction.Style.cancel, handler: { (alert: UIAlertAction!) in
        self.encryptTextField.text! = value
        print("OK")
        
        self.encryptTextField.placeholder = "Enter a text to encrypt..."
    })
    let copy: UIAlertAction = UIAlertAction(title: "Copy!", style: UIAlertAction.Style.default, handler: { (alert: UIAlertAction!) in
        print("Copy!")
        
        let pasteboard: UIPasteboard = UIPasteboard.general
        pasteboard.string! = value
        
        self.encryptTextField.placeholder = "'" + string + "' was copied!"
    })
    
    alert.addAction(cancel)
    alert.addAction(copy)
    
    present(alert, animated: true, completion: nil)

So that I can quickly insert the encrypted text into another app (e.g. WhatsApp) I use this code (simplified):

let pasteboard: UIPasteboard = UIPasteboard.general
pasteboard.string! = "Hello World!"

The code works in the simulator: The encrypted text is copied and I can paste it with a double click (see picture).

Paste encrypted text with a double click

But when I run the app on my mobile phone (iPhone 8), the app crashes at this point!

Does anyone know a solution or at least know why?


Solution

  • The solution here is to not force unwrap optional variables in your code.
    I highly recommend to read more about Optionals in Swift here.

    let input: String = encryptTextField.text!
    The text in a UITextField can be nil. The data type is a String optional(String?)

    Instead of the above, use if let statements to safely unwrap optionals!

    if let input = encryptTextField.text{
       // Your logic/code to process input as String goes here
    }
    

    Similarly, You can remove the force unwrapping("!") done here.
    1. encryptTextField.text! = "". Just use encryptTextField.text = ""
    2. pasteboard.string! = value You can remove the force unwrapping("!") done here.
    3. pasteboard.string! = "Hello World!"

    Basically only force unwrap variables if you for sure know that the value that the optional variable holds is not nil!

    Force unwrapping optional variables that hold a nil value will crash you app!