めも。
int position = 0; LinearLayout item = (LinearLayout) mActivity.getListView().getChildAt(position); Log.e("result", String.valueOf(mActivity.getListView().performItemClick(item, position, 0)));// tap!
上述のように子Viewを一度取得しなければいけない。
めも。
int position = 0; LinearLayout item = (LinearLayout) mActivity.getListView().getChildAt(position); Log.e("result", String.valueOf(mActivity.getListView().performItemClick(item, position, 0)));// tap!
上述のように子Viewを一度取得しなければいけない。
めも。
ClipboardManager clipboardManager = (ClipboardManager) mActivity.getSystemService(Context.CLIPBOARD_SERVICE); Log.e("face", (String) clipboardManager.getText());
ClipboardManager clipboardManager = (ClipboardManager) mActivity.getSystemService(CLIPBOARD_SERVICE); clipboardManager.setText(result);
毎回微妙にはまるのでそろそろ書いておく。
eclipseの.projectディレクトリがある場合は、「File > import > Existing Projects into Workspace」で行う。
ディレクトリ構成などが異なってるとリンクが切れたりするので、「Packeage Explorer > プロジェクトルートで右クリック > Properties > Java Build Path > Libraries」で再設定する。
以下のようなエラーが出る場合がある。
Android requires compiler compliance level 5.0 or 6.0. Found ‘1.7’ instead. Please use Android Tools > Fix Project Properties.
「環境設定 > Java > Compiler」でCompiler compliance levelを1.6にする。
ビルドできる状態ならば勝手に生成されるのだが、極々稀に自動生成が開始されなかったりするので、その場合は再起動したりするといいと思う。
上述の方法でインポートする。但し、ディレクトリ構成が異なっていてテスト対象が見つけられずエラーが出る場合は、「Package Explorer > Propaties > Java Build Path > Projects」でプロジェクトをセットしなおす。
ドキュメントが分かりにくかったので自分で書いてみた。
ASIHTTPRequestを使った普通のクラス。
#import <Foundation/Foundation.h> #import "MyHTTPDelegate.h" @class ASIHTTPRequest; @class MyHTTPDelegate; @interface MyHTTP : NSObject { id <MyHTTPDelegate> delegate; } @property (nonatomic, retain) id delegate; - (void)loadData; - (void)requestFinished:(ASIHTTPRequest *)request; - (void)requestFailed:(ASIHTTPRequest *)request; @end
以下のように実装する。ASIHTTPRequestを使った事があるならばお手の物だ。
#import "MyHTTP.h" #import "ASIHTTPRequest.h" #import "SBJson.h" // 今回は触れないけど通信するので圏外判定に使っている #import "UIDevice-Reachability.h" #import "Reachability.h" #define URL @"http://example.org/api/data" @implementation MyHTTP @synthesize delegate; // 通信して更新する - (void)loadData { if([[UIDevice currentDevice] networkAvailable] == YES){ ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:URL]]; [request setDelegate:self]; [request setRequestMethod:@"GET"]; [request startAsynchronous];// 非同期通信の開始 } else{ // 圏外の時 = cahceから再現させる } } #pragma mark - #pragma mark ASIHTTPRequestDelegate - (void)requestFinished:(ASIHTTPRequest *)request { SBJsonParser *parser = [[SBJsonParser alloc] init]; NSArray *json = [parser objectWithString:[request responseString] error:nil]; if(json != nil && [json count] > 0){// success [delegate reflectData:json]; } [parser release]; } - (void)requestFailed:(ASIHTTPRequest *)request { NSError *error = [request error]; } @end
以下のようにGHAsyncTestCaseを継承する。
#import <GHUnitIOS/GHUnit.h> @class MyHTTP; @interface MyHTTPTest : GHAsyncTestCase { MyHTTP *http; } @property (nonatomic, retain) MyHTTP *http; @end
以下のように実装する。
#import "MyHTTPTest.h" #import "MyHTTP.h" @implementation MyHTTPTest @synthesize http; - (void)setUpClass { http = [[MyHTTP alloc] init]; [http setDelegate:self]; } - (void)tearDownClass { [http release]; } - (void)testLoadData { // 非同期処理が始まる前の準備 [self prepare]; // 非同期処理を実行する [self performSelector:@selector(startAsynchronous) withObject:nil afterDelay:0.1]; // どのくらい[結果]が帰ってくるのを待つか指定する(ここでは3秒待つことにした) [self waitForStatus:kGHUnitWaitStatusSuccess timeout:3.0]; } - (void)startAsynchronous { [http loadData]; } #pragma mark - #pragma mark MyHTTPDelegate - (void)reflectData:(NSArray *)json { NSLog(@"json:%d", [json count]); @try { GHAssertFalse( !!([json count] == 0), @"success to transfer for popular"); [self notify:kGHUnitWaitStatusSuccess forSelector:@selector(testLoadData)];// テストの[結果]を通知 } @catch (NSException *exception) {// アサーションに失敗した場合 [self notify:kGHUnitWaitStatusFailure forSelector:@selector(testLoadData)];// テストの[結果]を通知 } } @end
GHAssert系のメソッドはテストが失敗した場合にExceptionを発生させるので、上述のようにcatchしないとユニットテスト自体がクラッシュする。ちなみに以下のように書いても問題なくテストできた。
#import "MyHTTPTest.h" #import "MyHTTP.h" @implementation MyHTTPTest @synthesize http; - (void)setUpClass { http = [[MyHTTP alloc] init]; [http setDelegate:self]; } - (void)tearDownClass { [http release]; } - (void)testLoadData { // 非同期処理が始まる前の準備 [self prepare]; // 非同期処理を実行する [http loadData]; // どのくらい[結果]が帰ってくるのを待つか指定する(ここでは3秒待つことにした) [self waitForStatus:kGHUnitWaitStatusSuccess timeout:3.0]; } #pragma mark - #pragma mark MyHTTPDelegate - (void)reflectData:(NSArray *)json { NSLog(@"json:%d", [json count]); @try { GHAssertFalse( !!([json count] == 0), @"success to transfer for popular"); [self notify:kGHUnitWaitStatusSuccess forSelector:@selector(testLoadData)];// テストの[結果]を通知 } @catch (NSException *exception) {// アサーションに失敗した場合 [self notify:kGHUnitWaitStatusFailure forSelector:@selector(testLoadData)];// テストの[結果]を通知 } } @end
performSelectorメソッドの有用性が分からない。
実はMyHTTPクラスには通信ができなかった時の事を考慮して、キャッシュから呼び出す機能がある。以下のようにSELをプロパティに持たせる事で通知先を分岐するようにした。
#import "MyHTTPProxyTest.h" #import "MyHTTPProxy.h" @implementation MyHTTPProxyTest @synthesize http; @synthesize selector; - (void)setUpClass { http = [[MyHTTPProxy alloc] init]; [http setDelegate:self]; } - (void)tearDownClass { [http release]; } - (void)testLoadCache { [self setSelector:@selector(testLoadCache)]; [self prepare]; [self performSelector:@selector(startLoadCache) withObject:nil afterDelay:0.01]; [self waitForStatus:kGHUnitWaitStatusSuccess timeout:3.0]; } - (void)testLoadData { [self setSelector:@selector(testLoadData)]; [self prepare]; // Do asynchronous task here [self performSelector:@selector(startAsynchronous) withObject:nil afterDelay:0.01]; // Wait for notify [self waitForStatus:kGHUnitWaitStatusSuccess timeout:3.0]; } - (void)startLoadCache { [http loadCache]; } - (void)startAsynchronous { [http loadData]; } #pragma mark - #pragma mark MyHTTPDelegate - (void)reflectData:(NSArray *)json { NSLog(@"json:%d", [json count]); @try { GHAssertFalse( !!([json count] == 0), @"success to transfer"); [self notify:kGHUnitWaitStatusSuccess forSelector:[self selector]]; } @catch (NSException *exception) { [self notify:kGHUnitWaitStatusFailure forSelector:[self selector]]; } } @end
UITableViewのCellは使い回しされているのでサブビューを加えたりカスタマイズする時は注意が必要って備忘録。
#import <UIKit/UIKit.h> @interface UITableViewCellCustomized : UITableViewCell { UILabel *title; } @property (nonatomic, retain) UILabel *title; @end
#import "UITableViewCellCustomized.h" @implementation UITableViewCellCustomized @synthesize title; - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) {// Initialization code // title title = [[[UILabel alloc] initWithFrame:CGRectMake(20, 5, 280, 20)] autorelease]; [title setFont:[UIFont systemFontOfSize:18]]; [self addSubview:title]; // accessory [self setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; } return self; } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; } - (void)dealloc { [title release]; } @end
// create cell - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // call cell UITableViewCellCustomized *cell = (UITableViewCellCustomized *)[tableView dequeueReusableCellWithIdentifier:@"table_cell"]; if (cell == nil) {// create cell cell = [[[UITableViewCellCustomized alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"table_cell"] autorelease]; } [cell.title setText:@"なんらかの文字列"]; return cell; }
上述のようにUITableViewCellを継承したクラスを用意してセットアップする。以下の例のようにしてはならない。
以下のように通常の使い回しされているUITableViewCellに直にaddSubviewする。
// create cell - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // cell UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"table_cell"]; cell = nil; if (cell == nil) { cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"table_cell"] autorelease]; } [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; // title UILabel *title = [[[UILabel alloc] initWithFrame:CGRectMake(20, 5, 280, 20)] autorelease]; [title setText:@"なんらかの文字列"]; [cell addSubview:title]; return cell; }
以下のように記述する。
ListActivity currentActivity = (ListActivity) mActivity.getLocalActivityManager().getCurrentActivity();