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

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

ただいまの
回答率

89.55%

delegateする時のインスタンスについて

解決済

回答 2

投稿 編集

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

pegy

score 126

(環境)
xcode:11.3
version 5.1.3

(参考文献)
詳解 Swift 第5版
著者 萩原剛志
発行者 SBクリエイティブジャブ式会社

でdelegateに出会い理解ができずに、Qiitaで平易な解説がされている記事を見つけました。

以下のコードの説明において、文中で以下の記載がございます。

outputTextはUITextFieldクラスのインスタンスなので、これは、outputTextのtextプロパティにtextを代入することを意味します。

コードを見ても私にはoutputTextUITextField のインスタンスとして読み取れず、どちらのインスタンスであったとしても、後段の以下の文章との因果関係を読み解くことができません。

なるほど、だからこう実装することでUITextField(inputText)に入力された文字列をUILabel(outputText)に渡せるんですね。

1.実際にUITextFieldクラスのインスタンスであるのか?またそれはどのコードから読み解くことができるのかをアドバイス願えますでしょうか?また、後段との因果関係、なぜUITextFieldのインスタンスまたはUILabelのインスタンスであれば文字列を渡せるのかをご教示願えますでしょうか?

2.また、基本的な理解なのですが、self.propなどでは自分自身のクラスの中のpropプロパティにアクセスできることは理解しているのですが、inputText.delegate = selfの様な記法にけるクラスはそのクラス全体を指している(特定のプロパティやメソッドではない)という理解であっていますでしょうか?

import UIKit

class ViewController: UIViewController, UITextFieldDelegate { // 追加記述①

  @IBOutlet weak var inputText: UITextField!
  @IBOutlet weak var outputText: UILabel!

  override func viewDidLoad() {
    super.viewDidLoad()
    // 追加記述②
    inputText.delegate = self
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
  }

  // 追加記述③
  func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    let text = textField.text
    outputText.text = text
    return true
  }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+1

outputTextはUITextFieldクラスのインスタンスなので、これは、outputTextのtextプロパティにtextを代入することを意味します。

Qiitaのテキストに間違いがありますね。outputTextUITextFieldのインスタンスではありません。

1.実際にUITextFieldクラスのインスタンスであるのか?またそれはどのコードから読み解くことができるのかをアドバイス願えますでしょうか?また、後段との因果関係、なぜUITextFieldのインスタンスまたはUILabelのインスタンスであれば文字列を渡せるのかをご教示願えますでしょうか?

outputTextがどのインスタンスか、ということはソースコードの

  @IBOutlet weak var inputText: UITextField!
  @IBOutlet weak var outputText: UILabel!

からみてもわかる通りUILabelのインスタンスです。

「なぜUITextFieldのインスタンスまたはUILabelのインスタンスであれば文字列を渡せるのか」と言う部分ですが、上記のtypoを考慮にいれれば「なぜUITextFieldのインスタンス(のプロパティであるtext)であれば文字列を渡せるのか」ということかと思います。

それは、「テキストフィールドに表示されている文字列は、UITextFieldtextプロパティで保持されるから」と言うことになります。 Appleのドキュメントも合わせて参考にされるといいかとおもいます(クイックメニューにも同じような内容は表示されます)。

任意のタイミングでUTTextFieldtextを参照すれば、テキストフィールドに表示されている文字列を取得することができます。しかし、プログラムで逐一textの値を参照することは効率的とはいえません。

なのでどのようにしているかと言うと、Delegateという考え方を使って、ある条件が満たされた場合に呼び出されるメソッドを使い、そのタイミングである操作をしています。

UITextFieldには、textFieldShouldReturn(_:)というデリゲートがあります。

これは、「キーボードのリターン(に相当する)ボタンが押された時」に呼び出されるメソッドです。つまり、「ある条件」で呼び出されるメソッドということになります。

では、「キーボードのリターンボタンを押された時」にする処理とは何でしょうか。

それは、プログラムを組む人間が自由に決めて良い内容です。

Qiitaの例では、リターンボタンを押されたタイミングで「テキストフィールドに入力されている文字列を、ラベルに表示させる」という処理を行わせています(もちろん、それ以外の処理もあります)。

それが、

    let text = textField.text
    outputText.text = text

という処理ということになるわけです。つまり、これが「ある操作」ということになります。

Delegateの解説は、「移譲する」視点から書かれたものが多いと思います。しかし、最初のうちは「移譲される」側、つまり今回の例だと、エンターボタンを押された時の具体的な処理を移譲される側としてプログラムを記述することが多いとおもます。なので、「移譲される側」としてDelegateの動作を考えてみた方が理解が容易かもしれません。

また、ここ1-2ヶ月の間でも、teratailではSwiftにおけるDelegate処理に関する質問が2,3出ていますので、それらの解説も合わせてご覧になるのも良いかもしれません。

2.また、基本的な理解なのですが、self.propなどでは自分自身のクラスの中のpropプロパティにアクセスできることは理解しているのですが、inputText.delegate = selfの様な記法にけるクラスはそのクラス全体を指している(特定のプロパティやメソッドではない)という理解であっていますでしょうか? 

selfというキーワードは、「自分自身のインスタンスそのもの」をあらわします。クラスの中で定義したインスタンスは変数名や定数名でアクセスできますが、自分自身のインスタンスは変数・定数には入れていません(やる方法はあると思いますが)。その代わりselfというキーワードを使って汎用的にアクセスできるようになっているわけです。

inputText.delegate = selfという記述は、delegateという変数に自分自身のインスタンスを入れる定義です。なので、厳密には「クラス全体を指している」という表現ではなく、「自分自身のインスタンスを指している」ということになると思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/03/26 14:37

    一から作り直して、動作させることができました。
    コードを追加・削除する時にView Controllerのoutletsの紐付きも削除しているつもりなのですが、どこかでうまく行ってなかったのかもしれません。

    もっと、早くエラーコードをみて、すぐ当たりをつけることができる経験値を積みたいです!。

    さて、お試しで以下のコードを動作させることができたのですが、つまりinputText_1で文字入力してリターンをするとinputText_1の文字が
    inputText_2で文字入力してリターンをするとinputText_2の文字が
    outputTextに出力されるという動作になります。

    なぜ、
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    let text = textField.text
    outputText.text = text
    return true
    }
    の引数で具体的にどのインスタンスか指定していないにもかかわらず、両方とも入力された状態でinputText_2入力後にリターンを押して、inputText_1の入力ちがoutputTextに出力されないのかが不思議でした。これはSwiftが(_ textField: UITextField)の引数に入っているインスタンスがリターンされたtextFieldの.textをみに行っており、UITextFieldDelegateのプロトコルのメソッドであるtextFieldShouldReturnというのはそういうものであるとというふうに認識することができました。

    Javascriptでも
    $('.class').on('click',function(event){
    event.//
    })
    の様にクリックされた要素のevent(オブジェクト)でコールバック処理をする様な書き方があり、これと照らすと非常にしっくりする様な気がいたします。
    ※ここでJSのお話を持ってきてしまい申し訳ございません。あとで私みたいな想像力のない人がみた時にあー、なるほどと思える様に書き残しました。


    import UIKit

    class ViewController: UIViewController ,UITextFieldDelegate{

    @IBOutlet weak var inputText_1: UITextField!

    @IBOutlet weak var inputText_2: UITextField!

    @IBOutlet weak var outputText: UILabel!
    override func viewDidLoad() {
    super.viewDidLoad()
    inputText_1.delegate = self
    inputText_2.delegate = self

    // Do any additional setup after loading the view.
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    let text = textField.text
    outputText.text = text
    return true
    }


    }

    キャンセル

  • 2020/03/26 14:49

    > もっと、早くエラーコードをみて、すぐ当たりをつけることができる経験値を積みたいです!。


    実は、単にエラーメッセージのうち汎用的な部分(this class is not key value coding-compliant for)だけを検索しただけです。

    for の先は具体的なインスタンス名などになっていて、検索キーワードのノイズになってしまいますから、どのようなエラーでも同じく表示される部分だけで検索すれば比較的容易に見つかると思います。


    JavaScriptで比較できる例があれば、それに照らし合わせてみるのが一番いいかもしれませんね。他言語での知識は新しい言語の獲得に役立つと思います。

    この先の話になりますが、じゃあ「ふたつのTextFieldのうち、どちらから呼び出されたのか」という疑問が出てくることも間近だとおもいますが、それはtyobigorouご指摘の==を使った比較や(つい最近、どなたかが質問されて、自己解決した質問にもありました)、あるいはtagをつける方法で解決できますので、そのときに思い出されるといいかとおもいます。

    キャンセル

  • 2020/03/26 16:14

    ご丁寧なご説明を賜り、またずっと同じことを考えていたので、なんとなく理解が進んできました。
    ちょっと、混乱を避けるためにいったん頭を少しスッキリさせて整理してみたいと思います!

    本当にご親切にありがとうございました!

    キャンセル

0

コードを見ても私にはoutputTextはUILabelのインスタンスとして読み取れず、

以下のように outputText は UILabel! と宣言されてますので、outputText は UILabel のインスタンスですね。

  @IBOutlet weak var inputText: UITextField!
  @IBOutlet weak var outputText: UILabel!

後段との因果関係、なぜUITextFieldのインスタンスまたはUILabelのインスタンスであれば文字列を渡せるのかをご教示願えますでしょうか?

以下の 2 行ですが、まず最初の行で textField の text プロパティ、つまり入力されたテキストを text という変数に代入します。次に、その text を outputText というラベルの text プロパティ、つまりラベルに表示されるテキストとしてセットします。

    let text = textField.text
    outputText.text = text

「なぜUITextFieldのインスタンスまたはUILabelのインスタンスであれば文字列を渡せるのか」という質問がいまいち理解できてませんが、
・UITextField はテキスト入力欄であり、入力されたテキストを text プロパティで取得できる
・UILabel はテキストを表示するラベルで、表示するテキストは text プロパティで指定する
ということが分かれば、コードの意味も理解できるのではないでしょうか。

inputText.delegate = selfの様な記法にけるクラスはそのクラス全体を指している

inputText.delegate = self にはクラスは出てきません。self のことであれば、ViewController クラスのインスタンスそのものを指します。(あまりインスタンス「全体」とは言いませんが、インスタンスの一部ではないという意味で「全体」と言えないこともないとは思います。)

以上、回答になってるといいのですが。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/03/26 16:17

    コメントをいただきありがとうございます。
    概ねご回答については理解することができました。

    また、私の当初の質問に致命的なタイポがあり誤解を招いてしまい、申し訳ございません。

    コードを見ても私にはoutputTextはUITextField のインスタンスとして読み取れず、どちらのインスタンスであったとしても、後段の以下の文章との因果関係を読み解くことができません。

    と修正しているのですが、UITextField の箇所をあろうことかUILabelにしてしまっていました。大変失礼いたしました。

    よろしくお願い申し上げます。

    キャンセル

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

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