20367


現在`Xib`で`UIView`を一つ置き、その`UIView`の中に`UITableView`を置いてます。  
そしてコードは以下のように書きました。

[code]

    @implementation CategoriesViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        CategoriesView *categoriesView = [[CategoriesView alloc] initWithFrame:self.view.bounds];
        [self.view addSubview:[categoriesView loadFromNib]];
    }
    
    @end
    
    
    @implementation CategoriesView {
        NSMutableArray *categoriesArray;
    }
    
    - (id)initWithFrame:(CGRect)frame {
        if (self = [super initWithFrame:frame]) {
            categoriesArray = [[NSMutableArray alloc] initWithObjects:@"食品", @"服", @"おもちゃ", @"家電", @"本", nil];
        }
    
        return self;
    }
    
    - (id)loadFromNib {
        return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:nil options:nil] firstObject];
    }
    
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        return [categoriesArray count];
    }
    
    -(UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
        cell.textLabel.text = categoriesArray[indexPath.row];
    
        return cell;
    }
    
    @end
    
[/code]

以上を実行すると、中身のないテーブルビューが表示されます。  
`tableview.delegate`と`tableview.dataSource`は`Storyboard`で設定しており、それぞれ`UIView`を継承した「CategoriesView」に紐付けています。  
試しにログを取ってみると、initWithFrameを通った時にはcategoriesArrayにきちんと全ての値が入っていたのですが、numberOfRowsInSectionの中を通る時にはcategoriesArrayはnilになっていました。これがいけないのだと思うのですが、なぜcategoriesArrayがnilになってしまうのでしょうか？`Xib`で`UITableView`を扱う時には何か他にしなければならないことがあるのでしょうか？  
どなたか解決できる方がいれば教えていただきたいです。よろしくお願いします。


CC BY-SA 3.0
2015-12-25T08:24:32.587
20364
2015-12-25T21:28:09.840
5210
question
ios objective-c xcode storyboard xib
Xibを使って生成したTableViewのデリゲートメソッドが呼ばれない


`CategoriesView`インスタンスを2回生成するプログラムになってますね。

[code]

    CategoriesView *categoriesView = [[CategoriesView alloc] initWithFrame:self.view.bounds];
    
[/code]

ここで、コードから生成。（1回目）

[code]

    [self.view addSubview:[categoriesView loadFromNib]];
    
[/code]

この`[categoriesView loadFromNib]`で、XIBから生成して2回目。  
で、`self.view`が`addSubview:`しているのは、無名の`CategoriesView`インスタンスであって、`categoriesView`でないということになっています。  
これが不具合の原因というわけではありませんが、無意味なことをしている点は、指摘しておかなければいけません。

それで、不具合の原因は、こちらです。  
InterfaceBuilder、Storyboardから生成したオブジェクトは、`init`で始まるイニシアライザを実行しません。初期化処理はすべてXIBファイル、.storyboardファイルに記述されています。なので、`categoriesArray`を生成する処理は行われず、この配列インスタンスは`nil`になります。  
XIB、.storyboardに書かれていない初期化処理をするときは、`awakeFromNib`メソッドないし`initWithCoder:`メソッドに実装します。

* * *

改善案を載せておきます。

[code]

    @implementation CategoriesViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        CategoriesView *categoriesView = [[[NSBundle mainBundle] loadNibNamed: @"CategoriesView" owner:nil options:nil] firstObject];
        categoriesView.frame = self.view.bounds;
        [self.view addSubview:categoriesView];
    }
    
    @end
    
    @implementation CategoriesView {
        NSMutableArray *categoriesArray;
    }
    
    - (void)awakeFromNib {
        [super awakeFromNib]; // この行は不用かもしれません。
    
        categoriesArray = [[NSMutableArray alloc] initWithObjects:@"食品", @"服", @"おもちゃ", @"家電", @"本", nil];
    }
    
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        return [categoriesArray count];
    }
    
    -(UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
        cell.textLabel.text = categoriesArray[indexPath.row];
    
        return cell;
    }
    
    @end
    
[/code]


CC BY-SA 3.0
2015-12-25T09:31:56.747
20367
2015-12-25T21:28:09.840
2015-12-25T21:28:09.840
7362
7362
20364
answer