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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Firebase

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

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

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

Swift

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

Q&A

解決済

1回答

1067閲覧

関数内に設定したイベントリスナの処理について

ruuuu

総合スコア174

Firebase

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

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

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

Swift

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

0グッド

0クリップ

投稿2019/12/20 08:50

編集2019/12/20 09:20

イベントリスナについて、お聞きしたいことがあります。

import UIKit import ChameleonFramework import Firebase class ChatViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UITextFieldDelegate { @IBOutlet weak var tableView: UITableView! @IBOutlet weak var messageTextField: UITextField! @IBOutlet weak var sendButton: UIButton! //スクリーンサイズ let screenSize = UIScreen.main.bounds.size var chatArray = [Message]() override func viewDidLoad() { super.viewDidLoad() tableView.delegate = self tableView.dataSource = self messageTextField.delegate = self //カスタムセルを作成する前に、テーブルビューに伝える必要がある tableView.register(UINib(nibName:"CustomCell",bundle:nil),forCellReuseIdentifier:"Cell") //可変 tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 75 //キーボード NotificationCenter.default.addObserver(self, selector: #selector(ChatViewController.keyboardWillShow(_ :)), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(ChatViewController.keyboardWillHide(_ :)), name: UIResponder.keyboardWillHideNotification, object: nil) //Firebaseからデータをfetch(取得) fetchChatData() tableView.separatorStyle = .none } @objc func keyboardWillShow(_ notification:NSNotification){ let keyboardHeight = ((notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as Any) as AnyObject).cgRectValue.height messageTextField.frame.origin.y = screenSize.height - keyboardHeight - messageTextField.frame.height } @objc func keyboardWillHide(_ notification:NSNotification){ messageTextField.frame.origin.y = screenSize.height - messageTextField.frame.height guard let rect = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue, let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval else{return} UIView.animate(withDuration: duration) { //移動アニメーション? ↓view自体が上がってしまっている為、元の位置に戻す為の指定 let transform = CGAffineTransform(translationX: 0, y: 0) self.view.transform = transform } } //タッチされた場合 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { messageTextField.resignFirstResponder() } //Returnキーが押された場合 func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() return true } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { //メッセージの数 return chatArray.count } func numberOfSections(in tableView: UITableView) -> Int { return 1 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //このメソッドを呼び出す前に、registerとして登録する必要がある let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell cell.messageLabel.text = chatArray[indexPath.row].message cell.userNameLabel.text = chatArray[indexPath.row].sender cell.iconImageView.image = UIImage(named:"dogAvatarImage") if cell.userNameLabel.text == Auth.auth().currentUser?.email as! String{ cell.messageLabel.backgroundColor = UIColor.flatGreen() cell.messageLabel.layer.cornerRadius = 20 cell.messageLabel.layer.masksToBounds = true }else{ cell.messageLabel.backgroundColor = UIColor.flatBlue() cell.messageLabel.layer.cornerRadius = 20 cell.messageLabel.layer.masksToBounds = true } return cell } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 100 } @IBAction func sendAction(_ sender: Any) { messageTextField.endEditing(true) messageTextField.isEnabled = false //ボタン無効 sendButton.isEnabled = false if messageTextField.text!.count > 15{ print("15文字以上です!!。") return } let chatDB = Database.database().reference().child("chats") //キーバリュー型で内容を送信(Dictionary型) let messageInfo = ["sender":Auth.auth().currentUser?.email,"message":messageTextField.text!] //chatDBに入れる chatDB.childByAutoId().setValue(messageInfo) { (error, result) in if error != nil{ print(error as Any) }else{ print("送信完了") // self.sendButton.isEnabled = true // self.messageTextField.isEnabled = true // self.messageTextField.text = "" } } } //データを引っ張ってくる func fetchChatData(){ //どこからデータを引っ張ってくるのか let fetchDataRef = Database.database().reference().child("chats") //新しく更新があった時だけ取得 fetchDataRef.observe(.childAdded) { (snapShot) in let snapShotData = snapShot.value as AnyObject let text = snapShotData.value(forKey: "message") let sender = snapShotData.value(forKey: "sender") let message = Message() message.message = text as! String message.sender = sender as! String self.chatArray.append(message) self.tableView.reloadData() } } }

データの取得処理はfetchChatDataに記載していますが、イベントリスナというのはデータの更新があった場合は、どこかの関数内であっても(どこに記載されていようとも)そこの処理部分だけ(今回はfetchDataRef.observe)呼び出されそこの処理を行う、のでしょうか?
Firebase公式ドキュメントにはデータが変更されると、そのたびに再トリガーされます。とあったのですが、関数の中にある関数(fetchDataRef.observe)だけ呼び出された場合、呼び出された後の処理はどうなるのかなど、少々疑問でした為、質問させて貰いました。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

データの取得処理はfunc fetchdata()に記載しています

func fetchChatData() のtypoですかね?

イベントリスナというのはデータの更新があった場合は、どこかの関数内であっても(どこに記載されていようとも)そこの処理部分だけ(今回はfetchDataRef.observe)呼び出されそこの処理を行う

結論を言うと Yes ですが、日本語が正確ではない気がしますね。

fetchDataRef.observe(.childAdded) { (snapShot) in { ... } } は、イベントリスナを登録する処理です。イベントをリスンさせる処理と言ってもいいです。この場合、 .childAdded イベントをリスンして、イベント時に取得したデータを snapShot という引数にしてBlock (Closure) に渡しています。この登録処理はviewWillAppearに直接書いてもいいし、AppDelegateに書いておいて、ViewController側ではNotificationCenterとかで受けても大丈夫です。ただし、無秩序にどこでも宣言できるわけではなく、FIRAppの初期設定が終わっていないといけない、などの制約はあります。
余談ですが snapshot という一つの単語 (snap shotではない) なのにSが大文字なのが気になりますね……

イベントをリスンさせるというのは、「おい田中、昼休みに焼きそばパン買ってこいよ」という指示を出すようなもので、田中に声をかけたのが通学路上であっても下駄箱であっても教室の中であっても関係なく、昼休みのチャイムがなるイベントが発火すると田中は焼きそばパンを買いに行きます。ただし、田中が生まれる前に指示をしても期待通りには動かないなど、無秩序にどこでも宣言できるというわけではありません。

投稿2019/12/20 09:18

thyda.eiqau

総合スコア2982

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ruuuu

2019/12/20 09:32 編集

ご回答ありがとうございます。 たまに、「イベントリスナ」や「リッスン」と出てきて混乱してしまう部分があったのですが、「リッスン=登録」と読み替えて差し支えなかったですね。 イベント自体は「.childAdded」がイベントの種類となり、「.observe」はイベントを登録する処理であった訳ですね。 自由に記載しても良いといっても初期設定などの制約が存在することを、念頭に入れておきたいと思います。
thyda.eiqau

2019/12/20 09:36

> 「リッスン=登録」 いいえ、違います。「Eventが起こったことを検出すること」がListenであり、「Listenしてくれるやつ」がListenerです。「Listenerを登録する」処理がFirebaseではobserveというメソッドになっています。
ruuuu

2019/12/20 09:46 編集

詳細なご説明助かります。 また、分からなくなったら頂いたコメントを見返したいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問