28482

[code]

    import UIKit
    
    class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource  {
        @IBOutlet weak var tableView: UITableView!
    
        var dataArray:[Int] = []
    
        // ボタンが押された時にデータを追加する
        @IBAction func add(sender: UIBarButtonItem) {
            dataArray.append(dataArray.count)
            tableView.reloadData()
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
        // MARK: UITableViewDataSource プロトコルのメソッド
        // TableView の各セクションのセルの数を返す
        func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return dataArray.count
        }
    
        // 各セルの内容を返す
        func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
            // 再利用可能な cell を得る
            let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell")
    
            // Cellに値を設定する.
            cell.textLabel?.text = "\(dataArray[indexPath.row])"
            cell.detailTextLabel?.text = "Subtitle \(dataArray[indexPath.row])"
    
            return cell
        }
    }
    
[/code]

いくつか質問があります。  
上記のプログラムで

[code]

    @IBOutlet weak var tableView: UITableView!
    
[/code]

このtableViewは関数ですか？それともインスタンスですか？

また

[code]

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataArray.count
    }
    
[/code]

で引数となっているnumberOfRowsInSectionはメソッドだと思うのですが  
それがどうして引数になるのですか？

最後にこのプログラムは関数を定義しているだけなのに  
どうして実行するのかが分かりません。

たくさんの質問をすいませんがよろしければ  
回答を宜しくお願いします。


CC BY-SA 3.0
2016-08-21T10:09:08.880
28410
2016-08-25T11:08:14.770
2016-08-21T10:14:32.263
5337
18539
question
swift xcode uitableview
UITableViewを使ったプログラム内のインスタンス、関数、引数について


> `@IBOutlet weak var tableView: UITableView!`  
>  このtableViewは関数ですか？それともインスタンスですか？

`tableView`は、 **プロパティ**
（Property）です。その下の`dataArray`と同じ。`@IBOutlet`、`weak`など修飾子が複数ついていますが、それらを外してしまえば、`tableView`はひとつの
**変数** です。  
たとえていうなら、変数は容器を指し、 **インスタンス**
は、その内容を指します。質問の文脈からすれば、`tableView`は容器、すなわち変数とみるべきです。  
置いてある場所や、使い道によって、同じモノでも、異なる名称になるのは、私たちの日常でよくあることです。Swiftにおいても、クラスや構造体などに属する関数のことを、
**メソッド** （Method）、クラスや構造体などに属する変数のことを **プロパティ** と呼びます。  
以上から、`tableView`は、プロパティと呼ぶのが妥当です。  
なお、プロパティには2種類あり、 **格納型プロパティ** （Stored Property）、 **計算型プロパティ** （Computed
Property）に分かれます。ここでは格納型プロパティを指しています。  
そして、プロパティについて勉強していくと、プロパティが単なる変数ではなく、じつはもっと複雑なものだということがわかってきます。学習を重ね、知識を深めていってください。

> `func tableView(tableView: UITableView, numberOfRowsInSection section: Int)
> -> Int`  
>  で引数となっている`numberOfRowsInSection`  
>  はメソッドだと思うのですが それがどうして引数になるのですか？

メソッドではありません。 **ラベル** （Argument Label）です。  
関数（メソッド）は、関数の引数にはなりません。ひとまとまりのプログラムを、引数に渡したいことは、ままありますが、そういう用途には、 **クロージャ**
（Closure）が用意されています。  
関数の書式について、基礎部分を説明します。Swiftは、C言語の書式を踏襲したものになっていますが、随所にC言語と異なる箇所があります。  
関数の基本書式は、

[code]

    // 定義の書式
    func area(width: Float, height: Float) -> Float {
        return width * height
    }
    
    // 呼び出す書式
    let a = area(100.0, height: 100.0)
    
[/code]

関数を呼び出すとき、第2引数以降に、ラベル`height`がつくのが、Swiftの特徴です。

※ここでは、Swift2に基づいて説明をしています。Swift3では、第1引数だけ特別扱いするのは、複雑なだけでわかりにくいという意見を取り入れて、第1引数にもラベルがつくようになります。

[code]

    func area(width: Float, height: Float) -> Float {
        return width * height
    }
    
    let a = area(width: 100.0, height: 100.0)
    
[/code]

基本書式では、引数名がそのままラベル名になりますが、引数名とラベル名を異なるものにすることが可能です。

[code]

    func area2(width w: Float, height h: Float) -> Float {
        return w * h
    }
    
    let b = area2(width: 100.0, height: 100.0)
    
[/code]

ラベル名と引数名を併記して定義します。  
質問の`func tableView(tableView: UITableView, numberOfRowsInSection section: Int)
-> Int`は、このパターンの書式に該当します。`numberOfRowsInSection`がラベルで、`section`が引数です。  
ついでに、いちいち引数にラベルをつけるのは、うざったいと考える向きには、ラベルを省略する書式も用意されています。

[code]

    func area3(w: Float, _ h: Float) -> Float {
        return w * h
    }
    
    let c = area3(100.0, 100.0)
    
[/code]

アンダーバー（_）を使って、省略を指示します。

> 最後にこのプログラムは関数を定義しているだけなのに どうして実行するのかが分かりません。

この点については、 **デリゲート**
（Delegate）というデザインパターンについて勉強していただく必要があります。iOSのフレームワークにおいては、多用されるデザインパターンですので、いちど腰を据えて学習するだけの価値があります。  
とりあえずかんたんに説明します。Delegateは、直訳すると、「委譲」、「委託」となります。  
`UITableView`は、いうまでもなくテーブルを表示するViewですが、テーブルを表示するには、まず表示するデータ、セクションの数、セクションごとの行数、行ごとの高さ、セルごとに表示するデータなどなど、多数の要素が決定しないと、なにも始まりません。たとえば、`UIImageView`は、イメージを表示するViewですが、サイズとイメージデータを、インスタンスのプロパティとして代入すれば、イメージが表示されます。`UITableView`でも、いくら必要な要素が多数あるとしても、すべてプロパティに代入すれば、コンテンツの表示はできるはずです。  
しかし、`UITableView`は、必要な要素を内部のプロパティに持つのではなく、そのほとんどを、外部の別のインスタンスに委託するという形態を取っています。`UITableView`は、`ViewController`インスタンスに定義してある`func
tableView(tableView: UITableView, numberOfRowsInSection section: Int) ->
Int`というメソッドを呼び出して、自らのセクションごとの行数を決定します。  
このメソッドは「呼ばれていないのに実行される」のではなく、`UITableView`が呼んだので、実行されます。

※C#などでは、Delegateは言語の一部として扱われますが、Swiftはそうではありません。純粋にSwiftに関する書籍、情報だけあたってみても、Delegateに関する記述が見つからないことがあります。iOSや、UIKitに関連づけて検索したほうがいいでしょう。


CC BY-SA 3.0
2016-08-25T07:41:55.023
28482
2016-08-25T11:08:14.770
2016-08-25T11:08:14.770
18540
18540
28410
answer