質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.80%

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 548

score 6

class SettingsViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITextFieldDelegate {


    @IBOutlet weak var usericonView: UIImageView!

    @IBOutlet weak var nickNameTextField: UITextField!

    @IBOutlet weak var userNameTextField: UITextField!

    @IBOutlet weak var sendEmailTextField: UITextField!

    @IBOutlet weak var sendPhoneNumber: UITextField!

    @IBOutlet weak var nextSendEmailTextField: UITextField!

    @IBOutlet weak var nextSendPhoneNumber: UITextField!



    @IBOutlet weak var nickNameLabel: UILabel!

    @IBOutlet weak var userNameLabel: UILabel!

    @IBOutlet weak var sendEmailLabel: UILabel!

    @IBOutlet weak var sendPhoneLabel: UILabel!

    @IBOutlet weak var nextSendEmailLabel: UILabel!

    @IBOutlet weak var nextSendPhoneLabel: UILabel!


    var nickNameText:String = "ニックネームを入力"
    var userNameText:String = "名前を入力"
    var sendEmailText:String = "送り先Emailを入力"
    var sendPhone:String = "電話番号を入力"
    var nextSendEmailText:String = "送り先Email-2を入力"
    var nextSendPhone:String = "電話番号-2を入力"


    let userDefaults = UserDefaults.standard



    override func viewDidLoad() {
        super.viewDidLoad()


        nickNameTextField.delegate = self
        userNameTextField.delegate = self
        sendEmailTextField.delegate = self
        sendPhoneNumber.delegate = self
        nextSendEmailTextField.delegate = self
        nextSendPhoneNumber.delegate = self

        userDefaults.register(defaults: ["NickName": "ニックネームを入力"])
        nickNameLabel.text = readData()

        userDefaults.register(defaults: ["UserName": "名前を入力"])
        userNameLabel.text = readData()

        userDefaults.register(defaults: ["SendEmail": "Emailを入力"])
        sendEmailLabel.text = readData()

        userDefaults.register(defaults: ["SendPhone": "電話番号を入力"])
        sendPhoneLabel.text = readData()

        userDefaults.register(defaults: ["NextSendEmail": "Emailを入力"])
        nextSendEmailLabel.text = readData()

        userDefaults.register(defaults: ["NextSendPhone": "電話番号を入力"])
        nextSendPhoneLabel.text = readData()

    }

    //アルバムの写真を選択してアイコンとして表示する。
    @IBAction func toAlbumButton(_ sender: Any) {

        let picker = UIImagePickerController()
        picker.sourceType = .photoLibrary
        picker.delegate = self
        present(picker, animated: true)
        self.present(picker, animated: true, completion: nil)

    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let selectedImage = info[.originalImage] as? UIImage{
            usericonView.image = selectedImage
        }
        self.dismiss(animated: true)
    }

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        self.dismiss(animated: true, completion: nil)
    }

    //テキスト入力設定

    func textFieldShouldReturn(_ textField: UITextField) -> Bool{
        nickNameText = textField.text!
        nickNameLabel.text = nickNameText

        userNameText = textField.text!
        userNameLabel.text = userNameText

        sendEmailText = textField.text!
        sendEmailLabel.text = sendEmailText

        sendPhone = textField.text!
        sendPhoneLabel.text = sendPhone

        nextSendEmailText = textField.text!
        nextSendEmailLabel.text = nextSendEmailText

        nextSendPhone = textField.text!
        nextSendPhoneLabel.text = nextSendPhone


        textField.resignFirstResponder()

        saveData(str: nickNameText)
        saveData(str: userNameText)
        saveData(str: sendEmailText)
        saveData(str: sendPhone)
        saveData(str: nextSendEmailText)
        saveData(str: nextSendPhone)

        return true

    }

    func saveData(str: String){
        userDefaults.set(str, forKey: "NickName")
        userDefaults.set(str, forKey: "UserName")
        userDefaults.set(str, forKey: "SendEmail")
        userDefaults.set(str, forKey: "SendPhone")
        userDefaults.set(str, forKey: "NextSendEmail")
        userDefaults.set(str, forKey: "NextSendPhone")
    }

    func readData() -> String {
        let str: String = userDefaults.object(forKey: "NickName") as! String

        let _: String = userDefaults.object(forKey: "UserName") as! String

        let _: String = userDefaults.object(forKey: "SendEmail") as! String

        let _: String = userDefaults.object(forKey: "SendPhone") as! String

        let _: String = userDefaults.object(forKey: "NextSendEmail") as! String

        let _: String = userDefaults.object(forKey: "NextSendPhone") as! String

        return str

    }


    @IBAction func hozonButtton(_ sender : AnyObject) {

        // Key の値を削除
          userDefaults.removeObject(forKey: "NickName")
         userDefaults.removeObject(forKey: "UserName")
        userDefaults.removeObject(forKey: "SendEmail")
        userDefaults.removeObject(forKey: "SendPhone")
        userDefaults.removeObject(forKey: "NextsendEmail")
        userDefaults.removeObject(forKey: "NextSendPhone")



        userDefaults.set(true, forKey: "NickName")
     let str: String = userDefaults.object(forKey: "NickName") as! String
     nickNameLabel.text = str

        userDefaults.set(true, forKey: "UserName")
        let _: String = userDefaults.object(forKey: "UserName") as! String
        nickNameLabel.text = str

        userDefaults.set(true, forKey: "SendEmail")
        let _: String = userDefaults.object(forKey: "SendEmail") as! String
        nickNameLabel.text = str

        userDefaults.set(true, forKey: "SendPhone")
        let _: String = userDefaults.object(forKey: "SendPhone") as! String
        nickNameLabel.text = str

        userDefaults.set(true, forKey: "NextSendemail")
        let _: String = userDefaults.object(forKey: "NextSendEmail") as! String
        nickNameLabel.text = str

        userDefaults.set(true, forKey: "NextSendPhone")
        let _: String = userDefaults.object(forKey: "NextSendPhone") as! String
        nickNameLabel.text = str

        nickNameLabel.text = str
        userNameLabel.text = str
        sendEmailLabel.text = str
        sendPhoneLabel.text = str
        nextSendEmailLabel.text = str
        nextSendPhoneLabel.text = str


        print()

    }


}

コード
全くの初心者でこのエラーがどこから来てるのか分かりません。

ご指導いただければ存じます。

一通りコードを書いてビルドして動作を確認してましたが、155行目で
表題のエラーメッセージが発生しました。

### Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value


該当コードは let _: String = userDefaults.object(forKey: "UserName") as! String です。
どこにnilになるのか分かりません。
```

該当のソースコード

試したこと

いくつかの関数を見直しました。

補足情報(FW/ツールのバージョンなど)

Xcodwは最新です。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • y_waiwai

    2020/04/13 23:27

    このままではコードが読めないので、質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください

    キャンセル

  • Eijirou

    2020/04/13 23:31

    承知しました。

    キャンセル

  • Eijirou

    2020/04/13 23:48

    大丈夫でしょうか??

    キャンセル

回答 4

+1

エラーの出る行の上で、

print(userDefaults.object(forKey: "UserName"))

ってしてみたらnilって表示されない?


viewDidLoad()の中で、初期値を設定する前に値を読み込んでいます。
初期値を全て登録してから、値を読み込むようにコードの順番を変更してください。

readData()はいつも"NickName"をキーとして保存してる文字列を返すようになっています。各々のラベルに表示する文字列を返す用に変更してください。

userDefaultは保存処理をすると値が上書きされるので、func hozonButton()内部のKey の値を削除部分は不要です。

とりあえず直してみてください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/04/14 00:17

    1:”ニックネームを記入”となります。

    キャンセル

  • 2020/04/14 00:29

    nilじゃないんか〜い。

    キャンセル

  • 2020/04/14 00:32

    エラーの出ている行の上に↓これ貼り付けると、コンソールになんて表示されるの?
    print(type(of: userDefaults.object(forKey: "UserName")))

    キャンセル

+1

readData()メソッドで最初のstrしか使用していないのであれば、以下のように変更してしまえばいいのではないでしょうか?

func readData() -> String {
        let str: String = userDefaults.object(forKey: "NickName") as! String

        let _: String = userDefaults.object(forKey: "UserName") as! String

        let _: String = userDefaults.object(forKey: "SendEmail") as! String

        let _: String = userDefaults.object(forKey: "SendPhone") as! String

        let _: String = userDefaults.object(forKey: "NextSendEmail") as! String

        let _: String = userDefaults.object(forKey: "NextSendPhone") as! String

        return str

    }

↓↓↓↓

func readData() -> String {
        let str: String = userDefaults.object(forKey: "NickName") as! String

        return str

    }

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/04/14 00:53

    let str: String = userDefaults.object(forKey: "NickName") as! Stringを

    func readData(key: nickName) -> String{
    let str: String = userdefault.object(forKey: NickName) as! String
    return str
    }
    でしょうか?

    キャンセル

  • 2020/04/14 00:56

    全文記載しておきました。
    ↓↓↓

    https://teratail.com/questions/253432#reply-365609

    キャンセル

  • 2020/04/14 22:56

    ありがとうございました!!
    まだまだ理解力がなくみなさんの回答スピードに驚きました(汗
    今後もよろしくお願いします♪

    キャンセル

checkベストアンサー

0

書き直しました。これしてみてください。

class SettingsViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITextFieldDelegate {


    @IBOutlet weak var usericonView: UIImageView!

    @IBOutlet weak var nickNameTextField: UITextField!

    @IBOutlet weak var userNameTextField: UITextField!

    @IBOutlet weak var sendEmailTextField: UITextField!

    @IBOutlet weak var sendPhoneNumber: UITextField!

    @IBOutlet weak var nextSendEmailTextField: UITextField!

    @IBOutlet weak var nextSendPhoneNumber: UITextField!



    @IBOutlet weak var nickNameLabel: UILabel!

    @IBOutlet weak var userNameLabel: UILabel!

    @IBOutlet weak var sendEmailLabel: UILabel!

    @IBOutlet weak var sendPhoneLabel: UILabel!

    @IBOutlet weak var nextSendEmailLabel: UILabel!

    @IBOutlet weak var nextSendPhoneLabel: UILabel!


    var nickNameText:String = "ニックネームを入力"
    var userNameText:String = "名前を入力"
    var sendEmailText:String = "送り先Emailを入力"
    var sendPhone:String = "電話番号を入力"
    var nextSendEmailText:String = "送り先Email-2を入力"
    var nextSendPhone:String = "電話番号-2を入力"


    let userDefaults = UserDefaults.standard



    override func viewDidLoad() {
        super.viewDidLoad()


        nickNameTextField.delegate = self
        userNameTextField.delegate = self
        sendEmailTextField.delegate = self
        sendPhoneNumber.delegate = self
        nextSendEmailTextField.delegate = self
        nextSendPhoneNumber.delegate = self

        userDefaults.register(defaults: ["NickName": "ニックネームを入力"])
        nickNameLabel.text = readData("NickName")

        userDefaults.register(defaults: ["UserName": "名前を入力"])
        userNameLabel.text = readData("UserName")

        userDefaults.register(defaults: ["SendEmail": "Emailを入力"])
        sendEmailLabel.text = readData("SendEmail")

        userDefaults.register(defaults: ["SendPhone": "電話番号を入力"])
        sendPhoneLabel.text = readData("SendPhone")

        userDefaults.register(defaults: ["NextSendEmail": "Emailを入力"])
        nextSendEmailLabel.text = readData("NextSendEmail")

        userDefaults.register(defaults: ["NextSendPhone": "電話番号を入力"])
        nextSendPhoneLabel.text = readData("NextSendPhone")

    }

    //アルバムの写真を選択してアイコンとして表示する。
    @IBAction func toAlbumButton(_ sender: Any) {

        let picker = UIImagePickerController()
        picker.sourceType = .photoLibrary
        picker.delegate = self
        present(picker, animated: true)
        self.present(picker, animated: true, completion: nil)

    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let selectedImage = info[.originalImage] as? UIImage{
            usericonView.image = selectedImage
        }
        self.dismiss(animated: true)
    }

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        self.dismiss(animated: true, completion: nil)
    }

    //テキスト入力設定

    func textFieldShouldReturn(_ textField: UITextField) -> Bool{
        nickNameText = textField.text!
        nickNameLabel.text = nickNameText

        userNameText = textField.text!
        userNameLabel.text = userNameText

        sendEmailText = textField.text!
        sendEmailLabel.text = sendEmailText

        sendPhone = textField.text!
        sendPhoneLabel.text = sendPhone

        nextSendEmailText = textField.text!
        nextSendEmailLabel.text = nextSendEmailText

        nextSendPhone = textField.text!
        nextSendPhoneLabel.text = nextSendPhone


        textField.resignFirstResponder()

        saveData(str: nickNameText)
        saveData(str: userNameText)
        saveData(str: sendEmailText)
        saveData(str: sendPhone)
        saveData(str: nextSendEmailText)
        saveData(str: nextSendPhone)

        return true

    }

    func saveData(str: String){
        userDefaults.set(str, forKey: "NickName")
        userDefaults.set(str, forKey: "UserName")
        userDefaults.set(str, forKey: "SendEmail")
        userDefaults.set(str, forKey: "SendPhone")
        userDefaults.set(str, forKey: "NextSendEmail")
        userDefaults.set(str, forKey: "NextSendPhone")
    }

    func readData(key: String) -> String {
        let str: String = userDefaults.object(forKey: key) as! String
        return str
    }


    @IBAction func hozonButtton(_ sender : AnyObject) {

        // Key の値を削除
          userDefaults.removeObject(forKey: "NickName")
         userDefaults.removeObject(forKey: "UserName")
        userDefaults.removeObject(forKey: "SendEmail")
        userDefaults.removeObject(forKey: "SendPhone")
        userDefaults.removeObject(forKey: "NextsendEmail")
        userDefaults.removeObject(forKey: "NextSendPhone")



        userDefaults.set(true, forKey: "NickName")
     let str: String = userDefaults.object(forKey: "NickName") as! String
     nickNameLabel.text = str

        userDefaults.set(true, forKey: "UserName")
        let _: String = userDefaults.object(forKey: "UserName") as! String
        nickNameLabel.text = str

        userDefaults.set(true, forKey: "SendEmail")
        let _: String = userDefaults.object(forKey: "SendEmail") as! String
        nickNameLabel.text = str

        userDefaults.set(true, forKey: "SendPhone")
        let _: String = userDefaults.object(forKey: "SendPhone") as! String
        nickNameLabel.text = str

        userDefaults.set(true, forKey: "NextSendemail")
        let _: String = userDefaults.object(forKey: "NextSendEmail") as! String
        nickNameLabel.text = str

        userDefaults.set(true, forKey: "NextSendPhone")
        let _: String = userDefaults.object(forKey: "NextSendPhone") as! String
        nickNameLabel.text = str

        nickNameLabel.text = str
        userNameLabel.text = str
        sendEmailLabel.text = str
        sendPhoneLabel.text = str
        nextSendEmailLabel.text = str
        nextSendPhoneLabel.text = str


        print()

    }


}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/04/14 01:50

    nickNameTextFieldに「サル」と入力したらnickNameTextLabelに「サル」と表示させたい。
    nameTextFieldに「キジ」と入力したらnameTextLabelに「キジ」
    emailTextFieldに「aaa@gmail.com」と記入したらtextLabelに「aaa@gmail.com」とそれぞれの
    値を表示さてないです。

    キャンセル

  • 2020/04/14 02:12

    https://teratail.com/questions/253451?modal=q-comp
    こちらになります。よろしくお願いします・

    キャンセル

  • 2020/04/14 02:13

    あれ?写真は1枚しかあげられないんですか?

    キャンセル

0

ベストな書き方ではないと思いますが、次のようにしてはどうでしょうか。

let config = UserDefaults.standard
let _: String = config.string(forKey: "UserName") == nil ? "" : config.string(forKey: "UserName")!

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/04/14 01:14 編集

    最近落ちないって確信できる部分は!ってしちゃうんだけど、??のがいいのかな?

    キャンセル

  • 2020/04/14 01:18

    絶対に落ちないところなら別にいいと思います!

    プログラムの観点では、強制アンラップを使用しない「??」のがベターですね。
    nilになることが100%ない設計になるので。

    キャンセル

  • 2020/04/14 01:29

    なるほど、betterですね。ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る