【iPhone】Objective-CでAtomPubを簡単に操作できるライブラリ公開してみた

Posted by: daichi  /  Category: 開発補助

daichi1128’s DCAtomPub at master – GitHub

はてなブックマークの登録をiPhoneアプリから行うにははてなのAtomPub APIを叩く必要がありますが、WSSE認証やらsha1やらbase64エンコードやらISO8061やらXMLポストやらでハマリ倒してしまったので、二度とつまずかないためにもライブラリ化してみた。
ライブラリというほど大げさなものでもないのですが、ソースコード公開デビューということで大目にみてやってください。

Objective-CでAtomPubを簡単に操作するライブラリDCAtomPubをgithubに公開しました。
ライセンスは修正BSDライセンスです。

AtomPubに関する情報はこちらから
日本語訳はこれ。ソフトウェア分野の研究開発 / RFC 5023 Atom Publishing Protocol 日本語訳 | Ricoh Japan

はてなブックマークAPIはこちらから。
はてなブックマークAtomAPIとは – はてなキーワード

セットアップ

ターミナルから以下のコマンドでダウンロード(要gitクライアント)

git clone git://github.com/daichi1128/DCAtomPub.git

githubからダウンロードしたら、Xcodeで起動し、DCAtomPubグループ内のファイル群を自分のプロジェクトにコピー。はてな用クライアントも必要ならHatenaExample内のファイルもコピー。

使い方

WSSE認証

DCAtomPubClinetの初期化メソッドの引数にユーザ名、パスワードを渡してあげれば面倒なWSSE認証の準備は勝手にDCAtomPubClientがやります。

?View Code OBJECTIVE-C
NSString *username = @"user";
NSString *password = @"pass";
DCAtomPubClient *atomClient = [[DCAtomPubClient alloc] initWithUsername:username password:password];

正確にはリクエストを投げるまでにユーザ名、パスワードがセットされていればリクエスト送信時にうまいことやってくれます。こんな形でもよいです。

?View Code OBJECTIVE-C
DCAtomPubClient *atomClient = [[DCAtomPubClient alloc] init];
atomClient.username = @"user";
atomClient.password = @"pass";

POST

AtomPubのPOSTメソッドはDCAtomPubClientクラスのpost:XMLString:メソッドで行います。
はてぶでは登録時にPOSTメソッドでXMLを投げます。
サンプルコードはこんな感じです。

?View Code OBJECTIVE-C
        NSString *username = @"user";
        NSString *password = @"pass";
	/** 
	 *AtomPubクライアントではてなブックマークを追加
	 */
	DCAtomPubClient *atomClient = [[DCAtomPubClient alloc] initWithUsername:username password:password];
	atomClient.delegate = [[DummyDelegate alloc] init];
 
	NSString *hatenaPostURL = @"http://b.hatena.ne.jp/atom/post";
	NSString *postXMLTemplate = 
	@"<entry xmlns=\"http://purl.org/atom/ns#\">"
	@"<link rel=\"related\" type=\"text/html\" href=\"%@\" />"
	@"<summary type=\"text/plain\">%@</summary>"
	@"</entry>";
 
	// POSTメソッドでXMLを送信
	[atomClient post:hatenaPostURL XMLString:[NSString stringWithFormat:
		  postXMLTemplate, 
		  @"http://iphone.longearth.net/itasktimer/",@"DCAtomPubから" ]];

PUT

はてなブックマークの編集時にAtomPubのPUTメソッドを使います。使い方はPOST時と同じように、DCAtomPubClientのput:XMLString:を呼べばOKです。

DELETE

はてなブックマークの削除時にAtomPubのDELETEメソッドを使います。使い方はPOST、PUTと同じです。DCAtomPubClientのdelete:XMLStringを呼びます。はてなブックマークの場合はXMLStringはnilでOKです。

はてなクライアントの使い方

AtomPubの扱いは上のDCAtomPubClientでだいぶ簡略化できたけど、いちいちXMLを調べて組み立てるのが面倒だ。なのではてな用AtomPubクライアントも作りました。
DCHatenaClient。DCAtomPubClientを継承してます。

ブックマークを追加する

DCHatenaClientを使ってブックマークを登録するには、DCHatenaClientの
- (void)post:(NSString *)bookmarkURL comment:(NSString *)comment;
メソッドで行います。
引数にはブックマークするURLとコメントを渡してあげます。
サンプルはこんな感じです。

?View Code OBJECTIVE-C
	/** 
	 * はてなブックマーク用クライアントではてなブックマークを追加
	 */
	DCHatenaClient *hatenaClient = [[DCHatenaClient alloc] initWithUsername:username password:password];
	[hatenaClient post:@"http://iphone.longearth.net" comment:@"DCHatenaClientから"];

だいぶすっきりします。

ブックマークを編集する

ブックマーク編集は
- (void)edit:(NSString *)eid title:(NSString *)title comment:(NSString *)comment;
で行います。
引数に編集するエントリID、変更後のタイトル、変更後のコメントを渡します。はてぶAPI的にタイトルとコメントいずれか必須らしいのでそうしてください。変更したくないものはnilを渡します。

?View Code OBJECTIVE-C
	DCHatenaClient *hatenaClient = [[DCHatenaClient alloc] initWithUsername:username password:password];
	[hatenaClient edit:@"15151515" title:@"変更後のタイトル" comment:nil];

すっきりですね。

ブックマークを削除する

ブックマーク削除は
- (void)delete:(NSString *)eid;
で行います。

?View Code OBJECTIVE-C
	DCHatenaClient *hatenaClient = [[DCHatenaClient alloc] initWithUsername:username password:password];
	[hatenaClient delete:@"15151515"];

もうAtomPub恐るるに足らずです。

その他

デリゲートとしてDCAtomPubDelegateを用意しています。呼べるものはNSURLConnection系を周到してます。こんな感じです。

?View Code OBJECTIVE-C
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
- (void)connectionDidFinishLoading:(NSURLConnection *)connection data:(NSData *)data;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;


リクエストを投げる前に
dcAtomPubClinet.delegate = self;
などとしてセットしてあげればNSURLConnectionと同じ感覚で使えるはずです。

mixiの隠しAPIもAtomPubらしいので、うまくいけば使えるかもしれません。まだ試してない。
※本来ならAtomPubのルートエンドポイントからアクセス可能なURLを引っ張ってくるのがAtomPub的に正しいことらしいのですが、面倒なので今回はそこまでしてません。

参考

はてなブックマークAtomAPIとは – はてなキーワード
CocoaでWSSE認証 – 24/7 twenty-four seven
cocoa_crypto_hashing: Summary
NSDataにBase64のエンコード・デコード機能を追加する

【iPhone】アプリ内でWEBアプリ感覚で画面遷移する

Posted by: daichi  /  Category: iphone開発

iPhoneアプリで画面遷移させる場合、コントローラをalloc/initしてナビゲーションコントローラのスタックにプッシュしたり、modalしたりする流れになるわけですが、複数の画面から呼ばれる画面だったりするとインスタンスの管理が面倒だったり、決まり文句をいちいち書くのが面倒になります。

そこでThree20のTTNavigatorを使うと、すっきり画面遷移できるようです。

webアプリ感覚で”http://about”のように遷移先を指定するだけで、その画面を表示できるようになります。
httpの部分は任意の文字列を定義できます。

そのためには、まずURLとコントローラのマッピングが必要です。

簡単にサンプルを示します。

?View Code OBJECTIVE-C
#import "DCAppDelegate.h"
#import "DCTwitterController.h"
#import "DCGoogleReaderController.h"
#import "DCAboutController.h"
#import "DCTabBarController.h"
 
@implementation DCAppDelegate
 
- (void)applicationDidFinishLaunching:(UIApplication *)application {
 
	TTNavigator *navigator = [TTNavigator navigator];
	navigator.supportsShakeToReload = YES;
	navigator.persistenceMode = TTNavigatorPersistenceModeTop;
 
	TTURLMap *map = navigator.URLMap;
	[map from:@"*" toViewController:[TTWebController class]];
	[map from:@"dc://tab" toSharedViewController:[DCTabBarController class]];
	[map from:@"dc://twitter" toViewController:[DCTwitterController class]];
	[map from:@"dc://reader" toViewController:[DCGoogleReaderController class]];
	[map from:@"dc://web" toViewController:[TTWebController class]];
	[map from:@"dc://about" toViewController:[DCAboutController class]];
	[map from:@"dc://compose?title=(compose:)" toModalViewController:[DCAboutController class]];
 
    [navigator openURL:@"dc://tab" animated:NO];
 
}
 
- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)URL {
	[[TTNavigator navigator] openURL:URL.absoluteString animated:NO];
	return YES;
}
@end


まずTTNavigatorクラスのインスタンスを取得します。
TTNavigator.supportsShakeToReloadをYESにすると、iPhoneを振ると、リロードをしてくれるようになります。
TTNavigator.persistenceModeはアプリ終了時にどの画面を開いていたかを記憶する設定です。persistenceModeAllを指定すると常に最後に開いていた画面を記憶し、次回起動時にその画面を表示するようになります。

その後のTTURLMapがURLとコントローラのマッピング情報を保持するクラスです。
from:toViewControllerメソッドでは、fromに指定されたURLが呼ばれるとtoViewControllerの画面を表示する、というような設定になります。
fromに”*”を指定すると、マッピングにないURLが指定された場合のコントローラを指定できます。

URLを指定したら、TTNavigatorのopenURL:animated:メソッドを呼べば画面遷移が行われます。

TTNavigatorはシングルトンなため、どの画面からでも同一インスタンスを取得でき、遷移したい時にopenURL:animated:メソッドを呼んでやればよい、という感じです。

TabBarコントローラのような全画面で共通で使いたいコントローラの場合は
from:toSharedViewController:メソッドを使うと一つのインスタンスを使い回せるようです。

また、コントローラに渡すパラメータも指定できます。

?View Code OBJECTIVE-C
[map from:@"dc://compose?subject=(compose:)" toModalViewController:[DCAboutController class]];

の部分がそれで、これはDCAboutControllerクラスのcompose:メソッドが呼ばれます。

パラメータの受け取りは以下のように行います。

?View Code OBJECTIVE-C
#import "DCAboutController.h"
 
@implementation DCAboutController
 
- (void)createModel {
	self.dataSource = [TTSectionedDataSource dataSourceWithObjects:
						@"About",
						[TTTableTextItem itemWithText:@"サイト" URL:@"http://iphone.longearth.net"],
						[TTTableTextItem itemWithText:@"ご意見ご要望" URL:@"dc://compose?subject=%5biSlot%20Pro%5d%e6%84%8f%e8%a6%8b%2f%e8%a6%81%e6%9c%9b"],
					   [TTTableTextItem itemWithText:@"友達にすすめる" URL:@"dc://compose?subject=&body=http%3a%2f%2fitunes%2eapple%2ecom%2fWebObjects%2fMZStore%2ewoa%2fwa%2fviewSoftware%3fid%3d304074830%26mt%3d8"],
						@"関連アプリ",
					   [TTTableTextItem itemWithText:@"iPachi" URL:@""],
					   [TTTableTextItem itemWithText:@"iSlot Pro" URL:@""],
					   [TTTableTextItem itemWithText:@"iTaskTimer" URL:@""],
						nil];
}
 
- (UIViewController *)compose:(NSString *)subject query:(NSDictionary *)param {
	TTMessageController* controller =
    [[[TTMessageController alloc] init] autorelease];
	controller.subject = subject;
	controller.body = [param objectForKey:@"body"];
	return controller;
}
@end

第一引数にはsubjectで指定したものが、第二引数以降にも&繋ぎで複数パラメータが指定でき、中身はDictionaryとして取り出すことができます。
上の例ではパラメータを受け取り、それらの値を使って、メール送信画面を起動しているところです。

createModelメソッドはTTTableViewControllerでテーブルデータを表示する際に呼ぶメソッドで、ここではあまりふれません。
が、少しだけ触れておくと、TTTableViewControllerのdatasourceがテーブルデータとなり、TTSectionDataSourceを入れています。TTSectionDataSourceは引数にNSStringがあればそれをセクション名とし、それ以降のものをセクション内に属するデータとして扱います。それからそのデータとしてTTTableTextItemがあり、textで表示する文字を、URLでタップした時の遷移先を指定しています。以上でこんな画面になります。
About画面

URL形式での画面遷移でもすごい画期的なのに、まだまだThree20にはすごい部分が盛りだくさんです。
マジすごい。

Three20とJSON-FrameworkでTwitterのタイムライン画面を作る

Posted by: daichi  /  Category: iphone開発

Three20 JSON datasource implementation – revetkn.com

Three20とjson-frameworkを使って簡単にタイムライン画面を作ってみる。

それぞれセットアップは以下を参考に

【Three20】をプロジェクトで使えるようにする手順 | iphoneアプリで稼げるのか
[iPhone] JSON Framework の使い方(準備編) | Sun Limited Mt.

※JSONFramework側の不具合で上記リンクの通り設定した場合でも、OS3.0で使うと実機転送時にcode signエラーが出た。そんな時は「他のリンカフラグ」等の設定はせずに、JSONディレクトリの中身のファイル達を直接プロジェクトに追加で回避できる。6月末に修正されたらしいので最新版を使えばだいじょぶかもしれない。
json-framework – Google Code

最低限のAPI仕様は

  1. http://twitter.com/statuses/friends_timeline.jsonへ
  2. ベーシック認証つきで
  3. GETメソッドでリクエストを投げる
上記3点が満たされていればOK。

例によってTwitter APIの詳細は公式wikiに譲る。
Twitter API Wiki / Twitter REST API Method: statuses friends_timeline

Three20の中でも今回は

を使う。

コードは以下。

コントローラ

FirstViewController.h

?View Code OBJECTIVE-C
#import
#import "Three20/Three20.h"
 
@interface FirstViewController : TTTableViewController {
 
}
 
@end


FirstViewController.m

?View Code OBJECTIVE-C
#import "FirstViewController.h"
#import "JSONDataSource.h"
 
@implementation FirstViewController
- (void)loadView {
	self.view = [[[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame] autorelease];
	self.view.backgroundColor = RGBCOLOR(240, 242, 245);
	self.variableHeightRows = YES;
       // STATUS_HEIGHTはTTGlobal.hで定義されてるステータスバーの高さを表す定数
	self.tableView = [[[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 480 - STATUS_HEIGHT)
												   style:UITableViewStylePlain] autorelease];
	self.tableView.autoresizingMask =
    UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
	self.tableView.sectionIndexMinimumDisplayRowCount = 2;
	[self.view addSubview:self.tableView];
}
 
// この辺はTTTableViewControllerのdelegateメソッド
// ここで返したデータソースを使ってTTTableViewControllerが描画もろもろやってくれる
- (id)createDataSource {
	JSONDataSource *dataSource = [[[JSONDataSource alloc] init] autorelease];
	[dataSource load:TTURLRequestCachePolicyNoCache nextPage:NO];
	return dataSource;
}
 
- (UIImage*)imageForError:(NSError*)error {
	return [UIImage imageNamed:@"Three20.bundle/images/error.png"];
}
 
@end


データソース

JSONDataSource.h

?View Code OBJECTIVE-C
#import
#import "Three20/Three20.h"
 
@interface JSONDataSource : TTListDataSource {
@private
        // 読み込み中フラグ
	BOOL _isLoading;
       // 読み込み完了フラグ
	BOOL _isLoaded;
       // ここいらのフラグを見て読み込み中Activityとか出し分けしてる様子
}
 
@end


JSONDataSource.m

?View Code OBJECTIVE-C
#import "JSONDataSource.h"
 
static	NSString *username = @"username";
static	NSString *password = @"password";
 
@implementation JSONDataSource
 
- (id)init {
	if (self = [super init]) {
        	_isLoading = YES;
		_isLoaded = NO;
	}
	return self;
}
 
#pragma mark TTTableViewDataSource
 
- (void)load:(TTURLRequestCachePolicy)cachePolicy nextPage:(BOOL)nextPage {
       // この辺はTwitterポスト時とほぼ同じ
	static NSString *jsonUrl = @"http://%@:%@@twitter.com/statuses/friends_timeline.json";
	NSString *url = [NSString stringWithFormat:jsonUrl, username, password];
 
	TTURLRequest *request =
    [TTURLRequest requestWithURL:url delegate:self];
	request.cachePolicy = cachePolicy;
	request.response = [[[TTURLDataResponse alloc] init] autorelease];
	request.httpMethod = @"GET";
 
	BOOL cacheHit = [request send];
	NSLog((cacheHit ? @"Cache hit for %@" : @"Cache miss for %@"), jsonUrl);
}
 
#pragma mark TTLoadable
 
- (BOOL)isLoading {
	return _isLoading;
}
 
- (BOOL)isLoaded {
	return _isLoaded;
}
 
#pragma mark TTURLRequestDelegate
 
- (void)requestDidStartLoad:(TTURLRequest*)request {
	_isLoading = YES;
	_isLoaded = NO;
	[self dataSourceDidStartLoad];
}
 
- (void)requestDidFinishLoad:(TTURLRequest*)request {
        // 通常通りレスポンスゲット
	TTURLDataResponse *response = request.response;
	NSString *responseBody = [[NSString alloc] initWithData:response.data encoding:NSUTF8StringEncoding];
 
        // JSONFrameworkのメソッドでArrayとして受け取る。JSONの構造次第でNSDictionaryの可能性もあるのでAPI要確認
	NSArray *json =  [responseBody JSONValue];
 
	for(NSDictionary *result in json) {
                // JSON内のデータ構造はTwitter APIを参照
		NSDictionary *user = [result valueForKey:@"user"];
                // データソースの要素としてTTIconTableFieldをセット。これでアイコンとテキストがワンセットのテーブルになる。
		[self.items addObject:[[[TTIconTableField alloc]
                                                                // JSONからテキスト取得
								initWithText:[result objectForKey:@"text"]
								url:nil
                                                                // JSONから画像取得
								image:[user objectForKey:@"profile_image_url"]
                                                                // 画像読み込み前のデフォルト画像を指定。ここは自分で用意
								defaultImage:[UIImage imageNamed:@"DefaultAlbum.png"]] autorelease]];
	}
 
	_isLoading = NO;
	_isLoaded = YES;
	[self dataSourceDidFinishLoad];
}
 
// この辺はNSURLRequestでおなじみな感じ
- (void)request:(TTURLRequest*)request didFailLoadWithError:(NSError*)error {
	NSLog([error localizedDescription]);
	NSLog(@"didFailLoadWithError");
	_isLoading = NO;
	_isLoaded = YES;
	[self dataSourceDidFailLoadWithError:error];
}
 
- (void)requestDidCancelLoad:(TTURLRequest*)request {
	NSLog(@"requestDidCancelLoad");
	_isLoading = NO;
	_isLoaded = YES;
	[self dataSourceDidCancelLoad];
}
 
@end


以上で、こんな画面の出来上がり。

timeline

これだけで、ネットワーク接続エラー時の対応やデータキャッシュや読み込み中表示などをこちらが意識せずとも勝手にやってくれる。
※表示項目をよりtwitterクライアントにしたい場合は別途カスタマイズが必要。

JSONに関してはアクセス先のURLと取り出し方法の2つが外部APIに依存する部分なので、その辺をdelegateに任せるなりすればこのソースをうまいこと活用できると思う。

【Objective-C】カテゴリ使って既存クラスに機能を追加する

Posted by: daichi  /  Category: iphone開発

Objective-Cのカテゴリという仕組みを使うと、1つのクラスを複数のクラスに分割したり、クラスに新しい機能を追加したりできる。

このカテゴリの強力なところは、NSStringのようなCocoa Frameworkで提供されているクラス達に対しても、メソッドを追加できるところ。

例えば、ベーシック認証をリクエストのヘッダ内に認証情報を持たせて行いたい。その時、ユーザ名、パスワードはbase64エンコードが必要になるのだけど、既存のNSStringにはそんな便利メソッドはない。

そんな時は、このカテゴリを使ってNSStringにbase64エンコードを行うメソッドを追加してしまう。

このカテゴリによるクラス拡張はオープンソースを眺めてると必ず出てくる。
json-framework – Google Code
google-toolbox-for-mac – Google Code

サンプルコードは以下。

NSString+Base64Encode.h

?View Code OBJECTIVE-C
#import 
 
@interface NSString (DCEncode)
+ (NSString*)stringEncodedWithBase64:(NSString*)str;
@end


NSString+Base64Encode.m

?View Code OBJECTIBE-C
#import 
#import "NSString+Base64Encode.h"
 
@implementation NSString (DCEncode)
 
+ (NSString*)stringEncodedWithBase64:(NSString*)str
{
	static const char *tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
	const char *s = [str UTF8String];
	int length = [str length];
	char *tmp = malloc(length * 4 / 3 + 4);
 
	int i = 0;
	int n = 0;
	char *p = tmp;
 
	while (i &lt; length) {
		n = s[i++];
		n *= 256;
		if (i &lt; length) n += s[i];
		i++;
		n *= 256;
		if (i &lt; length) n += s[i]; 		i++; 		 		p[0] = tbl[((n &amp; 0x00fc0000) &gt;&gt; 18)];
		p[1] = tbl[((n &amp; 0x0003f000) &gt;&gt; 12)];
		p[2] = tbl[((n &amp; 0x00000fc0) &gt;&gt;  6)];
		p[3] = tbl[((n &amp; 0x0000003f) &gt;&gt;  0)];
 
		if (i &gt; length) p[3] = '=';
		if (i &gt; length + 1) p[2] = '=';
 
		p += 4;
	}
 
	*p = '\0';
 
	NSString *ret = [NSString stringWithCString:tmp];
	free(tmp);
 
	return ret;
}
 
@end


ヘッダファイルでは@interfaceの後にある(DCEncode)というのがカテゴリの名前。
実装ファイルでは@implementationの後にある(DCEncode)と対応してる。

Objective-Cではファイル名とクラス名は特に関連がなくてもOKなのもポイント。

自作クラスでもこのようにカテゴリを分けて記述することで、複数ファイルに分割してプログラムができる。

ただし、変数は親ファイルで定義しないといけないので注意。

これは動的なメソッド追加が可能なことを意味しているのだけど、詳細は以下のサイトに譲る。
【コラム】ダイナミックObjective-C (8) カテゴリ – 動的なメソッドの追加によるクラスの拡張 | エンタープライズ | マイコミジャーナル

base64エンコードのロジックは夏ライオンのソースを参考にさせていただきました。
感謝。

参考
takuma104’s ntlniph at master – GitHub

【iPhone】【Objective-C】Twitterにつぶやきをポストする

Posted by: daichi  /  Category: iphone開発

最近Twitter熱が僕の回りでも加速してきたけど、アプリ標準機能として搭載すべく、iPhoneアプリ内でtwitterポストするためのサンプルコードを書いてみた。

Twitter API Wiki / Twitter REST API Method: statuses update

詳細は公式Wikiに譲るとして、最低限のAPI仕様は

  1. http://twitter.com/statuses/update.xmlへ
  2. ベーシック認証つきで
  3. POSTメソッドを使い
  4. statusパラメータ=「つぶやき」のリクエストを投げる
上記4点が満たされていればOK。

そんな条件を満たしたポストコードが以下。

続きを読む

【iPhone】写真を撮らずにカメラの音を鳴らす方法

Posted by: daichi  /  Category: iphone開発

カメラを撮らずにシャッター音のみを再生するサンプルコード。

適当にiPhone内のめぼしい音声ファイルを見つけたら、以下のようにファイルパスを指定すると再生できる。

?View Code OBJECTIVE-C
        NSString* srcPath;
	NSURL*  url;
 
	// オーディオファイルパス
       srcPath = @"/System/Library/Audio/UISounds/photoShutter.caf";
	// オーディオファイルのURLを取得する
	url = [NSURL fileURLWithPath:srcPath];
 
	// システムサウンドを作成する
	AudioServicesCreateSystemSoundID((CFURLRef)url, &soundFileObject);
 
	// サウンドを鳴らす
	AudioServicesPlayAlertSound(soundFileObject);

【NSString】文字列から表示サイズを取得する方法

Posted by: daichi  /  Category: iphone開発

twitterFonとかBB2Cとかのつぶやきや書き込みは、内容によって表示する文字の長さが違うので、各セルはセルの高さをそれぞれ計算する必要がある。
そんな時は下のような方法で表示に必要なCGSizeが取得できるので、このheightをセルの高さに使えばいい。

?View Code OBJECTIVE-C
// 最大の表示領域CGSize。このCGSize以上は文字列長がこのサイズを超える場合はすべて表示されない
CGSize bounds = CGSizeMake(300, 10000);
 
// 文字列描画に使用するフォント
UIFont *font = [UIFont systemFontOfSize:14];
 
// 表示に必要なCGSize
CGSize size = [@"表示する文字列" sizeWithFont:font constrainedToSize:bounds lineBreakMode:UILineBreakModeTailTruncation];

【ニコニコ】キュイン for iPhone

Posted by: daichi  /  Category: 開発後

加速度センサーとオーディオ周りの勉強がてら
キュインアプリを作りました。

<a href=”http://www.nicovideo.jp/watch/sm6629980″ mce_href=”http://www.nicovideo.jp/watch/sm6629980″>【ニコニコ動画】キュイン for iPhone</a>

音はAVAudioPlayerで再生。
コードはこんな感じ

続きを読む

【objective-c】[NSDate date]でセットした変数が参照できずエラー

Posted by: daichi  /  Category: objective-c

これ。はまりました。

画面上に今日の日付を表示したい。
画面を表示する度に日付を取得し直すのもあれなので、
一度画面をロードしたタイミングで日付を取得して
それを変数で保持しておこうと。

というわけでこんなコードを書いてました。

コントローラのヘッダファイルで以下のプロパティを指定

?View Code OBJECTIVE-C
@property (nonatomic, retain) NSDate *targetDate;


続きを読む

【UITableView】UITableViewを使って詳細画面を作る-1【UITableViewDataSource】

Posted by: daichi  /  Category: iphone開発

前回まででUITableViewでリストを表示して、
行を選択すると別画面を表示するところまで
できました。

今回は行選択時にその行の詳細画面を表示する画面を
UITableViewを使って作ります。

学べること

  • コントローラ内でのデータをビューに表示する方法
  • UITableViewに必要なもの-datasource
続きを読む

Get Adobe Flash playerPlugin by wpburn.com wordpress themes