ラベル iPad の投稿を表示しています。 すべての投稿を表示
ラベル iPad の投稿を表示しています。 すべての投稿を表示

[iOS] iPad の場合、UITableView の背景を透明にするには setBackgroundView:nil が必要

2011年2月26日土曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

元ネタ。
setBackgroundView:nil


self.tableView.backgroundColor = [UIColor clearColor];
iPhone の時にやっていた上記が効かず困っていたのだが、そういことか。

- (void)viewDidLoad {
    [super viewDidLoad];

 [self.tableView setBackgroundView:nil];
 [self.tableView setBackgroundView:[[[UIView alloc] init] autorelease]];
 self.tableView.backgroundColor = [UIColor clearColor];
透明になった。

[iOS] UIWebView でPDFを表示する

2011年1月6日木曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

[前回] Cocoaの日々: [iOS] UIWebView でリッチテキスト形式のファイル(*.rtfd)を表示する

肝心のPDFを忘れていた。確認しておく。

サンプル


いい感じだ。
- (IBAction)load5:(id)sender
{
 NSURL* url = [[NSBundle mainBundle] URLForResource:@"sample"
           withExtension:@"pdf"];
 NSURLRequest* req = [NSURLRequest requestWithURL:url];
 
 [self.webView loadRequest:req]; 
}


問題


直前に表示した文書(今回の場合PPT)が背景に残ったままになる現象があった。
-[UIWebView reload] を呼び出してみたが効果なし。うーむ。



ソースコード


GitHub からどうぞ。
DisplayingExcelFile at 2011-01-06 from xcatsan/iOS-Sample-Code - GitHub

[iOS] UISplitViewController - おぼえ書き

2011年1月5日水曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

iPad 用アプリの開発を開始。UISplitViewController について調査した(そのおぼえ書き)。

Split View-based Application


Xcode のテンプレートから UISplitViewController を選ぶ。

実行するとこんな画面が表示される。
縦にするとポップオーバー表示になる。


構成


構成イメージはこんな感じ。
UISplitViewController を構成するコントローラの指定はInterface Builder のインスペクタで設定してある。

UISplitViewController.viewControllers の中身はこう。
(
    "<UINavigationController: 0x4d2e290="">",
    "<DetailViewcontroller: 0x4d2e5f0="">"
)
UISplitViewController.view の構成はこう。
UIView
  |-UILabel
  |-UIToolbar
    |-UIToolbarTextButton
      |-UIPushButton
UILayoutContainerView
  |-UINavigationTransitionView
  |-UINavigationBar
    |-UINavigationItemView
なるほど。

RootViewController は UINavigationController に載っているので、階層的なビューの切り替えができるようになっている。この辺りはこれまでの iPhoneアプリと同じようにできる。試しに SubViewController を良いして遷移させてみた。
RootViewController.m

- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    
    detailViewController.detailItem = [NSString stringWithFormat:@"Row %d", indexPath.row];
 
 UIViewController* viewController = [[SubViewController alloc] initWithNibName:nil bundle:nil];
 [self.navigationController pushViewController:viewController animated:YES];
 [viewController release];
}

画面の回転により UISplitViewControllerDelegateのメソッドが呼び出される。

– splitViewController:willHideViewController:withBarButtonItem:forPopoverController:
 横 => 縦 により、左側のビューが隠れる時

– splitViewController:willShowViewController:invalidatingBarButtonItem:
 縦 => 横 により、左側のビューが表示される時

– splitViewController:popoverController:willPresentViewController:
 ポップオーバーが表示される時


ソースコード


サンプルはこちら。
SplitViewBaseSample at 2011-01-05 from xcatsan/iOS-Sample-Code - GitHub

[iOS] UIWebView でエクセルシートを表示する [2] 実機確認

2010年12月26日日曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

[前回] Cocoaの日々: [iOS] UIWebView でエクセルシートを表示する

前回のコードを iPad対応させて実機で確認してみた。

シミュレータとほとんど同じ表示(当たり前だが..)。フォントは元のファイルで 11pt 指定だったが実機では一回り小さく見える(8か9ptぐらい?)。


[参考] Cocoaの日々: 簡易スライドビューア [7] iPad対応〜ユニバーサルアプリを作る

[iOS] GameKit - Bluetoothを使った iOSデバイス間の通信 [2]画像の送受信

2010年12月10日金曜日 | Published in | 2 コメント

このエントリーをはてなブックマークに追加

[前回] Cocoaの日々: [iOS] GameKit - Bluetoothを使った iOSデバイス間の通信

今回は画像を送信してみた。

サンプル


画像が選ぶと...

こうなる。転送は2秒程度。


解説


まず送信部分。UIImagePickerController の扱いは割愛する。UIImage を送る部分だけピックアップした。
- (void)imagePickerController:(UIImagePickerController *)picker
 didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    [picker dismissModalViewControllerAnimated:YES];
 
 UIImage* image = [info objectForKey:UIImagePickerControllerEditedImage];
 
 NSError* error = nil;
 NSData* data = UIImageJPEGRepresentation(image, 0.5);
 [self.session sendData:data
       toPeers:[NSArray arrayWithObject:self.peerID]
     withDataMode:GKSendDataReliable
      error:&error];
 if (error) {
  NSLog(@"%@", error);
 }
 
}
特別な工夫はなく UIImage を NSData に変換して送信しているだけ。

次に受信部分。
- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer
 inSession:(GKSession *)session context:(void *)context
{
  // image
  NSLog(@"received image");
  self.imageView.image = [UIImage imageWithData:data];
 }
}
これも工夫は無い。送られてきた NSData から UIImageを生成して表示しているだけ。

なお大きなサイズだとエラーが出ていた。
Error Domain=com.apple.gamekit.GKSessionErrorDomain Code=30202 "Send data error."
 UserInfo=0x570c1b0 {NSLocalizedFailureReason=AGPSessionSendTo failed (801C0001).,
 NSLocalizedDescription=Send data error.}
メモリが不足していたのでそれに関連してエラーが出たのかもしれない。


ソースコード


GitHub からどうぞ。
xcatsan/iOS-Sample-Code at 2010-12-10b - GitHub

[iOS] GameKit - Bluetoothを使った iOSデバイス間の通信

2010年12月9日木曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

GameKit を使い端末間の Bluetooth通信を試してみた。

サンプル


テキストメッセージをやりとりできる簡易なサンプルプログラムを組んでみた。
2つの iOS端末でプログラムを立ち上げて両方で "Connect" を押す。すると近くの端末を探し始める。

Bluetooth がオフに鳴っている場合はオンにするか尋ねられる。
通信可能な端末が見つかるとリストアップされる。
選択すると相手側で受け入れの確認がある。
受け入れる(Accept)と接続が成立する。
 テキストを入れて "send" ボタンを押すと相手側の端末にそのテキストが表示される。


解説


Bluetooth を使った端末間通信を行うのに今回は GameKit.framework を使った。最初にこのフレームワークをプロジェクトへ加えておく。

実装のポイントは2つ。
1. GKPeerPickerController を使い接続を確立する
2. 接続後は GKSession を使いデータの送受信を行う

まず 1. の接続確立から。
- (IBAction)connect:(id)sender
{
 GKPeerPickerController* picker = [[GKPeerPickerController alloc] init];
 picker.delegate = self;
 picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;
 [picker show];
}
インスタンスを作り、-[show] を投げると接続に必要なダイアログが表示される。
この後は接続の確立もしくはキャンセルのタイミングで GKPeerPickerControllerDelegate のメソッドが呼ばれる。
接続が確立すると -[peerPickerController:didConnectPeer:] が呼ばれる。接続してしまえば GKPeerPickerController は不要になるので閉じておく。接続後に渡される GKSession を取っておく。この GKSession をこの後のデータ送受信で使う。
- (void)peerPickerController:(GKPeerPickerController *)picker
 didConnectPeer:(NSString *)peerID toSession:(GKSession *)session
{
 self.peerID = peerID;
 self.session = session;
 session.delegate = self;
 [session setDataReceiveHandler:self withContext:nil];
 picker.delegate = nil;
 [picker dismiss];
 [picker autorelease];
}

続いて 2. のデータ送受信を行う。まず送る側から。UITextField 内の文字列を UTF8エンコードして NSDateに変換し、これを送信する。
- (IBAction)sendText:(id)sender
{
 NSData* data = [self.sendText.text dataUsingEncoding:NSUTF8StringEncoding];

 NSError* error = nil;
 [self.session sendData:data
       toPeers:[NSArray arrayWithObject:self.peerID]
     withDataMode:GKSendDataReliable
      error:&error];
 if (error) {
  NSLog(@"%@", error);
 }
 self.sendText.text = @"";
}
次に受け側。receiveData:fromPeer:inSession:context: を実装する。ここでは渡ってきた NSData を UTF8でデコードして NSStringに戻し、画面上の UITextView へ表示している。
- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer
 inSession: (GKSession *)session context:(void *)context
 NSString* msg = [[[NSString alloc] initWithData:data
   encoding:NSUTF8StringEncoding] autorelease];
 NSString* text = [self.textView.text stringByAppendingFormat:@"%@\n", msg];
 self.textView.text = text;
}

最低限のコードはこれだけ。実に簡単に Bluetooth 通信が実現できる。


ソースコード


GitHub からどうぞ。
BluetoothSample at 2010-12-09 from xcatsan/iOS-Sample-Code - GitHub


備考


Mac Book Pro 上で動かしている iPhoneシミュレータでは Bluetooth の接続確認は行えなかった。Bluetooth自体は有効になるのだが iPhoneを見つけてくれない。シミュレータでテストできるとかなり楽なのだが。今は iPhone 3GS, iPad 両方にいちいちインストールしてテストしている。WiFi接続に切り替えられるようにするとシミュレータでも動くかもしれないので後で試してみよう。

CoreLocation - [1] 現在地の緯度経度を取得する

2010年10月9日土曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

CoreLocation を使って現在地の緯度経度を取得する。簡単なサンプルを作ってシミュレータ、iPhone3GS、iPadで動作確認をやってみた。

CoreLocation


CoreLocationManager を使う。使い方はリファレンスに書いてある。
CLLocationManager Class Reference より抜粋

To configure and use a CLLocationManager object to deliver events:
  1. Always check to see whether the desired services are available before starting any services and abandon the operation if they are not.
  2. Create an instance of the CLLocationManager class.
  3. Assign a custom object to the delegate property. This object must conform to theCLLocationManagerDelegate protocol.
  4. Configure any additional properties relevant to the desired service.
  5. Call the appropriate start method to begin the delivery of events.


サンプル


起動するとデバッガコンソールへ CLLocationの情報を書き出す簡単なサンプルを作った。
[3389:307] Start updating location.
[3389:307] ----------------------------------------------------
[3389:307] latitude,logitude : 35.433066, 139.720322
[3389:307] altitude          : 0.000000
[3389:307] cource            : -1.000000
[3389:307] horizontalAccuracy: 250.000000
[3389:307] verticalAccuracy  : -1.000000
[3389:307] speed             : -1.000000
[3389:307] timestamp         : 2010-10-20 06:31:09 +0900
画面表示は何もなし。



実装


準備

(1) Frameworks に CoreLocation.frameworkを追加する

(2) ヘッダファイル読み込み
#import <CoreLocation/CoreLocation.h>

コード


- (void)viewDidLoad {
    [super viewDidLoad];

 if ([CLLocationManager locationServicesEnabled]) {
  self.locationManager = [[CLLocationManager alloc] init];
  self.locationManager.delegate = self;
  [self.locationManager startUpdatingLocation];
  NSLog(@"Start updating location.");
  
 } else {
  NSLog(@"The location services is disabled.");
 }
}

- (void)logLocation:(CLLocation*)location
{
 CLLocationCoordinate2D coordinate = location.coordinate;
 NSLog(@"----------------------------------------------------");
 NSLog(@"latitude,logitude : %f, %f", coordinate.latitude, coordinate.longitude);
 NSLog(@"altitude          : %f", location.altitude);
 NSLog(@"cource            : %f", location.course);
 NSLog(@"horizontalAccuracy: %f", location.horizontalAccuracy);
 NSLog(@"verticalAccuracy  : %f", location.verticalAccuracy);
 NSLog(@"speed             : %f", location.speed);
 NSLog(@"timestamp         : %@", location.timestamp);
}

- (void)locationManager:(CLLocationManager *)manager
 didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {

 [self logLocation:newLocation];
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
 NSLog(@"Error: %@", error);
}



結果


シミュレータ (WiFi)

初回に確認ダイアログが表示される。

1回目
Start updating location.
----------------------------------------------------
latitude,logitude : 35.534066, 139.720422
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 150.000000
verticalAccuracy  : -1.000000
speed             : -1.000000
timestamp         : 2010-10-19 21:44:07 GMT
----------------------------------------------------
latitude,logitude : 35.533892, 139.720450
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 185.000000
verticalAccuracy  : -1.000000
speed             : 0.000000
timestamp         : 2010-10-19 21:44:38 GMT
----------------------------------------------------
latitude,logitude : 35.533892, 139.720450
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 185.000000
verticalAccuracy  : -1.000000
speed             : 0.000000
timestamp         : 2010-10-19 21:44:53 GMT

2回目
Start updating location.
----------------------------------------------------
latitude,logitude : 35.533892, 139.720450
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 185.000000
verticalAccuracy  : -1.000000
speed             : 0.000000
timestamp         : 2010-10-19 21:45:13 GMT
----------------------------------------------------
latitude,logitude : 35.533892, 139.720450
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 185.000000
verticalAccuracy  : -1.000000
speed             : 0.000000
timestamp         : 2010-10-19 21:45:23 GMT

実機 - iPhone 3GS (iOS4.0) ※屋内

初回にダイアログが表示される。

また実行中は位置情報使用中のインジゲータが表示される。

1回目 6:47起動
Start updating location.
----------------------------------------------------
latitude,logitude : 35.530754, 139.718766
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 620.000000
verticalAccuracy  : -1.000000
speed             : -1.000000
timestamp         : 2010-10-20 06:46:50 +0900
----------------------------------------------------
latitude,logitude : 35.530754, 139.718766
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 620.000000
verticalAccuracy  : -1.000000
speed             : -1.000000
timestamp         : 2010-10-20 06:46:50 +0900
----------------------------------------------------
latitude,logitude : 35.533505, 139.720757
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 80.000000
verticalAccuracy  : -1.000000
speed             : -1.000000
timestamp         : 2010-10-20 06:46:52 +0900
  :

2回目 6:47起動
Start updating location.
----------------------------------------------------
latitude,logitude : 35.533505, 139.720757
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 80.000000
verticalAccuracy  : -1.000000
speed             : -1.000000
timestamp         : 2010-10-20 06:47:47 +0900
  :

3回目 6:53起動(5分後)
Start updating location.
----------------------------------------------------
latitude,logitude : 35.533505, 139.720757
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 80.000000
verticalAccuracy  : -1.000000
speed             : -1.000000
timestamp         : 2010-10-20 06:48:22 +0900
----------------------------------------------------
latitude,logitude : 35.533505, 139.720757
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 80.000000
verticalAccuracy  : -1.000000
speed             : -1.000000
timestamp         : 2010-10-20 06:54:22 +0900
----------------------------------------------------
latitude,logitude : 35.533505, 139.720757
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 80.000000
verticalAccuracy  : -1.000000
speed             : -1.000000
timestamp         : 2010-10-20 06:55:25 +0900
----------------------------------------------------
latitude,logitude : 35.533658, 139.720645
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 250.000000
verticalAccuracy  : -1.000000
speed             : -1.000000
timestamp         : 2010-10-20 06:56:27 +0900


実機 - iPad (iOS 3.2/WiFi)

1回目(6:52起動)
Start updating location.
----------------------------------------------------
latitude,logitude : 35.533658, 139.720645
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 250.000000
verticalAccuracy  : -1.000000
speed             : -1.000000
timestamp         : 2010-10-20 06:52:15 +0900
----------------------------------------------------
latitude,logitude : 35.533658, 139.720645
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 250.000000
verticalAccuracy  : -1.000000
speed             : -1.000000
timestamp         : 2010-10-20 06:53:17 +0900

2回目(6:53起動)
Start updating location.
----------------------------------------------------
latitude,logitude : 35.533658, 139.720645
altitude          : 0.000000
cource            : -1.000000
horizontalAccuracy: 250.000000
verticalAccuracy  : -1.000000
speed             : -1.000000
timestamp         : 2010-10-20 06:53:52 +0900


まとめ

  • 実機(iPhone3GS)では1分毎に CLLocationManagerDelegate のメソッドが呼び出される(位置情報が更新される)
  • 実機(iPhone3GS)では位置情報更新の度に精度 が上がっていった(CLLocation.horizontalAccuracyが低くなる)。ただし悪くなるケースも見られた。
  • 5分程度してから位置情報へアクセスすると前回キャッシュされた位置情報が最初に返された(CLLocation.timestampで確認可能)。
  • シミュレータでも WiFi経由で現在位置の取得が可能。確認ダイアログも表示される(昔はそうではなかったらしい)
  • locationServicesEnabledプロパティはiOS4.0から Deprecated。同名のクラスメソッドを使う。
  • 検証環境での精度は
    シミュレータ [150〜185m]
    iPhone3GS [80〜250m]
    iPad-Wifi [250m] ※固定?
  • CLLocation.verticalAccuracyはiOSの場合常に-1(リファレンスに書いてある)。

ソースコード


GitHub からどうぞ。
xcatsan's iOS-Sample-Code at 2010-10-09 - GitHub


参考情報


CLLocationManager Class Reference

リファレンス


LocateMe

iOS Reference Library のサンプル


【コラム】実践! iPhoneアプリ開発 (15) ロギングアプリの作り方 (1) - Core Locationで現在地を取得する | エンタープライズ | マイコミジャーナル
【コラム】実践! iPhoneアプリ開発 (16) ロギングアプリの作り方 (2) - Map Kitで地図を表示する | エンタープライズ | マイコミジャーナル
【コラム】実践! iPhoneアプリ開発 (17) ロギングアプリの作り方 (3) - アノテーションビューをカスタマイズする | エンタープライズ | マイコミジャーナル

木下氏の連載。わかりやすくとても参考になった。


GPSを利用する方法 - プログラミングノート

ソースコードを参考に。


Core Locationのaccuracyについて - The iPhone Development Playground

精度の話。タイムスタンプチェックや精度を上げる為には数回位置更新を待つ、など。昨年の記事なので iOS 3ベース。

- - - - -
今更ながら初めて CoreLocation を試してみた。なんか楽しい-。
次回はマップにピンを立てる。

簡易スライドビューア [11] 隣の画像が見えるモード追加

2010年9月27日月曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

プロパティを追加
@property (nonatomic, assign) BOOL showcaseModeEnabled;

YES にすると隣の画像が見えるようになる。

拡大もOK。
画面回転もOK。

※iPad でも動作確認済み。

ソースは GitHub からどうぞ。
EasyGallery at 2010-09-27 from xcatsan's iOS-Sample-Code - GitHub


- - - -
EasyGalleryは1枚絵を見ることが主目的で、隣が見える動作はどちらかと言えばおまけ的な機能。ちょっとしたトリックっぽい処理で実現しているので、隣の画像はフリックに反応しない。横に画像を並べてみせる U/I は別途作った方がいい。

簡易スライドビューア [7] iPad対応〜ユニバーサルアプリを作る

2010年9月20日月曜日 | Published in | 4 コメント

このエントリーをはてなブックマークに追加

[前回]

ユニバーサルアプリにしてiPadに入れてみた。

iPad対応


このサイトが参考になった。
3時間でiPhoneアプリをiPad対応にした : 管理人@Yoski

以下、記録。


1. ターゲットを iPad用にアップグレード


ターゲット上で右クリックして「現在のターゲットを iPad 用にアップグレード...」を選ぶ。
ユニバーサルアプリ(1つでiPhone/iPadに対応)にするのか、デバイス毎に別々のアプリとするのかを聞かれる。今回は「One Universal application」を選択。
すると "Resource-iPad" というグループが作成された。ただ中身は何も入っていなかった。

2. XIBを iPad用に作成


EasyGallery では2つのXcodeが作成した2つの XIBファイルを使っている。
MainWindow.xib
EasyGalleryViewController.xib
これらを iPad用に新規に作成する。

まず MainWindow.xib から。InterfaceBuilderでファイルを開いた後、「File」メニューから「Create iPad Version」を選択する。
すると MainWindow.xib をコピーした新しい XIBファイルが生成される。
名前を MainWindow-iPad.xib として保存する。この名前は Info.plist の設定と一致させておく必要がある。1. でターゲットをアップグレードした時に Info.plist にはデフォルトで "Main nib file base name (iPad)" が追加されている。値は "MainWindow-iPad"。

同様にして EasyGalleryViewController.xib も iPad用に新規作成する。名前は後ろに "-iPad" をつけて EasyGalleryViewController-iPad.xib とした。

なお「File」メニューで「Create iPad Version Using Autoresizing Masks」を選ぶと、Autoresizing Masksが iPad用に自動的に摘要される。大抵の場合、ビューのサイズを iPad用に拡大するのでこれは便利。

これで完了。


実機で実行


あっさり動いた。


横にすればちゃんと回転する。拡大時の回転も問題なし。


これはちょっと嬉しい。


その他


EasyGalleryViewController-iPad.xib はソースコード上に名前が現れない。また新規に作った MainWindow-iPad.xib の NIB Name は "EasyGalleryViewController" のまま。
自動的に"-iPad"が付くファイルを探してXIBを読み込んでいるようだ。画像等と同じく暗黙のルールがあるのだろうか。リファレンスを探したがこれについの説明は見つけられなかった。

10/8追記)iPhone用の XIBが使われていたことが判明。やっぱりこの設定を変える必要がある。


ソースコード


GitHubからどうぞ。
EasyGallery at 2010-09-20 from xcatsan's iOS-Sample-Code - GitHub


- - - -
わかってはいたけれど同じソースで iPhone/iPad 両方が動くのはすごいな。実際にアプリを作るときには作業量が増えるので大変だとは思うけれど。

人気の投稿(過去 30日間)