いつもお世話になっております。
表題の件ですが、一回UITableViewをviewdidlaod内で生成し、値を表示した後に別の関数でもう一度cellに表示する値を取得しなおして一回目に生成したUITableViewを削除し、もう一回UITableViewを生成したいのですが、2回目以降からUITableViewを作成しようとしてもcellForRowAtIndexPathが呼ばれず、作成することができません...
調べてみると、numberOfRowsInSectionの値は0になっているとcellForRowAtIndexPathが呼ばれないとネットに書いてありましたが、NSLogで確認してみたところ、0にはなっていませんでした。
この原因がわかる方おりましたら教えていただけると幸いです。 以上です。 よろしくお願いいたします。
*追記
下記がUITableViewを更新しようとしているコードになります。
hoge.hの中
NSMutableDictionary *m_UserListDict;
@property (retain, nonatomic)NSMutableArray *hoge;
NSString *UserCnt;
NSString *str;
NSMutableArray *val;
hoge.mの中
int iUserCnt;
CGRect listView_windowsize;
float listView_height_windowsize;
float listView_width_windowsize;
- (void)viewDidLoad { //tableviewの生成
listView_windowsize = [[UIScreen mainScreen] bounds];
listView_height_windowsize = listView_windowsize.size.height;
listView_width_windowsize = listView_windowsize.size.width;
listtable = [[UITableView alloc] initWithFrame:[self.view bounds]];
listtable.frame = CGRectMake(0, 44 , listView_width_windowsize, listView_height_windowsize * 0.8);
listtable.delegate = self;
listtable.dataSource = self;
listtable.allowsMultipleSelection = YES;
[self.view addSubview:listtable];
}
- (void)OnEnterMember:(const char*)strUserId { //サーバーから通知を受け取る関数(ここも都合上、割愛させてもらってます)
[self performSelectorOnMainThread:@selector(DisplayList) withObject:nil waitUntilDone:YES];
}
-(void)get_data{ //サーバーからxml形式でデータを取得し、格納する。(サーバと通信してる部分等は省略してます)
m_UserListDict = [[NSMutableDictionary alloc]init];
[m_UserListDict setDictionary:UserList];
for (id key in m_UserListDict){
NSLog(@"%@,%@", key, m_UserListDict[key]);
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView //セクションの数を返す
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section //cellの数を返す
{
return self.hoge.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
static NSString *CellIdentifier = @"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.textLabel.text = [self.hoge objectAtIndex:indexPath.row];
return cell;
}
-(void)DisplayList{
[self get_data];
NSLog(@"isMainThread=%@", NSThread.currentThread.isMainThread?@"YES":@"NO");
str = [[NSString alloc]init];
val = [[NSMutableArray alloc]init];
self.userlistarray = [[NSMutableArray alloc]init];
UserCnt = [m_UserListDict objectForKey:@"UserCnt"];
iUserCnt = [UserCnt intValue];
for ( int i = 0; i < iUserCnt; i++){
str = [NSString stringWithFormat:@"%d", i];
val = [[m_UserListDict objectForKey:str] objectForKey:@"name"];
[self.hoge addObject:val];
}
NSLog(@"reloadDataの直前のlisttable=%@", listtable);
[listtable reloadData];
NSLog(@"reloadDataの直後のlisttable=%@", listtable);
userlistcnt = (int)[self.userlistarray count];
}
処理の流れとしてはm_UserListDictの中にあるnameというkeyで保存されている値をvalに入れてそれを self.hogeに入れて最後に[listtable reloadData];を行っている処理になります。 m_UserListDictの中身が空とかいう問題はありませんでした。
よろしくお願いいたします。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
まず、UITableViewを削除するのはやめましょう。
値を取得しなおした後、
[tableView reloadData];
とすればテーブルが更新されるはずです。
【追記】
サンプルコードです。 セルをタップするとセルが増えていきます。
#import "ViewController.h"
@interface ViewController ()
{
NSMutableDictionary *m_UserListDict;
NSString *UserCnt;
NSString *str;
NSMutableArray *val;
int iUserCnt;
UITableView *listtable;
}
@property (retain, nonatomic)NSMutableArray *hoge;
@end
#define _REUSEID @"hoge"
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//テーブル生成
listtable = [[UITableView alloc] initWithFrame:self.view.frame];
[self.view addSubview:listtable];
listtable.dataSource = self;
listtable.delegate = self;
[listtable registerClass:UITableViewCell.class forCellReuseIdentifier:_REUSEID];
//m_UserListDict初期化
m_UserListDict =
@{
@"UserCnt": @"3",
@"0": @{@"name": @"zero"},
@"1": @{@"name": @"one"},
@"2": @{@"name": @"two"},
}.mutableCopy;
//NSLog(@"%@", m_UserListDict);
//hoge初期化
[self DisplayList];
}
//セル数を返す
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.hoge.count;
}
//セル生成
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//セル取得
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:_REUSEID];
//セル設定
cell.textLabel.text = self.hoge[indexPath.row];
return cell;
}
//セルタップ時に呼ばれる
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//m_UserListDictに追加 (この中はあまり気にしないで下さい)
{
//key生成
NSString *key = @(self.hoge.count).stringValue;
//obj生成
NSNumberFormatter *nf = NSNumberFormatter.new;
nf.locale = [NSLocale localeWithLocaleIdentifier:@"en_US"];
nf.numberStyle = NSNumberFormatterSpellOutStyle;
NSString *name = [nf stringFromNumber:@(self.hoge.count)];
m_UserListDict[key] = @{@"name": name};
//UserCnt+1
m_UserListDict[@"UserCnt"] = @([m_UserListDict[@"UserCnt"] integerValue] + 1).stringValue;
}
//更新
[self DisplayList];
}
//hoge更新
// reloadDataをループの外に出した以外は変更無しです
-(void)DisplayList
{
str = [[NSString alloc]init];
val = [[NSMutableArray alloc]init];
self.hoge = [[NSMutableArray alloc]init];
UserCnt = [m_UserListDict objectForKey:@"UserCnt"];
iUserCnt = [UserCnt intValue];
NSLog(@"UserCnt=%zd", iUserCnt);
for ( int i = 0; i < iUserCnt; i++){
str = [NSString stringWithFormat:@"%d", i];
val = [[m_UserListDict objectForKey:str] objectForKey:@"name"];
[self.hoge addObject:val];
}
[listtable reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.13%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2015/12/09 16:42
試してみましたが、更新されませんでした...値を取得し直すというのは,
cellForRowAtIndexPath内で,
cell.textLabel.text = [self.hoge objectAtIndex:indexPath.row];
というようにhogeの中身を表示しているのですが、hogeの中身を取得し直すタイミングで
[tableView reloadData];をすればよろしいのでしょうか??
2015/12/09 16:52 編集
2015/12/09 16:58
2015/12/09 17:01
2015/12/09 17:03
2015/12/09 17:07
更新する前は何も表示していない状態ですが、reloaddataをする前は何か一つでも値が入っていなければダメなのでしょうか?
2015/12/09 17:14
2015/12/09 17:30
はい。cellが表示されてない状態です。hogeの中身が空ということです。
2015/12/09 17:38 編集
numberOfRowsInSection は { return hoge.count; }
だと仮定して、例えば、
[hoge addObject:@"hogehoge"];
[tableView reloadData];
としても何も表示されないでしょうか?
2015/12/09 18:24
自作の関数内で処理を行っているので、[listtable reloaddata];というように記述しているのですがそれがいけないのでしょうか?
[tableView reloaddata];だと自作関数内ではエラーが出てしまうので、listtableというUITableVIewを生成した際に自分でつけた名前の方できじゅつしているのですが、それが原因だったりするのでしょうか??
2015/12/09 18:33 編集
なんとなくですが、TableView周りの設定が出来ていないような気がしてきました。
UITableViewDataSourceとかUITableViewDelegateは設定しているでしょうか?
2015/12/09 19:01
2015/12/09 21:21 編集
hoge = [NSMutableArray arrayWithObjects:@"A",@"B",@"C",nil];
などとして初期化し、テーブルが表示されるかどうか、表示されない場合、numberOfRowsInSection や cellForRowAtIndexPath が呼ばれているかどうかを確認してみて下さい。
2015/12/10 09:18
試してみたところ、TableViewは正常に動いています。
やはり、更新するところがうまくいかないみたいです...
2015/12/10 09:19
2015/12/10 09:31
質問にコードを追記します。
2015/12/10 09:42
よろしくお願いいたします。
2015/12/10 10:03
NSLog(@"%@", m_UserListDict); としたときに、
{
0 = {
name = zero;
};
1 = {
name = one;
};
2 = {
name = two;
};
UserCnt = 3;
}
正しければ、こんな感じで表示されるはずです。
あと、[listtable reloadData]; はforループの外に出して下さい。(中でも動きますが無駄なので)
2015/12/10 10:15
わかりました。reloaddataをループの外に出します。
しかしまだ、更新はされません...
2015/12/10 10:48
2015/12/10 10:50
確認してみます!!
2015/12/10 14:04
2015/12/10 14:43
hirahasuさんのソースで、reloadDataの前に NSLog(@"listtable=%@", listtable); を入れてlisttableの値を確認してみて下さい。nilになっていないでしょうか?
2015/12/10 15:00
reloadの前にlisttableをもう一度生成すれば良いのでしょうか?
2015/12/10 15:12 編集
・定義部分(私のソースでは UITableView *listtable;)
・生成部分(私のソースでは listtable = [[UITableView alloc] initWithFrame:self.view.frame];)
を教えて下さい。(定義部分は、どこで定義しているかも書いて下さい)
その他、listtableに何か代入している箇所があればそれも教えて下さい。
2015/12/10 15:19
UITableView *listtable;
生成部分が
listtable = [[UITableView alloc] initWithFrame:[self.view bounds]];
listtable.frame = CGRectMake(0, 0 , listView_width_windowsize, listView_height_windowsize * 0.8);
listtable.delegate = self;
listtable.dataSource = self;
listtable.allowsMultipleSelection = YES;
[self.view addSubview:listtable];
listView_width_windowsizeとlistView_height_windowsizeはfloat型で画面の大きさを[[UIScreen mainScreen] bounds];で取得し、計算してtableviewの大きさ決めています。
代入しているものが特にありません。
2015/12/10 15:47
DisplayListはどういうタイミングで呼んでいるのでしょうか?
2015/12/10 17:31
DisplayListはサーバと通信をして、新しい値を取得したら呼ぶようにしています。
2015/12/10 18:01 編集
NSLog(@"isMainThread=%@", NSThread.currentThread.isMainThread?@"YES":@"NO");
を入れてみて下さい。
もし NO なら、reloadDataの呼び出しを、
dispatch_async(dispatch_get_main_queue(), ^{
[listtable reloadData];
});
として、メインスレッドで実行するようにしてみて下さい。
(dispatch_async じゃなくて dispatch_sync の方が安全かも)
2015/12/10 18:17
[listtable reloadData];
});を記述したところ、numberOfRowsInSectionがよばれるようになりました。
しかし、cellForRowAtIndexPathがよばれません...
2015/12/10 18:25
numberOfRowsInSection が0を返していませんか?
2015/12/10 18:33
2015/12/10 18:40
2015/12/10 18:46
なので、dispatch_asyncで呼ばれてないことになります。
わかりにくくて大変申し訳ありません...
もう一度、ソースコードを綺麗にして明日、再チャレンジしてみることにします。
2015/12/11 14:08
2015/12/11 14:56
あと、現在のコードを書いて下さい。(可能な限りコードを書いて下さい。コードがない状態では前に進みません)
2015/12/11 15:05
わかりました。
可能な限りでソースコードを追記いたします。
2015/12/11 15:45
よろしくお願いいたします。
2015/12/11 16:38
2015/12/11 16:47
UITableView *listtable;
}
という様に定義してます。
2015/12/11 17:02
2015/12/11 17:05
2015/12/11 17:30
2015/12/11 17:43
listtable生成(initFrameWith)の直後でlisttableの値を調べてみてください。
あと、
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(@"[viewWillAppear] listtable=%@", listtable);
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(@"[viewDidAppear] listtable=%@", listtable);
}
を追加して値を調べてみてください。
2015/12/11 17:50
そして確認したところviewdidloadが二回呼ばれていました....
viewdidiloadでtableviewを生成しているのでfuzzballさんのおっしゃる通り二回生成していることになってますね...
2015/12/11 17:57
2015/12/11 18:06
追記しておきます。