20846


Appleのプログラミングガイドを参考にして同じコードを書いてみました。

[code]

    // RootViewController.h
    @interface RootViewController: UIViewController {
    }
    @end
    
    @interface RootViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
    @property (nonatomic, strong) NSArray *timeZoneNames;
    @end
    
    // RootViewController.mm
    #import "RootViewController.h"
    
    @implementation RootViewController
    - (void)loadView {
        self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease];
        self.view.backgroundColor = [UIColor whiteColor];
    
        UITableView *tableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStylePlain];
    
        tableView.delegate = self;
        tableView.dataSource = self;
        [tableView reloadData];
    
        self.view = tableView;
    }
    
    - (NSInteger)numberOfSectionInTableView:(UITableView *)tableView {
        return [regions count];
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowInSection:(NSInteger)section {
        Region *region = [regions objectAtIndex:section];
        return [region.timeZoneWrappers count];
    }
    
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
        Region *region = [regions objectAtIndex:section];
        return [region name];
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        static NSString *MyIdentifier = @"MyReuseIdentifier";
    
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
    
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
        }
    
        Region *region = [region objectAtIndex:indexPath.section];
        TimeZoneWrapper *timeZoneWrapper = [region.timeZoneWrappers objectAtIndex:indexPath.row];
        cell.textLabel.text = timeZoneErapper.localeName;
        return cell;
    }
    @end
    
[/code]

このようなコードでビルドすると、次のようなエラーが出ます。どこが間違っているのでしょうか？[![enter image description
here](https://i.stack.imgur.com/4kmcG.jpg)](https://i.stack.imgur.com/4kmcG.jpg)

[![enter image description
here](https://i.stack.imgur.com/qDGf5.jpg)](https://i.stack.imgur.com/qDGf5.jpg)


CC BY-SA 3.0
2016-01-11T13:46:58.543
20834
2016-01-14T06:21:23.063
2016-01-11T15:28:26.730
5519
13963
question
ios objective-c
UITableViewを使ってセルを表示させ項目をセットしたい


Objective-Cの基礎について説明します。Objective-
Cのプログラムコードは、ファイル分割して作成する場合、ヘッダファイル（`.h`）と実装ファイル（`.m`）の2ファイルで構成します。  
（実装ファイルの拡張子は、`.m`です。`.mm`は、C++のコードが混在する場合につける拡張子です。）  
基本構文（テンプレート）はこうなります。クラス`Template`を定義するものとします。

_Template.h_

[code]

    #import <Foundation/Foundation.h> // 必要なフレームワーク等をインポート。
    
    @interface Template: NSObject // コロンの後ろに継承するSuper Classを記述する。
    
    // 公開する（Publicな）プロパティとメソッドを宣言。
    
    @end
    
[/code]

_Template.m_

[code]

    #import "Template.h" // ヘッダファイルをインポート。
    
    // クラスエクステンション（Class Extension）。クラス名の後に()を付ける。
    @interface Template () {
        // インスタンス変数を宣言。
    }
    
    // 非公開（Privateな)プロパティとメソッドを宣言。
    
    @end
    
    @implementation Template
    
    // 実装を記述。
    
    @end
    
[/code]

なぜ`@interface`宣言がふたつあるかというと、公開するプロパティ、メソッドと、非公開のものを区別する意図から、そういう構成にしています。ここらへんはけっしてAppleの推奨通りにする必要はありませんが、実用的に、ヘッダファイルと実装ファイルを行き来する行為を大幅に減らせるというメリットがあるので、素直に従ったほうがいいでしょう。

* * *

つぎに、名称の **プレフィックス** の話をします。  
プログラムは大規模になると、複数のプログラマが従事することになりますが、そうなると心配されるのが、名称の重複、バッティングです。Javaなどの新しい言語では、名前空間（Namespace）という概念が導入されて、名称の有効範囲を限定することで、名前の重複があっても、たがいに影響を与えない工夫がなされています。しかしObjective-
Cは、いまとなっては古い言語なので、名前空間はありません（注）。代わりに、名称を長くするという工夫が施されています。Objective-
Cのメソッド名や、定数名は、キーボードで入力したくないくらい長いものが多いのですが、理由の第一は、メソッドがどういうことをしてくれるのか、定数がなにを指しているのか、マニュアルを読まなくても、おおむね理解できるようにというもので、第二にこの名前の重複を避けるという目的があります。  
iOSで使われるクラス名は、`NS`や`UI`という大文字2〜3文字で始まります。`NSArray`、`UITableView`などですね。これらをプレフィックスと呼びます。`UI`は、`UIKit`フレームワークに属するクラス名などについています。`NS`は、`Foundation`フレームワークに属するものに付けられます。`NS`は、「Next
Step」の略で、（Mac） OS
Xの前身（の前身）であるNext社のOSの名称に由来するという、歴史的背景のある名称です。ほかに、`CGRect`、`CGPoint`といった構造体の名称のプレフィックス`CG`は、`Core
Graphics`フレームワークに属していることを表しています。こうしたプレフィックスの存在で、名前の重複をかなりのケースで回避することができます。  
さて、ここから本題ですが、サンプルコードを読み解いていると、プレフィックスが付いていないクラス名が出てきます。`RootViewController`や`Region`といったクラスがそれです。それは既存のフレームワークに属していないクラスだと判断できます。そのプロジェクトでのみ使うクラス、プログラマが定義したクラスなのです。よって、たとえサンプルコードを丸写ししたのだといっても、プレフィックスのないクラスについては、プログラマが自身の責任で定義、実装しなければ、「未定義の識別子」という理由でエラーの元になります。

* * *

以上2点を念頭に置いて、コードを書きかえれば、目的は達成できないにしても、エラーの出ないプログラムにはできるはずです。

注：古い言語たとえばC言語でも名前空間に似た考え方はあります。ローカル変数の有効範囲を`{〜}`に限定することで、名前の重複が悪影響を出さないようにしています。

_C言語のコード_

[code]

    #include <stdio.h>
    
    int main() {
        int a;
        a = 100;
        {
            int a;
            a = 200;
            printf("Local a = %d\n", a); // Local a = 200
        }
        printf("Global a = %d\n", a); // Global a = 100
    
        return 0;
    }
    
[/code]

Objective-Cは、C言語の拡張なので、ローカル変数の有効範囲も同様です。


CC BY-SA 3.0
2016-01-12T03:13:48.203
20846
2016-01-14T06:21:23.063
2016-01-14T06:21:23.063
8000
7362
20834
answer