オブジェクトのインスタンス変数について

このQ&Aのポイント
  • オブジェクトのインスタンス変数についての疑問
  • AppDataという共有データモデルクラスの配列データをviewControllerのリストにセットして表示させたいがうまくいかない
  • ポインタやインスタンス変数の寿命についての理解が必要。どうすればうまく動かすことができるか教えてください
回答を見る
  • ベストアンサー

オブジェクトのインスタンス変数について

AppDataというどのクラスからもアクセスできるデータモデルクラスを作り、AppDataに格納された配列のデータを viewControllerがもつリストにセットして、テーブル表示させたいのですがうまくいかないのです。 自分の考えではポインタをきちんと理解していないorオブジェクトのインスタンス変数の寿命を把握していない。 なぜ動かないのか??どういった部分を勉強するべきか??教えていただければ幸いです! プログラムは省略してあります。 AppDelegateクラス - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { AppData *share = [AppData sharedData]; //共通データクラス作成完了 viewController.list = share.responseJsonDataArray; ←●ここが動きません!! デバッグさせるとresponseJsonDataArrayが初期化されていませんでした。 } AppDataクラス +(AppData *)sharedData { if (!_appData) { _appData = [[AppData alloc] init]; } responseJsonString = [[NSString alloc] init]; responseJsonDataArray = [[NSMutableArray alloc] initWithObjects:@"kou",@"kou",nil]; ↑ここに入ったデータを呼び出してテーブル表示させたい!! return _appData; } よろしくお願い致します!!

質問者が選んだベストアンサー

  • ベストアンサー
  • harawo
  • ベストアンサー率58% (3742/6450)
回答No.1

※表題にObjective-CあるいはiOS SDKに関する質問であることを、わからせる語句を入れとかないと、答えてくれそうな人がスルーしてしまいそうですね。ご一考を。 +(AppData *)sharedData { if (!_appData) { _appData = [[AppData alloc] init]; } responseJsonString = [[NSString alloc] init]; responseJsonDataArray = [[NSMutableArray alloc] initWithObjects:@"kou",@"kou",nil]; ↑ここに入ったデータを呼び出してテーブル表示させたい!! return _appData; } これでもいけそうな気がしますが、標準的な初期化メソッドと、形がかけ離れているのはたしかです。また、標準の初期化メソッドは、[[~ alloc] init~]という形をとり、クラスメソッドをとる初期化メソッドは、autoreleaseを内包していることにするのが、規則ではありませんが、推奨される形態となっています。NSDataやNSArrayなどの初期化メソッドをお調べになるといいでしょう。 標準的な初期化メソッドにならって、上のメソッドを書き換えると、おおよそこうなります。 - (id)init { self = [super init]; if (self != nil) { responseJsonString = [[NSString alloc] init]; responseJsonDataArray = [[NSMutableArray alloc] initWithObjects:@"kou",@"kou",nil]; ↑ここに入ったデータを呼び出してテーブル表示させたい!! } return self; } クラスAppDataのプロパティresponseJsonDataArrayなどが、動的な変化をせず、常に同じ値で、定数的な扱いをするのならば、プロパティではなくて、クラスメソッドとして定義したほうが、使いやすいです。(その場合は、クラスAppDataの初期化メソッドは不要になります) クラスAppDataに実装するメソッドとして、 + (NSArray *)responseJsonDataArray { return [[NSArray alloc] initWithObjects:@"kou",@"kou",nil]; } こういうように定義し、AppDelegate内で、 viewController.list = [AppData responseJsonDataArray]; と呼び出します。

sutekicut
質問者

お礼

ありがとうございます!以後気をつけます!ご指摘ありがとうございます。 >※表題にObjective-CあるいはiOS SDKに関する質問であることを、わからせる語句を入れとかないと、答えてくれそうな人がスルーしてしまいそうですね。ご一考を。 おかげさまできちんと動きました! 原因は+(AppData *)sharedDataでした! 「クラスメソッドで、インスタンス変数に代入してはいけない。」といったことが 『詳解objectiveーC』のクラスメソッドに書いてありました。 一度initでインスタンス化してから インスタンス変数にアクセスすることで解決できました! このやり方なら、例えば「あるデータモデルオブジェクトをいろんなクラスで使い回す」といったことが可能になるという認識でよさそうですね! 大変、勉強になります! >クラスAppDataのプロパティresponseJsonDataArrayなどが、動的な変化をせず、常に同じ値で、定数的な扱いをするのならば、プロパティではなくて、クラスメソッドとして定義したほうが、使いやすいです。(その場合は、クラスAppDataの初期化メソッドは不要になります) ありがとうございます!

関連するQ&A

  • Objecive-C

    NSDictionary *row1 = [[NSDictionary alloc]initWithObjectsAndKeys:            @"MacBook",@"Name",@"White",@"Color",nil]; NSDictionary *row2 = [[NSDictionary alloc]initWithObjectsAndKeys:        @"MacPro",@"Name",@"Silver",@"Color",nil]; NSArray *array● = [[NSArray alloc]initWithObjects:row1,row2,nil]; これをplistを使って実現させようと思ったのですが、 NSString *path =[[NSBundle mainBundle]pathForResource:@"Celldata" ofType:@"plist"]; NSArray *array○ = [[NSArray alloc]initWithContentsOfFile:path]; *array●と*array○は同様の配列で実現可能ですか? plistに問題があるのでしょうか?。 plistは、下記です。 key Type Value Root Dictionary row1 Dictionary ( 2 items) Name String MacBooc Color String White

  • Objective-C グローバル変数 値変更反映

    当方、Objective-Cに関して1年にも満たない経験を持つ初心者です。 初歩的な内容だとは思いますが行き詰まってしまったため質問させて下さい。 複数の.hと.mファイルで定義された複数クラス間で一つの変数を共通で利用し、あるクラスのメソッド内で値を変更した際にそれ以外のクラスですぐに反映出来る様にしたいのですが、どの様に書いても値が反映されず初期値のまま出力されてしまいます。恐らく各クラス内のメソッドが呼ばれる順番に起因すると思うのですが、上手く解決出来ません。 現在書いているコードとして、 -xxxAppDelegate.h (at)interface xxxAppDelegate : NSObject <UIApplicationDelegate> { ... int globalNum; } (at)property(nonatomic, assign)int globalNum; (at)end -xxxAppDelegate.m ... (at)implementation xxxAppDelegate (at)synthesize globalNum; ... (at)end -A.h ... (at)interface AController : UIViewController { xxxAppDelegate *appDelegate; } ... -(void)changeNum; -(IBAction)changeController; (at)end -A.m ... (at)implementation AController ... - init(){ appDelegate = (xxxAppDelegate *)[[UIApplication sharedApplication] delegate]; } ... -(void)changeNum{ //ここでglobalNumの値を変更; appDelegate.globalNum=...; } ... //配置したボタンを押すとA->BにviewControllerを切り替える -(IBAction)changeController{ BController *B = [[BController alloc] initWithNibName:(at)"BController" bundle:nil]; B.modalTransitionStyle = UIModalTransitionStyleCoverVertical; [self presentModalViewController:B animated:YES]; [B release]; } ... (at)end -B.h ... (at)interface BController : UIViewController { xxxAppDelegate *appDelegate; } ... -(void)readNum; (at)end -B.m ... (at)implementation BController ... - init(){ appDelegate = (xxxAppDelegate *)[[UIApplication sharedApplication] delegate]; } ... -(void)readNum{ //globalNumの値を見る; NSLog((at)"%d" , appDelegate.globalNum); } ... (at)end となっています。( (at)=アットマークです。 ) xxxAppDelegateおよびxxxViewControllerよりAControllerを呼び出し、AクラスのchangeNumメソッドでglobalNumの値を変更した後、ボタンを押下してviewControllerをBControllerに切り替え、Bクラス内のreadNumメソッドでglobalNumの値を確認すると、変更が反映されていない事が分かります。 この方法以外にも色々と試してみたのですが、すっきりとしたコードが書けず、解決に至りませんでした。 申し訳ありませんが、皆さんの知恵をお貸し下さい。 よろしくお願いします。

  • Objective-Cクラス変数インスタンス変数

    現在iPhoneアプリを作成するために、Objective-Cの勉強をしています。しかしそこでわからないことがあり、質問させていただきました。 それは私がインスタンス変数(メンバ変数)を宣言してつかっているつもりなのですが、クラス変数の様な動きをするのです。 具体的にコードで説明します。 @implementation Main : NSObject - (void)hello{ [[Hoge alloc]init]; [[Hoge alloc]init]; } @end @implementation Hoge : NSObject NSNumber *i; - (id)init{ [super init]; NSLog(@"%d",i.intvalue); i = [NSNumber numberWithInt:123]; return self; } @end 出力結果 null 123 今手元にソースがないので正確ではないかもしれませんが、こんな感じです。hファイルにはとくになにもかいてません。 このソースの動きはmainでHogeクラスのインスタンスを二回作成することによって、initを二回呼んでいます。 疑問点は出力結果の挙動が予想外なことです。私としてはインスタンス作成時のiは初期化されていないため、 出力結果 null null になるのを期待しています。しかし二回目のinitでは前回に作成した123というデータが引き継がれています。この挙動はiはインスタンス変数ではなく、クラス変数のようにみえます。 しかしObjective-Cではクラス変数は存在しないとどっかのサイトに書いていました。 以上が質問です。なにかお気づきになった点があればごかいとういただけると幸いです。

  • テーブルビューで配列が自動消滅することについて

    xcode4.1をつかってiphoneアプリを作成しています。 テーブルビューの画面遷移時に、 可変配列NSMutableArrayに plistを読み込ませたNSMutableDictionaryの一意のキーの中身を保存し、 更に選択した行番号で呼び出した配列の中身を別ビューに渡そうとすると失敗してしまいます。 ・・自動解放されてしまっていると思うのですが、 [[[NSMutableArray alloc] init] retain]; としてもうまくいきませんでした。 どうすればうまくデータを別ビューに渡せるでしょうか。 (plistの読み込みは必須です。。) すみませんがご教授いただけますでしょうか。。。 よろしくお願いいたします。 //-------- .h------ @interface DtlVCL : UITableViewController { //別のViewからデータ受け渡し用 NSString *rcvStr; //plist一時読み込み用 NSMutableDictionary *dic; NSMutableArray *ary; } .m------------ viewDidLoad------ //各変数初期化 ary = [[[NSMutableArray alloc] init] retain]; dic = [[[NSMutableDictionary alloc] init] retain]; id path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"xxxxxxxx.plist"]; if([[NSFileManager defaultManager] fileExistsAtPath:path] == YES){ dic = [NSMutableDictionary dictionaryWithContentsOfFile:path]; }else{ NSLog(@"Dtl :ファイル読み込みエラー"); } ary = [dic objectForKey:rcvStr];//rcvStrは前ビューから取得した文字列 ------------------- - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath------ ExpVCL *expvcl = [[ExpVCL alloc] initWithNibName:@"ExpVCL" bundle:nil]; //データの受け渡し expvcl.rcvNum = [indexPath row]; expvcl.rcvStr = [NSString stringWithFormat:@"%@",[ary objectAtIndex:[indexPath row]]]; [self.navigationController pushViewController:expvcl animated:YES]; [expvcl release];

  • Xcodeのクラスについてお聞きします。

    何らかのクラスをつくり、ViewControllerからクラスを生成して そのクラス(以下TestClass)のメソッドにアクセスします。 TestClassのメソッドから呼び出し元のViewControllerの変数若しくはメソッドに アクセスすることはできるのでしょうか? 例) @interface ViewController : UIViewController{ UIlabel *label; //TestClassから書き込みたい } @end @implementation ViewController -(void)viewDidLoad{ TestClass *class = [[TestClass alloc] init]; [class labelWrite];//クラス呼び出し } - (void)hoge{ //TestClassからここにアクセスしたい //処理 } @end @interface TestClass : NSObject @end @implementation TestClass - (void)labelWrite{ //ここからViewControllerのlabelに書き込みたい //もしくはViewControllerのhogeメソッドにアクセスしたい } @end

  • Objective-C, Cocoaアプリ

    こんにちわ。初歩的な質問ですが、Objective-C, Cocoa Application両方とも初心者です。ボボタンを押すことで、NSTableViewに新しいデータを追加したいのですが、 デバッグして、データ自体はちゃんとデータソースの方に追加されているのですが、TableViewが表示していないようです。 reloadData, setNeedsDisplayも両方ためしたのですが、表示されません。 ちなみに、新しいデータを追加する関数ですが、tableViewがロードされる前にコールしたときはちゃんと新しいデータがtableViewに表示されています。 コードです。 ****************** dataはNSMutableArrayでItemInfoというクラスのArrayです。(ItemInfoは単純にNSString* nameとint priceの2つのデータを持っているクラスです。) この関数はすべてNSViewControllerのメンバ関数です。 -------コード---------- - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { if(self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]){ data = [[NSMutableArray alloc]initWithCapacity:5]; [data addObject:[[ItemInfo alloc]initWithName:@"Item1" price:100]]; [self addNewItem:nil]; //ここでのaddNewItemは反映され、TableViewには合計2つのデータが表示されています。 } return self; } -(IBAction)addNewItem:(id)sender { //ここはボタンを押したときにちゃんと実行されているのを確認しています。 //実際にdataにも新しいデータが追加されていることをデバッガで確認済みです。 ItemInfo *newItem = [[ItemInfo alloc]initWithName:@"NewItem" price:300]; [data addObject: newItem]; [tableView reloadData]; } #pragma mark - #pragma mark Table View Datasource - (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView { return [data count]; } - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex { //tableView には2つのColumnがあり、一つ目はItemInfo内のnameを、2つ目にはpriceを表示しています。 if([aTableColumn.identifier isEqual:@"Item"]){ return [[data objectAtIndex:rowIndex] name]; }else if([aTableColumn.identifier isEqual:@"Price"]){ return [NSString stringWithFormat:@"%d", [[data objectAtIndex:rowIndex] price]]; } return nil; } ------コード終わり------ 開発環境は以下の通りです。 OS: MacOSX10.6 SnowLeopard Xcode Version3.2.4 Cocoa Application

  • 【Objective-c】rubyの__send__みたいな使い方がしたい。

    Objective-cで、rubyの__send__みたいな使い方がしたいです。 例えば以下のようなインターフェィスのクラスがあるとします。 @interface Hoge : NSObject { } - (NSString*)retA; - (NSString*)retB; @end ある条件によって、このクラスのメソッドの呼び別けたいです。 そこで以下のように書いたのですが、コンパイルが通りませんでした。 Hoge* hoge = [[Hoge alloc] init]; NSLog(@"%@",[hoge sw ? retA : retB]); rubyだとこんな感じです。 hoge.__send__(sw ? "retA" : "retB") ご指導のほど、宜しくお願いいたします。

  • objective-Cについてご相談があります。

    現在objective-cを勉強中なのですが、 jsonについて教えて頂きたい事があります。 jsonのファイル・データ・オブジェクトそれぞれを 取得する必要があると習ったのですが、それらの違いが 今ひとつ分かりません。 下記のような記述なのですが、それぞれの違いをどなたか ご教示頂けないでしょうか。 // 対象Jsonファイル取得 NSBundle *bnd = [NSBundle mainBundle]; NSString *ptn = [bnd pathForResource:@"Test01" ofType:@"json"]; NSURL *url = [NSURL fileURLWithPath:ptn]; // Jsonオブジェクトの取得 NSURLRequest *req =[NSURLRequest requestWithURL:url]; NSData *dat = [NSURLConnection sendSynchronousRequest:req returningResponse:nil error:nil]; // Jsonデータの取得 NSDictionary *dick01 = (NSDictionary *) [NSJSONSerialization JSONObjectWithData:dat options:NSJSONReadingMutableContainers error:nil]; 以上、何卒宜しくお願い致します。

  • スクロールの上にある画像をフリックで変える方法とは

    今、画像を左右に数枚スクロールさせ、かつ、その画像を上や下にフリックすると各々、上や下に他の画像がでてきて、さらに拡大縮小もできるようなコードを書いています。 ViewContorller(以下、VC)にスクロールのメソッドを書き、 もう一つのPageView(UIScrollVIewクラスを親にもつ。以下、PV)に画像が拡大縮小するようなメソッドと上下のフリックのメソッドを書いています。 このPVの中で行う上下のフリックの操作によって、VCにあるスクロールの上に乗っている画像を変えたいのですが、色々と試したのですがその方法が一向にわかりません。もし宜しければ、ご教授ください。宜しくお願い致します。 xcodeは5.0です。 以下、スクロールとその上に画像をのせているpageがあるVC.mのコードです。 このpageにのっている画像をPVのほうのフリック操作で変更させたいと思っています。 - (void)viewDidLoad { [super viewDidLoad]; UIScrollView *scrollView = [[UIScrollView alloc] init]; scrollView.frame = self.view.bounds; scrollView.contentSize = CGSizeMake(self.view.frame.size.width * 3, self.view.frame.size.height); scrollView.pagingEnabled = YES; [self.view addSubview:scrollView]; //AppdelegateでValueというプロパティをつくり、PVでのフリック操作によってこの数値が変動したら、currentpageに反映して、それに対しての画像がでてくるようにしたいつもりです。 AppDelegate *appdelegate=(AppDelegate*)[[UIApplication sharedApplication]delegate]; currentpage=appdelegate.Value; //PageViewにて、画像をいれるメソッドをsetImageでつくっています。 for (int i=1;i<4;i++) { PageView *page = [[PageView alloc] initWithFrame:self.view.bounds]; [page setImage:[NSString stringWithFormat:@"%d.%d",currentpage,i]]; page.frame = CGRectMake( self.view.frame.size.width * (i-1), 0, self.view.frame.size.width, self.view.frame.size.height ); [scrollView addSubview:page]; }

  • objective-c のインスタンスについて教えていただきたいのですが

    初心者なのですみません。 ご存知の方教えていただきたいのですが、 例えばaインスタンスがbクラスをインスタンス化して bインスタンスがcクラスをインスタンス化して aインスタンスがcクラスをインスタンス化しないで bインスタンスがインスタンス化したcインスタンスに メソッド送信のようなことが したいのですがうまくいきません。 どのようにすればよいですか? よろしくお願いします (aインスタンスがcクラスをインスタンス化した場合、bインスタンスがcクラスをインスタンス化したものと同じもの(アドレスが同じ?)なものなのでしょうか?違いますよね?ようするにストレージクラスやNSDataなどインスタンスの中のデータを複数のインスタンスから取り出したいのです) 面倒でスミマセン。 以下は確認のために簡易的に作ったものです。 文字数多すぎなのでinterfaceは省きました #import "Aobject.h" #import "Bobject.h" #import "Cobject.h" @implementation Aobject - (IBAction)callb:(id)sender { id Bobj = [[Bobject alloc]init]; [Bobj make]; [Cobj log]; //ここでエラーが出ます(`Cobj' undeclared (first use in this function) (Each undeclared identifier is reported only once for each function it appears in.)) } @end //-------------------------------------- #import "Bobject.h" #import "Cobject.h" @implementation Bobject - (void)make { id cobj = [[Cobject alloc]init]; } @end //-------------------------------------- #import "Cobject.h" @implementation Cobject - (void)log { NSLog(@"ok"); } @end

    • ベストアンサー
    • Mac

専門家に質問してみよう