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

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

ただいまの
回答率

90.35%

  • Swift

    7632questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Xcode

    4307questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

  • Firebase

    668questions

    Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

2つのdictionaryを、共通の変更処理に使いたい。 firestore

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 122
退会済みユーザー

退会済みユーザー

ストーリーボード未使用で開発しています。

 やっていること

下記コード①のstruct Aとstruct B内のdictionaryを作り、
userNameのみを登録または変更するビューにあるUITextFieldと、
userNameとhogeを登録または変更するビューにあるUITextFieldを使って、
FireStoreに登録される様にしています。

//下記コード①

import Foundation
import Firebase


struct A {
    var userName :String

    var dictionaryA:[String:Any] {
        return
            ["userName":userName

        ]}
}



struct B {

    var userName :String
    var hoge :String

    var dictionaryB:[String:Any] {
        return
            ["userName" : userName,
                "hoge" : hoge
         ]}  
}




extension A {    
    init?(dictionaryA:[String:Any]) {

        guard let userName = dictionaryA["userName"] as? String else {return nil}

        self.init(userName: userName as String)

    }

}

extension B {
    init?(dictionaryB:[String:Any]) {

        guard let userName = dictionaryB["userName"] as? String else {return nil}
        guard let hoge = dictionaryB["hoge"] as? String else {return nil}


        self.init(userName: userName as String,
                                hoge: hoge as String)

}

 実現したいこと

var userNameは共通したインスタンスとして扱いたいので、
いろんな異なるビューでuserNameを変更しても、FireStoreではもちろん1つしか"userName":Stringが存在しないようにしたいです。
もしかしたらこれは出来ているかもしれませんが、分からないことがあります。

 やっていて分からないこと

下記コード③から下記コード②へモーダル遷移します。
下記コード②はuserNameとhogeを変更できるビューで、変更します(FireStoreのsetDataを使う)。
変更後下記コード③へ戻ります(dismiss)。

ここまでは下記コード③のUILabelに変更後のuserNameとhogeの値を表示できていますが、

いったん全く別のビューへ1度遷移して、そこから再度下記コード③へ遷移し、
同じ様に変更して下記コード③へ戻る(dismiss)と、

⚠️クラッシュ(Thread 1: signal SIGABRT)します。
reasonが無いため自分では原因が分かりませんでした。

 原因

これは共通のインスタンスとして扱えてないからでしょうか?
原因が分からない為質問致します。
よろしくお願いします。

userNameとhogeの値を登録または変更するビューです

//下記コード②
import UIKit
import Firebase


class HenkouModalViewController: UIViewController, UITextFieldDelegate {

...省略


    func henkou() {
        let db = Firestore.firestore()

        let b = B(userName: userNameField.text!, hoge: hogeField.text!)

        db.collection("users").document().setData(b.dictionaryB)

...省略
省略してますが、ラベルがあり変更後の値を表示しているビューです

//下記コード③

class HenkougoViewController: UIViewController {

...省略

    var a : A?
    var b : B?
    var dataListener : ListenerRegistration!

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        let userRef = db.collection("users").document()

        dataListener = userRef.addSnapshotListener { [unowned self] (docSnapshot, error) in
            guard let docSnapshot = docSnapshot, docSnapshot.exists else {return}

            //⚠️クラッシュの原因 Thread 1: signal SIGABRT
            if let b = B(dictionaryB: docSnapshot.data()!){
                self.userNameLabel.text = b.userName
                self.hogeLabel.text = b.hoge

            }
            if let a = A(dictionaryA: docSnapshot.data()!) {
                    self.userNameLabel.text = a.userName
                }       
    }    
    }

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

check解決した方法

0

共通するインスタンスとするのに、2つのstructは不要でしたので、
コード①でstruct Aとそのextensionを削除し、
struct Bとそのexensionのみにしました。

色々なビューにあるUITextFieldを使い値を共通のUILabelへ代入したい時は、
コード②func henkou()内の
let b = B(userName: userNameField.text!, hoge: hogeField.text!)の引数の型に
それぞれのUITextField名を入れてsetDataするといいと思いました。

コード③で⚠️クラッシュしていましたが、
原因は if let b = B(dictionaryB: docSnapshot.data()!)内の代入の際、
nilを許容するweakになっていないのが原因の様でした。
なので[unowned self]を[weak self]に変更し、
オプショナルの
self?.userNameLabel.text = b.userName
self?.hogeLabel.text = b.hoge
に変更し、クラッシュしなくなり、実現できました。
//

非常に本文が分かりづらく申し訳ないのですが、
今回私が実現したかった事は、
さまざまなビューにある異なるUITextFieldを変更しても、
共通のUILabelへ値を代入し、表示する、 というものでした。

見て頂いた皆様、ありがとうございました。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • Swift

    7632questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Xcode

    4307questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

  • Firebase

    668questions

    Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。