2011年11月25日金曜日

画像をPhotoLibralyに保存する


さて、前回作った画面キャプチャのUIImageって何に使うんだ?と思った人は多いでしょうね。
まあ、使い道としてはカメラやフォトライブラリから取得した写真をごにょごにょして、それをまた保存するなりメールで送りたいって感じでしょうかね。

コールバック関数の部分は別に nil にしてもらっても良いと思います。

-(void)saveToPhotoLibrary{

 UIImage* img = [self screenCapture];//前回の記事を呼んでちょ 
 NSData *pngData = UIImagePNGRepresentation(img);
 UIImage *screenImage = [[UIImage imageWithData:pngData] retain];
 
//コールバック関数の設定  
    SEL sel = @selector(savingImageIsFinished:didFinishSavingWithError:contextInfo:);
    UIImageWriteToSavedPhotosAlbum(screenImage, self, sel, nil);//ここのselが保存後に呼ばれる。

}



//コールバック関数

- (void)savingImageIsFinished:(UIImage*)image didFinishSavingWithError:(NSError*)error contextInfo:(void *)contextInfo{
   
    NSString* message;
    if(!error){
        message = @"success save";
    }else{
        message = @"fail save";
    }
    UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"保存" message:message
                              delegate:self
                              cancelButtonTitle:nil
                              otherButtonTitles:@"OK",nil];
    [alertView show];
    [alertView release];
}


2011年11月24日木曜日

お世話になった書籍たち

デベロッパー登録してはや一年半。
思えば、まったくアプリが売れてねぇ...



書籍だって何冊買ったかわからん位買ってるので、もうけるどころか大赤字です。
 まあ、今は本業でiOSやってるので就職活動代とみるか。。。

 始めたばかりの頃は、サンプルのコードを書き写してビルドするのが精一杯だったのですが、一体僕はどうやって開発できるようになったのだろう?
そんなことを考えてみました。
※そんなこと考える暇があったら設計書の一つでも書けと言われそうですが。。。





やっぱり大金をつぎ込んできた書籍達のおかげでしょうか。今日はその中でも厳選してご紹介致します。





interfaceBuilderを使わないというポリシーの本。
この本にどれだけ助けられたか。
そもそもInterfaceBuilderはわかりやすいけれど、ちゃんと使いこなすにはやっぱりコードが書けないとです。この本で学んでから、再びIBに戻ると新しい世界が開けます。
中級者くらいでも、ど忘れしたときに開くと便利かも。



MVCの何たるかが分かりやすく書いてあります。
この本の手法で、スマートで仕様変更にも耐えられるアプリが作りやすくなります。
アプリは作ったことあるけれど、デバッグしてるとよくBad Access食らってアプリが落ちるなんてひとにもおすすめかも。
中級者向け。



OpenGL ES1なのでちょっと古い感じになりましたが、この本にもすごく助けられた。OpenGLなんかやってられるかと思っていたけど、この本のおかげでなんとかなることが分かりました。
この本をやりつつ、OpenGL ESのクラスリファレンスを読むとより理解度が高くなるかもしれません。





目からウロコな一冊。パフォーマンスに関する部分は読まずに死ねるかという感じ。




これは枕にするにはちょうどいい本。はじめは呪文に見えましたw
iOSに関係ないガーベジコレクションについても書かれています。上を目指すには必読。




この本から、未だにかゆいところに手が届くネタを見つけることがあります。お気に入りの一冊。



iOS4の新機能に特化した書籍。カメラ周りやblocksについてなど内容は盛りだくさん。読んで納得の一冊。




唯一のCoreAudioの本。音系のアプリを作るなら必携の一冊。



真剣に読むというよりは、持っておくと便利な本。
 



この本のサンプルは作ってて楽しかった♪
UIKitを一通り触ってもうちょっと何かって人にお勧めです。




僕が初めて買った本。
書いてある通りに作ればサンプルは作れます。だけど、肝心のところが理解できないかも。
これと併用してObjective-Cの文法の本を買うと良いと思います。

cocos 2d関連


敷居の高そうなcocos2Dを自分の土俵に引きづり込めた一冊。おすすめ




上のやつを読んでからこの本を読むとよさそう。



開発以外



いろいろとアプリの企画からプロモーションまで為になることが書いてある。

画面をキャプチャする


久しぶりの投稿ですみませんm(_ _)m

最近 CoreGraphicsにハマってます。(以下 コアグラ)
いやーいろいろできて便利です♪

もう既にコアグラしてるぜっ!って人は突っ込みどころ満載かもしれないので手加減してくださいね。

まずは、画面に映ったものをUIImageに
しちゃいましょうか。

こんな感じ。


- (UIImage *)screenCapture {
   
    UIImage *capture;
    CGRect rect = self.view.frame;
   
    UIGraphicsBeginImageContext(rect.size);//コンテキストを作る。
    [[UIApplication sharedApplication].keyWindow.layer renderInContext:UIGraphicsGetCurrentContext()];//スクリーンからキャプチャしてコンテキストにレンダリング
    capture = UIGraphicsGetImageFromCurrentImageContext();
    

 UIGraphicsEndImageContext();//コンテキストを閉じる。
   
    return capture;



コアグラでイメージ作るのは、大抵そうなんだけど
メモリ上の空間(コンテキスト)に描画して (ここでは画面に結果が出力されない)
そいつを 
capture = UIGraphicsGetImageFromCurrentImageContext(); 

 でUIImageとして取り出す方法が基本w 




上の例では、ナビゲーションバーとかも画面に映ったものは問答無用でUIImageにしてるけれど
[app.view.layer renderInContext:UIGraphicsGetCurrentContext()];
とかに変更すると、Viewで狙いうつこともできます。

リリース前のplistとかプロジェクト周りの設定について

 あー、完全に自分の為のメモです

アイコン
iPad用とRatina ディスプレイ用にアイコンファイルを設定する。
用意するファイル
Icon.png = 57×57
Icon@2x.png = 114 × 114 (iPhone4用)
Icon-72.png = 72 × 72 (iPad2用)

plist設定
Icon file を空欄にする
行を追加してIcon filesを選ぶ。Item 0 Item1と追加して、項目にアイコンのファイル名を入れていく。
これにより、デバイスによって最適な画像のサイズを選んでアイコンを表示してくれるようになる。

必要であれば、検索で表示されるときの小アイコンも設定する。

Icon-Small.png 29 × 29 (iPhone3GS用小アイコン)
Icon-Small-50.png 50 × 50 (iPad用小アイコン)
Icon-Small-@2x.png 58 × 58(iPhone4用小アイコン)



<メモ>
iPad対応にする手順
http://blog.myrss.jp/archives/2010/04/iphone_ipad.html

2011年6月6日月曜日

LocalizedStringファイルの生成を半自動化する。

開発の規模が大きくなってくると、LocalizedStringの数がハンパなく多くなってきますね。
プログラマが複数名いて、とにかく自由奔放にNSLocalizedString()マクロを書きまくっていると収集がつかなくなります。
ソースコード上ではNSLocalizedStringしてるんだけど、ローカライズのファイルにその文言がなかったりとか
微妙に文言が違うとかありがち。


そんなんで時間をかけているのも馬鹿馬鹿しいけれど、表示の文言も大切な仕様です。
表記違いもプログラムの深刻なバグも同じと考える人もいるかもしれません。


そこでこのうざい問題を秒殺する方法を考えましたw


まず、すべての文言をリスト化します。
僕はこの作業でExcelを使います。Mac使いだからってWindowを使っちゃいけないって法律はないし。
管理しやすいし、文字列変換のコードがくそ簡単に書ける。



まず、ソースコード上のNSLocalizedStringをテキストに吐き出します。
ターミナルを開いて、プロジェクトが置いてあるフォルダのClassへ移動。基本的なコマンドがわからん!って人は簡単なので勉強してください。

下のコマンドを実行

grep -i "NSLocalizedString" $(find . -name '*.m') | less >> result.txt

これやると、どのクラスファイルで何をローカライズしようとしてるかがテキストファイルになります。

続いてウインドウズへ。
VBEを開いて下のコードをコピペ。

sub getLocalize()
Const cnsTITLE = "テキストファイル読み込み処理"
Const cnsFILTER = "全てのファイル (*.*),*.*"
Dim xlAPP As Application ' Applicationオブジェクト
Dim intFF As Integer ' FreeFile値
Dim strFILENAME As String ' OPENするファイル名(フルパス)
Dim strREC As String ' 読み込んだレコード内容
Dim GYO As Long ' 収容するセルの行
Dim lngREC As Long ' レコード件数カウンタ
Dim allString As String
Dim allArray As Variant
Dim strbuf As String
Dim lineArray As Variant
Dim splitArray As Variant
Dim lineCount As Integer
Dim z As Integer
Dim y As Integer
Dim row As Integer

Rows("2:65536").ClearContents
' Applicationオブジェクト取得
Set xlAPP = Application

strFILENAME = xlAPP.GetOpenFilename(FileFilter:=cnsFILTER, _
Title:=cnsTITLE)

If StrConv(strFILENAME, vbUpperCase) = "FALSE" Then Exit Sub


intFF = FreeFile

Open strFILENAME For Input As #intFF
GYO = 1

Do Until EOF(intFF)
' レコード件数カウンタの加算
lngREC = lngREC + 1

' 改行までをレコードとして読み込む
Line Input #intFF, strREC
' 行を加算しA列にレコード内容を表示(先頭は2行目)
GYO = GYO + 1
allString = allString & strREC
Loop
' 指定ファイルをCLOSE
Close #intFF

allArray = Split(strREC, vbLf)

row = 2
For i = 2 To UBound(allArray)


lineArray = Split(allArray(i), "NSLocalizedString")

If UBound(lineArray) > 0 Then
Cells(row, 1).Value = lineArray(0)
End If

For lineCount = 1 To UBound(lineArray)
lineArray(lineCount) = "NSLocalizedString" & lineArray(lineCount)
z = InStr(1, lineArray(lineCount), "@")
y = InStr(1, lineArray(lineCount), "nil") - 3
strbuf = Left(lineArray(lineCount), y)
Cells(row, 2).Value = Replace(Replace(Replace(Replace(strbuf, "NSLocalizedString", ""), "(", ""), "@", ""), Chr(34), "")
row = row + 1
Next lineCount



Next i


end sub



こいつを実行するときれいに形を整えてエクセルに取り込んでくれます。これを元にエクセルで翻訳リストを作成。
吐き出しようには下のモジュールを使う。
普通のテキスト吐き出し(フリーファイルとかFileSystemObject)とかだとUnicodeを扱えないのでADOStreamを使う。

参照設定でADOにチェック。
こいつを実行すると、実行したエクセルファイルと同じ場所にLocalized.Stringを吐き出すってわけ。
このファイルをそのまま使うんじゃなくて、ここからコピペをする予定なのでBOMとかはとってないです。

Sub getLocal()

Dim i As Integer
Dim endline As Integer
Dim str As String
Dim path As String
Dim endC As Integer
Dim strUni As String
'オブジェクトを作成
Dim txt2 As Object


Dim xlAPP As Application

Dim fileName As String ' OPENするファイル名(フルパス)
Dim strREC As String ' 書き出すレコード内容


Dim str_buf As String

path = Application.ThisWorkbook.path
endline = Cells(65536, 1).End(xlUp).row
endC = Cells(1, 200).End(xlToLeft).Column



For C = 2 To endC
Set txt2 = CreateObject("ADODB.Stream")

'オブジェクトに保存するデータの種類を文字列型に指定する
'txt2.Type = adTypeText
txt2.Type = 2
'文字列型のオブジェクトの文字コードを指定する
txt2.Charset = "UTF-16"

'オブジェクトのインスタンスを作成
txt2.Open

'//翻訳を作る処理

strREC = ""
strUni = ""
fileName = path & "\" & Cells(1, C).Value & ".txt"

For i = 2 To endline



If Cells(i, 1).Value <> "" And Left(Cells(i, 1).Value, 1) <> "#" Then
str = Chr(34) & Cells(i, 1).Value & Chr(34) & "=" & Chr(34) & Cells(i, C).Value & Chr(34) & ";"

Else
str = "//" & Cells(i, 1).Value
End If
str = Replace(str, "\" & Chr(13), "\n")
str = Replace(str, Chr(10), "")








'1行ずつ書き込む
txt2.WriteText str, adWriteLine




Next i

'オブジェクトの内容をファイルに保存
txt2.SaveToFile (fileName), adSaveCreateOverWrite


'オブジェクトを閉じる
txt2.Close

'メモリからオブジェクトを削除する
Set txt2 = Nothing


Next C

MsgBox "ファイル出力が完了しました。"
End Sub



このファイルを上手に使えば、翻訳リストとソースコードと実際のLocalizedStringファイルをマッチングして、ローカライズ漏れを一網打尽にすることができます。

2011年5月27日金曜日

Core Graphicsで図形を描く

まーるさんかくしかーくー♪
ってことで、今回は図形を描写します。

まずこれ。簡単な四角形から。





-(void)drawInContext:(CGContextRef)context
{
CGContextSetRGBStrokeColor(context, 1.0, 0, 0, 1.0);

CGContextStrokeRect(context, CGRectMake(20.0, 20.0, 100.0, 200.0));

}
CGContextStrokeRect(context, CGRect);で枠だけの四角を描く。

次にこれ
-(void)drawInContext:(CGContextRef)context
{
CGContextSetRGBStrokeColor(context, 1.0, 0, 0, 1.0);

CGRect rect = CGRectMake(20.0, 20.0, 200.0, 300.0);
CGContextStrokeRectWithWidth(context, rect,10.0);

}

CGContextStrokeRectWithWidth(context, rect,線の太さ);で線の太さを変更できる四角を描く

次にこれ

-(void)drawInContext:(CGContextRef)context
{
CGContextSetRGBStrokeColor(context, 1.0, 0, 0, 1.0);

CGRect rect = CGRectMake(20.0, 20.0, 200.0, 300.0);
CGContextFillRect(context, rect);

}

はい、真っ黒〜
CGContextSetRGBStrokeColorは線の色なので、下の塗りつぶし色の設定を追加します。
CGContextSetRGBFillColor(context, 1.0, 0, 0, 1.0);



再び実行。
まさにRectを塗りつぶした形になります。




次に丸を描いてみます。

CGContextAddEllipseInRect(context,rect);//線の円
CGContextFillEllipseInRect(context,rect);//塗りつぶされた円
CGContextAddEllipseInRect(context,rect);//パスを追加

これも分かりやすいですね。


三角形はどうしょうでしょうか。
特にそれ用の関数は無いので、線を引いてその中を埋めていきます。


CGContextMoveToPoint(context,160.0,10.0);
CGContextAddLineToPoint(context,10.0,200.0);
CGContextAddLineToPoint(context,310.0,200.0);
CGContextFillPath(context);//塗りつぶす


この書き方だと、複数図形があってそれぞれ異なる色で塗りつぶしたり、はたまた線だけの図形を描くときにどうするんだろう?
で、一回一回完結させてみた。

-(void)drawInContext:(CGContextRef)context
{

CGContextSetRGBStrokeColor(context, 1.0, 0, 0, 1.0);
CGContextSetRGBFillColor(context, 0, 1.0, 0, 1.0);

CGContextMoveToPoint(context,160.0,10.0);
CGContextAddLineToPoint(context,10.0,200.0);
CGContextAddLineToPoint(context,310.0,200.0);


CGContextFillPath(context);

CGContextStrokeEllipseInRect(context, CGRectMake(10, 200, 100, 100));

CGRect rect = CGRectMake(10,210 , 100, 100);
CGContextAddEllipseInRect(context,rect);
CGContextStrokePath(context);

CGContextSetRGBFillColor(context, 1.0, 1.0, 0, 1.0);
CGContextFillEllipseInRect(context,CGRectMake(200,200,100,200));

}



とりあえず図形についてはこれでおしまい。

Core Graphicsを学ぶ

何となく CoreGraphics 辺りを書きたい気分に。
これを使って何かをしようと思ったことが無いので、個人的にも勉強しながら書いていくというスタンスです。


Core Graphicsは、UIImageとかよりもちょっとだけ低レベルなグラフィックフレームワークだとか。
Cocoa Touchよりもハードウェアよりに位置するので、実行速度も多分速くなるし自由度も増す。
Core何とかと名前がついているAPIは大抵C言語で提供されているんだけれど、Core Graphicsもそうらしい。
ってことは、呼び出しが若干煩雑になるってこと。


とりあえず、プロジェクトに CoreGraphics.frameworkを追加してみる。


1、グラフィックスコンテキスト
書籍なんかでは描画する対象を表すものだとか何とか書かれている。まあ、良くわからんが Core Graphicsを使った描画では、最初にグラフィックスコンテキストを取得しないといけないってことだけは確かだ。

 CGContextRef UIGraphicsGetCurrentContext();
 

とりあえず実践。
すべての描画はdrawRect: メソッドの中に記述するか、この中から呼ぶメソッドに記述しないと動かないらしいので、Viewを一丁つくってdrawRectにメソッドを書いておく。

これ、コメントを削除したアップルさんのサンプルと一緒w
引数でグラフィックコンテキストも作って渡しちゃう。

-(void)drawRect:(CGRect)rect
{
[self drawInContext:UIGraphicsGetCurrentContext()];
}


呼び出されるメソッドの中身はこれ。
なにやってるかはコメントに記載しました。
-(void)drawInContext:(CGContextRef)context
{
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);//線の色。引数はcontext, R,G,B,アルファ。

CGContextMoveToPoint(context, 20.0, 50.0);//線の始点
CGContextAddLineToPoint(context, 300.0, 50.0);//線の終点から線を生成
CGContextStrokePath(context);//線を引く
}


はい、びしっと線が引けたかと。

じゃあ、これを使って折れ線グラフ的な線も引けるんじゃないかと言うのが人情ですね。
上のやり方でちまちまやってもいいのですが、まとめてやる方法があります。

-(void)drawInContext:(CGContextRef)context
{
CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);
CGPoint lines[] =
{
CGPointMake(10.0, 90.0),
CGPointMake(70.0, 60.0),
CGPointMake(130.0, 100.0),
CGPointMake(190.0, 70.0),
CGPointMake(250.0, 90.0),
CGPointMake(310.0, 50.0)
};

CGContextAddLines(context, lines, 6);
CGContextStrokePath(context);

}


これで、真っ赤なガタガタ線が引けたかと思います。



最初にCの配列 lines を生成してCGPointをぶっこみにいってます。
CGContextAddLines関数。末尾に”s”が付いてるので複数形ですね。第一引数はcontext、次に接点を保つ配列が第二引数。最後の引数は接点の数です。 
 この最後の引数の「6」ですが、実際のプログラムでは動的に入れたいというケースがほとんどなので、ここを
 sizeof (lines)/ sizeof( lines[0]) とするとスマートです。
sizeof はメモリのサイズを返すので、配列全体のサイズを最初の一個目のサイズで割ると、CGPointひとつひとつで確保しているメモリのサイズは同じなので、配列の数 = 接点の数が算出できるというわけです。obj-Cみたいに[ Array count ] とかできないところがもどかしいですね。


<その他>

太さの設定
CGContextSetLineWidth(context, x);
x は?pxということ。

たばこと丸と四角

・線の端っこの形の設定。
CGContextSetLineCap関数で設定。まさに名前の通りw
 ラインキャップを設定するんですね。キャップは両端にかぶせます。
 
 kCGLineCapButt = 両切りタバコ状態
 kCGLineCapRound = 丸いキャップをするんですね。
 kCGLineCapSquare = 四角いキャップ。
 
 
 CGContextSetLineCap = kCGLineCapRound;
 
 Buttという単語はアメリカ英語だとタバコって意味もあるらしくて、灰皿を Butt tray とかとも言うらしい。でも、アメリカ人以外には通じないらしいw
 
 
 
ジョイントの方法

CGContextSetLineJoin = kCGLineJoinMiter;

miter joint(マイタージョイント)っていうのは、斜めに切った角材を張り合わせた感じの事をいうらしい。
ふむふむ。

kCGLineJoinMiter マイターに
kCGLineJoinRound 丸くつなぐ
kCGLineJoinBevel 角をばつんと落とす。