iPhoneの画面サイズ(329 x 480)で、jpg画像を画面数分書き出してみる。 予め、CGContextRefには描画されていて、ページ数も取得されているものとします。
- (void)exportJPEG:(NSUInteger)pageCount {
context = UIGraphicsGetCurrentContext();
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = [paths objectAtIndex:0];
NSString *fileName;
NSString *filePath;
for (int i=0; i < pageCount; i++) {
fileName = [NSString stringWithFormat:@"page-%d.jpg", i + 1];
filePath = [basePath stringByAppendingPathComponent:fileName];
context = UIGraphicsGetCurrentContext();
CGImageRef imageRef = CGBitmapContextCreateImage(context);
UIImage *image = [UIImage imageWithCGImage:imageRef];
CGRect rect = CGRectMake(i * 320, 0, 320.0, 480.0);
CGImageRef pageImageRef = CGImageCreateWithImageInRect(image.CGImage, rect);
UIImage *pageImage = [UIImage imageWithCGImage:pageImageRef];
CGImageRelease(pageImageRef);
NSData *data = UIImageJPEGRepresentation(pageImage, 0.8);
[data writeToFile:filePath atomically:YES];
}
}
横(landscape)の状態もとれば、横向きでも書き出せますね。
Facebookを発端として、mixiのpluginが日々進化してますね。
「Open Graph Protocol」って言葉が浸透しているみたいです。
この概念については「IT戦記 フェイスブック、ミクシィ、グリーで使われている OGP (Open Graph Protocol) とは何か」で図解的に記載されているのでわかりやすいかと。
早速、このBlogも対応(?)してみました。 (単にヘッダタグつけただけだけど)
タイトルのところは動的に出力するけど、リスト形式の場合どうしようかね? とりあえず、定数で「Blog」として出力したけど。
「IT戦記 フェイスブック、ミクシィ、グリーで使われている OGP (Open Graph Protocol) とは何か」にも記載されているように、Facebook Appとも連携するみたいです。
今後はコンテンツの多様性によってプロパティをうまくつかって、リッチなリンクができそうですね!
個人でもGraph APIが利用できるようになったみたいなのでテスト。
Type : GET URI:https://mixi.jp/connect_authorize.pl パラメータ: client_id=Consumer Key response_type=code scope=r_profile r_voice
scopeは各APIを許可する為のパラメータ 例では、r_profile、r_voiceを指定しており「People API」「Voice API」の読み込み権限が利用可能
Type : POST URI:https://secure.mixi-platform.com/2/token パラメータ: grant_type=authorization_code client_id=Consumer Key client_secret=Consumer Secret code=Consumer Secret redirect_uri=アクセストークン response_type=code scope=r_profile r_voice
アクセストークンの有効期限は15分なので、リフレッシュトークンで再発行する必要がある。
こんな事も知らないのか!と言われると思いますが、 仕事ではPostgreSQLがメインなので(←言い訳)、実はMySQL基本的な事がわかってなかったり。 (先方のレンタルサーバの都合で仕方なくMySQLもやってはいるんだけど) MySQL InnoDBの利用
MyISAMってトランザクションが使えなかったのか!
いやぁ、知らないと怖い怖い(^^;) まぁ、うちがcreatedbはしてるわけでないので責任はないんだけど。
1月末で、yoo-s.comのホスティングSaasesの回線工事が行われ、 バックボーンが1Gbpsになりました。
速くなった!と言うよりマシになった
と言うレベルです。
以前はパケットロスが頻繁に起こっていたので、 工事してダメなら他の乗り移ろうと思っていたから取りあえず踏みとどまる。
でも、格安VPSなのでそうは文句は言えないのも現実。 牛丼商戦みたいになっていてペイできないだろうから。
クラウドと言う言葉が出てきたのって、GoogleやAmazonのテクノロジーがもてはやされてからなのだろうか? まぁ、クラウドの定義は置いといて「Amazon EC2を使う前に知っておきたいこと色々」の記事を見て今後のサーバ選択はどうしようか?非常に悩ましい。
・個人のオナニーか? ・ベンチャー的なものか? ・中小のBtoBか? ・大企業のBtoCか?
色々シチュエーションはあると思うが、実際やってみないとわからないのが現実だろう。
(1) 最小構成で0.085ドル/時間 (2) 月間転送量1GBあたりアップロード:0.1ドル ダウロード:0.17ドル
例えPVをシミュレーションしても実際その通りにならなだろうし、あとづけになるんだろう。 そう言う意味では、EC2って個人レベルではとっつきにくい部分がある。 でも最近、勉強代としてやってみる価値はあるように思えてきた。
そんな中、先ほど新たなアナウンスがありました。 AWS Elastic Beanstalk (beta)
【AWS発表】 AWS Elastic Beanstalkの発表
今後どうしますかね。 個人レベルでJavaシステムを組むメリットはないし、あまり作りたくないのでPHPベースでAPI作成かな?と考えています。
草野球が中止になって、インドアライフになったのでWebパトロール。
去年の末、サポートに問い合わせたらGraph APIの個人公開は未定って回答があったんだけど、 そのすぐ後に公開されてたんだ!!orz orz 急いで、法人登録するところだった・・・.
個人でもクレジットカード登録すれば利用可能です
Facebookと同じ仕様ですね。
さて最近、スクリプト系の勉強を怠ってるので、この三連休はmixi & facebook開発の自宅合宿(?)します。 まずは、手始めにPHP版から始めて見ようと思います。
とりあえず、最新のoauthをチェック。
svn co http://oauth.googlecode.com/svn/code/php/
ちょっと気になったFacebookのMobile Apps
mixiのGraphAPIとかはこれをやりたいんだろうな。 果たしてどの知識レベルでお手軽にアプリが作れるのか?ちょっと試してみたい。 そろそろSVNじゃなくてGitに移行する時期なのかな?とも思ったり。
MacBook:~ yoo$ git clone git://github.com/facebook/facebook-ios-sdk.git Cloning into facebook-ios-sdk...
JSONで通信するんだね。
ダウンロードしたSDKにデモ用のアプリがあるので使ってみる。
まず、Facebook Developerでアプリを作成してApp IDを取得する。
取得したApp IDをinfo.plistに設定する。
あとは、プログラム内にもAppIDを記述して起動するだけ。
認証処理
認証成功
publish streamでwallに投稿してみる
photo uploadはちと不明。 ソースを調べてて、時間あったらやってみます。
ハマりました。
Appleの仕様変更が結構頻繁に怒っているので、ネットに記載されている申請方法と 現在の方法は異なっていたりするので注意が必要です。
Apple Developer Centerに日本語マニュアルがあるのでそれをしっかり読む事も必要ですね。 僕の方は、Twitterで質問してすぐ解決しましたが(^^;
2011/2現在、アプリケーションのアップロード方法はReady Upload Binaryがワンクッション必要になっています。 これは、Export Compliance(輸出コンプライアンス)が必要かどうか? ここでは、
iPhoneアプリが暗号化されたアプリか?
によって分岐されます。 通常は暗号化しないと思いますので、Noと答えます。 うっかりYesで進んでしまうと、全部YESで答えてCompliance情報を提出するルートに行ってしまいます。 はじめは、自分の入力内容が悪いのか?と思いAppをDelete。 はい、同じApp Name, SKU Numberが二度と利用できなくなりました。。。
ちなみに、以前はzipファイルを直接アップロードできていたのでユルユルだったんですね。
zipファイルをitune storeにアップする際にicon.pngを57 x 57ピクセルにする必要があります。
という事まではすぐわかりますが、これだとiPhone4だと潰れて表示されてしまったりします。 Apple製品なのでアイコンは美しく!これは伝統ですので、妥協するのはどうかと?
と言う事で一生懸命、57 x 57ピクセルでピクセル職人してました(爆)
物理的に無理です。はい。
で、調べたらアイコンは複数指定できるそうです。
・iPhone3Gアイコン:icon.png(57 x 57px) ・iPhone4アイコン:icon@2x.png(114 x 114px) ・iPadアイコン:icon@-72.png(72 x 72px)
これをResourcesフォルダに格納しておけば、iPhone4なら114 x 114で自動判別してくれます。 うーん、ここら辺はちょっと不親切すぎる気がするので、Xcode4で改善して欲しいですね。
とういう事で、時間があれば一連の作業を記事にしようかと。
なぜiPhoneアプリのメモリ管理が面倒くさいか?なぜGCが便利化? ちょっとずつわかってきたような気がするこの頃。
Objective-Cを始めた頃は、どうしても「おまじない」で物事が進んでしまいます。 (ある意味仕方がないのですが) 2010/05/04 Objective-C 基礎編 Vol2
周知だとは思いますが、iOSにはガベージコレクションが使えない為、
リファレンスカウンタ方式
つまり、デバッグツールやretainCountでちゃんと確認しておかないと、 いずれはメモリリークしてしまいます。
retain、copy、assign
この使い分けがわからないので、初めは「おまじない」でコーディングしてしまいがち。
@property (nonatomic, retain) NSString *name;
みたいに、参考書どおりに宣言することがほとんどになるかと思います。
まずは、Nosue's log iPhoneプログラミング講義のフォローアップ資料の翻訳2 に基本的な使い分けが記載されて、わかりやすいかと思います。
(1) オブジェクトでない場合、指定しないかassignを指定 ※delegateはassign (2) copy オブジェクトの場合、assign、retain、copyのいずれかで指定。 (3) @propertyでretain, copy指定すると、各setter, getterの実装が不要 ※指定しない場合はassignがデフォルトとなり、プリミティブ型はassignにする ※逆にオブジェクト作成時にretain、copyを指定するとretainCountが増加する (4) オブジェクトが同時に使用される可能性がある場合は、無難にnonatomicにしておく。 ※通常は、nonatomic
---2011/05/09 追記 2011-02-20 [iPhone] メモリ管理 の記事も読んでおくとよいかも。
#import
@interface RetainTestViewController : UIViewController {
NSString *nameRetain;
NSString *nameAssign;
NSString *nameCopy;
}
@property (nonatomic, retain) NSString *nameRetain;
@property (nonatomic, assign) NSString *nameAssign;
@property (nonatomic, copy) NSString *nameCopy;
@end
#import "RetainTestViewController.h"
@implementation RetainTestViewController
@synthesize name;
- (void)viewDidLoad {
[super viewDidLoad];
//Retain
NSLog(@"retain0: %x %@ retain = %d",nameRetain, nameRetain, [nameRetain retainCount]);
nameRetain = @"Yoo"; //(1)
NSLog(@"retain1: %x %@ retainCount = %d",nameRetain, nameRetain, [nameRetain retainCount]);
nameRetain = [NSString stringWithFormat:@"Yoo"]; //(2)
NSLog(@"retain2: %x %@ retainCount = %d",nameRetain, nameRetain, [nameRetain retainCount]);
nameRetain = [NSString stringWithFormat:@"Hello %@", nameRetain]; //(3)
NSLog(@"retain3: %x %@ retainCount = %d",nameRetain, nameRetain, [nameRetain retainCount]);
nameRetain = [[NSString stringWithFormat:@"Yoo"] retain]; //(4)
NSLog(@"retain4: %x %@ retainCount = %d",nameRetain, nameRetain, [nameRetain retainCount]);
[nameRetain release]; //(5)
NSLog(@"retain5: %x %@ retainCount = %d",nameRetain, nameRetain, [nameRetain retainCount]);
nameRetain = nil; //(6)
NSLog(@"retain6: %x %@ retainCount = %d",nameRetain, nameRetain, [nameRetain retainCount]);
}
- (void)dealloc {
[super dealloc];
}
@end
2011-02-07 17:58:13.387 RetainTest[37717:207] retain0: 0 (null) retain = 0 2011-02-07 17:58:13.388 RetainTest[37717:207] retain1: 4044 Yoo retainCount = 2147483647 2011-02-07 17:58:13.388 RetainTest[37717:207] retain2: 4b025a0 Yoo retainCount = 1 2011-02-07 17:58:13.389 RetainTest[37717:207] retain3: 4b0dde0 Hello Yoo retainCount = 1 2011-02-07 17:58:13.389 RetainTest[37717:207] retain4: 4b039f0 Yoo retainCount = 2 2011-02-07 17:58:13.389 RetainTest[37717:207] retain5: 4b039f0 Yoo retainCount = 1 2011-02-07 17:58:13.390 RetainTest[37717:207] retain6: 0 (null) retainCount = 0
(1) retainCountが「2147483647」になっています。 これは、文字列を定数として保持しているからみたいです。 (2) stringWithFormatを介すとretainCountが1増加します。 (3) 文字を連結してもretainCountは変化しません。 (4) retainを記述すると、alloc/initと計2つretainCountが増加します。 (5) releaseにすると、retainCountが1減少します。 ただし、retainCountが0になってしまうと解放できないのでアプリが落ちます。 (6) nilにすると、retainCountが0となります。
で、このサンプルでは、NSStringに関してはretain,assign,copyのどれを使っても 結果が同じ(?)になりました。
//Copy
NSLog(@"copy0: %x %@ retain = %d",nameCopy, nameCopy, [nameCopy retainCount]);
nameCopy = @"Yoo"; //(1)
NSLog(@"copy1: %x %@ retainCount = %d",nameCopy, nameCopy, [nameCopy retainCount]);
nameCopy = [NSString stringWithFormat:@"Yoo"]; //(2)
NSLog(@"copy2: %x %@ retainCount = %d",nameCopy, nameCopy, [nameCopy retainCount]);
nameCopy = [NSString stringWithFormat:@"Hello %@", nameCopy]; //(3)
NSLog(@"copy3: %x %@ retainCount = %d",nameCopy, nameCopy, [nameCopy retainCount]);
nameCopy = [[NSString stringWithFormat:@"Yoo"] copy]; //(4)
NSLog(@"copy4: %x %@ retainCount = %d",nameCopy, nameCopy, [nameCopy retainCount]);
[nameCopy release]; //(5)
NSLog(@"copy5: %x %@ retainCount = %d",nameCopy, nameCopy, [nameCopy retainCount]);
nameCopy = nil; //(6)
NSLog(@"copy6: %x %@ retainCount = %d",nameCopy, nameCopy, [nameCopy retainCount]);
2011-02-07 17:58:13.390 RetainTest[37717:207] copy0: 0 (null) retain = 0 2011-02-07 17:58:13.390 RetainTest[37717:207] copy1: 4044 Yoo retainCount = 2147483647 2011-02-07 17:58:13.391 RetainTest[37717:207] copy2: 4b03180 Yoo retainCount = 1 2011-02-07 17:58:13.391 RetainTest[37717:207] copy3: 4e194e0 Hello Yoo retainCount = 1 2011-02-07 17:58:13.392 RetainTest[37717:207] copy4: 4b0c0d0 Yoo retainCount = 2 2011-02-07 17:58:13.392 RetainTest[37717:207] copy5: 4b0c0d0 Yoo retainCount = 1 2011-02-07 17:58:13.392 RetainTest[37717:207] copy6: 0 (null) retainCount = 0
ちなみに、NSStringはそのままcopyを利用できますが、その他のオブジェクトは基本的にcopyWithZoneで複製します。