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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Objective-C

Objective-Cはオブジェクト指向型のプログラミング言語のひとつです。C言語をベースにSmalltalkが取り入れられています。

mBaaS

mBaaSとはモバイルアプリケーションでの利用に特化したBaaSです。スマートフォン向けのWebアプリケーションが必要とするサーバ側の様々な機能をインターネットを通じてサービスとして提供しています。

ニフティクラウドmobile backend

ニフティクラウドmobile backend (mBaaS)はニフティが提供するBaasサービスです。プッシュ通知、データストア、ファイルストア、会員管理・認証機能などのバックエンド機能をクラウドから提供しています。 Andoird/iOS/JavaScript/Unityと各種SDKに対応しています。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Q&A

解決済

2回答

411閲覧

iOSアプリでクラウドから取得した値を配列に格納できない

donarudo

総合スコア15

Objective-C

Objective-Cはオブジェクト指向型のプログラミング言語のひとつです。C言語をベースにSmalltalkが取り入れられています。

mBaaS

mBaaSとはモバイルアプリケーションでの利用に特化したBaaSです。スマートフォン向けのWebアプリケーションが必要とするサーバ側の様々な機能をインターネットを通じてサービスとして提供しています。

ニフティクラウドmobile backend

ニフティクラウドmobile backend (mBaaS)はニフティが提供するBaasサービスです。プッシュ通知、データストア、ファイルストア、会員管理・認証機能などのバックエンド機能をクラウドから提供しています。 Andoird/iOS/JavaScript/Unityと各種SDKに対応しています。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

0グッド

0クリップ

投稿2018/11/08 13:59

編集2018/11/15 14:09

前提・実現したいこと

objective-Cを使ったアプリを開発しています。
クラウドのデータストアに保存された値を検索し、検索された値を配列に保存し、カスタムセルに配置したラベルにテキストとして反映されたいと思います。
ちなみ使用しているクラウドはニフクラ mobile backendです。
ニフクラドキュメント https://mbaas.nifcloud.com/doc/current/
実行してビルドは通るのですが、セルを表示する画面になるとアプリがクラッシュします。
(11/10プログラム修正しました)

発生している問題・エラーメッセージ

クラッシュする際に表示されるエラーメッセージがこちらです。 -[__NSCFString objectAtIndexedSubscript:]: unrecognized selector sent to instance 0x114e12a20

該当のソースコード

//hファイルです。 #import <UIKit/UIKit.h> #import "TransitionObj.h" #import "CustomCell.h" @interface SecandViewController : UIViewController<UITableViewDelegate,UITableViewDataSource> //@property (weak, nonatomic) IBOutlet UILabel *l1v; @property (strong, nonatomic) TransitionObj* transitionObj; //@property (weak, nonatomic) IBOutlet UITextField *f2v; // テーブルビュー @property (weak, nonatomic) IBOutlet UITableView *tblView; @end

Objective

1//mファイルです。 2#import <Foundation/Foundation.h> 3#import "SecandViewController.h" 4#import "TransitionObj.h" 5#import "givewater.h" 6#import "CustomCell.h" 7#import "NCMB/NCMB.h" 8 9@interface SecandViewController ()<UITableViewDataSource, UITableViewDelegate> 10{ 11 12} 13 14@end 15 16// テーブル表示件数 17//const NSInteger historyNumber = 100; 18 19@implementation SecandViewController 20 21#pragma mark Life Cycle 22 23- (void)viewDidLoad { 24 [super viewDidLoad]; 25 self.msgs = [[NSMutableArray alloc] init]; 26 self.amountwaters = [[NSMutableArray alloc] init]; 27 self.dates = [[NSMutableArray alloc] init]; 28 self.realTemperatures = [[NSMutableArray alloc] init]; 29 self.damiTemperatures = [[NSMutableArray alloc] init]; 30 self.array = [[NSMutableArray alloc] init]; 31 32 // DelegateとDataSourceはstoryboard(またはxib)のところで結び付けるのでもO.K. 33 _tblView.delegate = self; 34 _tblView.dataSource = self; 35 36 // カスタムセルを使用 37 UINib *nib = [UINib nibWithNibName:@"CustomCell" bundle:nil]; 38 [_tblView registerNib:nib forCellReuseIdentifier:@"Cell"]; 39 40 [self kaeruQuery]; 41 42 43} 44-(void)kaeruQuery 45{ 46 NCMBQuery *query = [NCMBQuery queryWithClassName:@"HAGE"]; 47 // query.skip = 4; 48 [query orderByDescending:@"createDate"]; 49 query.limit = 40; 50 [query findObjectsInBackgroundWithBlock:^(NSArray *array, NSError *error) 51 { 52 if (!error) { 53 for (NCMBObject *obj in array) { 54 { 55 if ([obj objectForKey:@"kaerumsg"]) { 56 NSMutableArray* hoge1; 57 hoge1 = [obj objectForKey:@"kaerumsg"]; 58 [self.msgs addObject:hoge1]; 59 NSLog(@"%@",self.msgs); 60 } 61 if ([obj objectForKey:@"water"]) { 62 NSMutableArray* hoge2; 63 hoge2 = [obj objectForKey:@"water"]; 64 [self.amountwaters addObject:hoge2]; 65 NSLog(@"%@",self.amountwaters); 66 } 67 if ([obj objectForKey:@"date"]) { 68 NSMutableArray* hoge3; 69 hoge3 = [obj objectForKey:@"date"]; 70 [self.dates addObject:hoge3]; 71 NSLog(@"%@",self.dates); 72 } 73 if ([obj objectForKey:@"hikakuleaf"]) { 74 NSMutableArray *hoge4; 75 hoge4 = [obj objectForKey:@"hikakuleaf"]; 76 [self.realTemperatures addObject:hoge4]; 77 NSLog(@"%@",self.realTemperatures); 78 } 79 if ([obj objectForKey:@"damileaf"]) { 80 NSMutableArray *hoge5; 81 hoge5 = [obj objectForKey:@"damileaf"]; 82 [self.damiTemperatures addObject:hoge5]; 83 NSLog(@"%@",self.realTemperatures); 84 } 85 86 } 87 88 } 89 [self.tblView reloadData]; 90 } 91 92 93 }]; 94} 95 96 97#pragma mark UITableView 98 99// セクション数 100- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 101 return 1; 102} 103 104// セル数 105- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 106 107 return [self.array count]; 108 109} 110 111 112/* 113- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 114 115 return [self.amountwaters count]; 116 117} 118*/ 119// セルの内容を設定 120- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 121 122 NSLog(@"cellForRowAtIndexPath indexPath:%ld", indexPath.row); 123 124 // カスタムセルを取得 125 CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; 126 127 cell.date.numberOfLines = 0; 128 cell.amountwater.numberOfLines = 0; 129 cell.damiTemperature.numberOfLines = 0; 130 cell.realTemperature.numberOfLines = 0; 131 cell.msg.numberOfLines = 0; 132 133 134 cell.msg.text = [self.msgs objectAtIndex:indexPath.row]; 135 cell.amountwater.text = [self.amountwaters objectAtIndex:indexPath.row]; 136 cell.date.text = [self.dates objectAtIndex:indexPath.row]; 137 cell.realTemperature.text = [self.realTemperatures objectAtIndex:indexPath.row]; 138 cell.damiTemperature.text = [self.damiTemperatures objectAtIndex:indexPath.row]; 139 140 /* 141 cell.msg.text = self.msgs [indexPath.row]; 142 cell.amountwater.text = self.amountwaters [indexPath.row]; 143 cell.date.text = self.dates [indexPath.row]; 144 cell.realTemperature.text = self.realTemperatures [indexPath.row]; 145 cell.damiTemperature.text = self.damiTemperatures [indexPath.row];*/ 146 147 return cell; 148} 149 150// セルの高さ設定 151- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 152 153 NSLog(@"heightForRowAtIndexPath indexPath:%ld", indexPath.row); 154 155 //dequeueReusableCellWithIdentifier(セルを使用する) 156 CustomCell *Cell = [self.tblView dequeueReusableCellWithIdentifier:@"Cell"]; 157 158 //とりあえず固定値に 159 return 200; 160} 161 162/** 163 * 文字列に必要な高さを計算する処理 164 * @param text 文字列 165 * @return CGFloat 高さ 166 */ 167 168- (CGFloat)calcHeight:(NSString *)text { 169 170 // 端末サイズ取得 171 CGRect screen = [[UIScreen mainScreen] bounds]; 172 // 表示する幅 (40 + 8 * 3):画像の幅(40)とマージンの合計(8*3) 173 CGFloat width = screen.size.width - (40 + 8 * 3); 174 175 // 表示する最大幅と高さ 176 CGSize maxSize = CGSizeMake(width, CGFLOAT_MAX); 177 178 // 文字列のフォント種類、サイズなど属性を指定 179 NSDictionary *attrDic = @{NSFontAttributeName:[UIFont systemFontOfSize:15.0]}; 180 181 CGRect rect = [text boundingRectWithSize:maxSize 182 options:NSStringDrawingUsesLineFragmentOrigin 183 attributes:attrDic 184 context:nil]; 185 return rect.size.height; 186} 187 188 189// セル押下時の処理 190- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 191 192} 193 194#pragma mark Memory 195 196- (void)didReceiveMemoryWarning { 197 [super didReceiveMemoryWarning]; 198 // Dispose of any resources that can be recreated. 199} 200 201@end 202

//DBの中身
|damileaf|date|hikakuleaf||kaerumsg||water||createDate|
| |11/15|| | | ||value ||2018-11-15T21:29:37.942+09:00|
| value| || value | value || ||2018-11-15T21:29:37.942+09:00|
| |11/15|| | | ||value ||2018-11-15T21:29:37.942+09:00|
| value| || value | value || ||2018-11-15T21:29:37.942+09:00|
//以下省略しています,valueには何かしらの値が入っています

試したこと

NSLogを用いてデータが検索できているかどうか調べましたが、mBassからの検索はできています。
おそらくデータを配列に入れてテキストに表示させるところで間違っていると思いますので、どなたかご指摘よろしくお願いします。

補足情報(FW/ツールのバージョンなど)

iOS11.4
Xcode10.1

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

soo

2018/11/20 06:00

Firebaseを使うのがオススメです。
guest

回答2

0

自己解決

damileaf,hikakuleaf,kaerumsgとwatarの取得時期が違う為、画面を2つに分けて別個に処理することで解決しました。

投稿2018/12/24 07:42

donarudo

総合スコア15

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) { // ... (中略) // 検索に成功した場合の処理 NSLog(@"検索に成功しました。"); NSArray *hoge = objects; //型変換を行う NCMBObject *object = (NCMBObject*)hoge; // ←こんなことは出来ません

findObjectsInBackgroundWithBlock で取得した objects は
NCMBObject*が0個以上入っている配列(NSArray)です。
ですからキャストしちゃだめです。

投稿2018/11/08 14:30

daisuke7

総合スコア1563

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

donarudo

2018/11/10 05:18

コメントありがとうございます。 プログラムの方を修正したので、ご覧いただけるとありがたいです。
daisuke7

2018/11/11 06:34

クラッシュはどこで起きているのでしょうか? デバッグ実行してクラッシュした時の場所など分かりませんか?
donarudo

2018/11/12 01:44

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath の中のcell.msg.text = _msgs[indexPath.row];でクラッシュしています。
daisuke7

2018/11/12 03:05

_msgs は配列ではなく NSString* (単一の文字列)なんじゃないでしょうか?
donarudo

2018/11/12 11:36

プログラムを変更しました。 配列の定義なども間違ってるといけないので、割愛した箇所も載せました。 はい、setupDataクラスの中でNSLogで確認したのですが、クエリを送ってきちんと検索できてます。 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPathの中でcell.msg.text = (NSString*)msgs;とするとテキストは表示されるのですが、配列の0番目の文字列しか表示できません。やはり、ご指摘を受けた通り、単一の文字列になってしまっていると思います。[indexPath.row]で検索した配列の中身を全て表示させたいのですが上手く行かないです。
daisuke7

2018/11/12 11:47

msgsも配列(NSMutableArray)ですから、クエリ成功後のforループでは [msgs addObject:[object objectForKey:@"kaerumsg"]]; しないとおかしいです。
donarudo

2018/11/12 12:32

[msgs addObject:[object objectForKey:@"kaerumsg"]];としましたが、配列の中身が全て(null)になってしまいました。調べましたが、原因がよくわかりません。
daisuke7

2018/11/12 13:43

msgs ちゃんと確保してますか? msgs = [[NSMutableArray alloc] init]; みたいに
donarudo

2018/11/12 14:07

@implementation SecandViewControllerの後に - (NSMutableArray *)msgs{ if (!_msgs) { _msgs = [[NSMutableArray alloc] init]; } return _msgs; } 入れましたが、同じく配列の中身が(null)のままです。初期化の方法がまずいのでしょうか?
daisuke7

2018/11/12 14:11

msgsと _msgsがどういう扱いになっているのかよくわかりません。 もう一度今のソースコードを提示し直していただけますか? *.h *.m 両方です。
donarudo

2018/11/12 14:19

編集しました。分かりにくいところがあればご指摘願います。
daisuke7

2018/11/12 14:56

@propertyで定義するプロパティについて理解出来てないと思います。 @property (strong, nonatomic)NSMutableArray *msgs; としてください。ARC潰してないならretainではなくstrongです。 _msgs というアクセスの仕方は一切やめてください。そうではなく self.msgs と書きます。 また- (NSMutableArray *)msgs は定義する必要はありません。 viewDidLoad中で self.msgs = [[NSMutableArray alloc] init]; としてください。
donarudo

2018/11/13 11:11

self.msgs = [[NSMutableArray alloc] init];としたら配列の値が取得できなくなりました。 現在のソースコードを提示しなおすのでご指摘願います。
daisuke7

2018/11/13 11:56

numberOfRowsInSection が返す値は self.msgs.count でなければなりません。 また、おそらくクエリが完了する前にテーブルの描画が始まります。その時点では self.msgs.count は0でないとクラッシュします。
donarudo

2018/11/13 13:10

numberOfRowsInSection が返す値をself.msgs.count にしてしまうとCustomCellが生成されなくなります。 さらに配列の中身が"\U6c34\U304c\U8db3\U308a\U306a\U3044\U3088\U3002"などとおかしくなります。
daisuke7

2018/11/13 13:15

最初は0件なのでセルがないのは当然です。 まずUITableViewの理解からはじめた方が良いと思います。
donarudo

2018/11/14 09:49

daisuke7さま おかげさまでカスタムセルのテキストにDBから取得した値を表示することができました。 ありがとうございます。 しかし、2回に1回の割合でアプリがクラッシュします。 その際に表示されるメッセージがこちらです。 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array' 色々調べましたがどこが間違っているのか分かりません。 よろしければご指摘願います。
daisuke7

2018/11/14 10:36

[self setupData1] から[self setupData5] でmsgsなど5種類の配列それぞれにクエリ結果を読み込んでいますが、これらはどの順序で完了するかは分かりません。(非同期型のネットワークAPIを呼び出しているのでいつ戻ってくるかは分からない) またテーブルの行数は[self.amountwaters count] で取得していますが、self.amountwatersと他の配列の個数が同数かどうかは分かりません。想定データでは同数だったとしても、APIを非同期で呼び出しているため、「amountwatersは5件だがそれ以外はすべて0件」という状態もありえます。 その状況でreloadData()してしまうと、amountwaters以外の配列でも5件分読み出そうとしてクラッシュします。
donarudo

2018/11/15 13:18

daisuke7さま ソースコードを訂正しました。 DBからカスタムセルへの値の表示をし、アプリもクラッシュすることなく動作します。 しかし、damileaf,hikakuleaf,kaerumsgとdate,waterのプログラムで取得するタイミングが違うため、セルに表示した時ずれていってしまいます。(damileaf,hikakuleaf,kaerumsgの方が取得時期が先) daisuke7さまもおっしゃった通りテーブルの行数を[self.amountwaters count] で取得すると最新のwaterの値が表示できないので、書き換えたいと思いますが、書き方がよく分かりません。 ご指摘の方よろしくお願いします。
daisuke7

2018/11/15 13:53

[self.tblView reloadData]; を for()ループの後にしたら挙動変わりませんか? (いま { } が二重になっててわかりにくいですが、forループの中になっています) ずっと不思議なのは NCMBObject の配列をそのまま使っちゃだめなのかな、ってことですが…
donarudo

2018/11/15 14:12

ソースコード訂正しました [self.tblView reloadData];をforループの後にしましたが、挙動は変わりませんでした。 NCMBObject の配列をそのまま使いましたが、カスタムセルが表示されなくなりました。
daisuke7

2018/11/15 14:15

そうですか。これ以上は実際にデバッグしてみないと話が進まないかもしれませんね。お役に立てなくてごめんなさい。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問