2013年7月30日火曜日

iOS アプリリリースまでのメモ

<DevCenter>
1,devCenterへログイン
2,Certificates,Identifiers & Profilesへ
3, App IDs に登録。
   名称などを入れてPushNotificationを使えるようにして登録
   
4, Continueを押して確認画面へ、その後 Submit

5,Provisioning Profiles > Distribution
   プラスボタン

6、 What type of provitioning profile do you need?

        Distribution の AppStoreにチェックしてContinue
       
 7, Select App ID

       さきほど作ったAppIDをプルダウンで選択
     
8, Select certificaties

      以前、実機ビルドするために作っているはずなので割愛します。
      それを選択してContinue
     
9, Name this profile and generate

   適当な名前をつけてください。
   Generateを押す
 
10, プロビジョニングをDLしてダブルクリック

<iTunesConnect>
1,iTunesConnectにログイン
 devCenterと同じID/PW
 
2,Manage Your Apps へ

 Add New App ボタンを押す
 
 <AppInformation の入力>


  DefaultLanguage = JPNでもいいですが、Englishにしておくと後々はまりづらいです。
 
   AppName = AppStoreに表示するアプリの名前
     ※使われてるとエラーになります。
   SKU Number = ユニークなキー (適当でいいです)
   Bundle ID = プルダウンで選択。事前にDevCenterで作っておく必要があります。
   
    次の画面へ
   
  Availability Date
      いつからリリースしたいかです。通常は最短ですが、プレス打つ場合などは先の日付です。
     
  Price Tier  = いくらで売るか。こんかいはFreeで
 
  Discount for Educational Institutions = 学生とかにディスカウントするかどうか。Freeなのではずします。
 
  次の画面へ
 
  VertionNumber = 1.0
  copyright = TigerTech.inc とか?
 
 Primary Category = どのカテゴリのアプリにしたいか。
 Secondary category =  同上

 Rating = Simlated Gambling 以外はNoneで


 Description = アプリの概要を記述 じつは結構な長文が入ります。
 keyword = 検索キーワードをカンマ区切りで
 SupportURL = アプリの紹介ページが必要です。そのURL
 MarketingURL = 紹介サイトなど(不要)
 Privacy Policy URL = 不要
 
・AppReview Information
    担当者の連絡先などを記載
    
・DemoAccount Information
           デモ用のアカウントがあればそれを記載
         
         
 < Uploads>

※ ここは事前に用意が必要
 プロモーションの要素もかねているので、
 アプリの中で一番いい物をスクリーンショットとして選ぶ。
 画面の遷移の順番通の必要はないので、相手に見てもらいたい順にあげる。

 Large App Icon  = 1024 × 1024 の大きいアイコンが必要

 3.5Inch スクリーンショット

 4 Inch スクリーンショット



<バイナリをあげる>

1,XcodeにてSchemeを実機に設定 (実機にビルドするときと同じ物を選択)
2,Optionを押しながらRun ボタンを押して Debug からRelaseに変更
3、 Product >  Clean
4,  Product > archive
5, archiveが終わると画面が変わるので Validateを押す。
6、Distributionを押す。
   AppStoreを選択。
   プロビジョニングが、上記で作ったものであることを確認


7、iTuneConnectにて Waiting For Reviewになっていることを確認






2013年1月23日水曜日

CoreData 小技 EntityからNSDictionaryをとる



CoreDataやってるとさ〜Mo(MamagedObject)とNSDictionaryのやりとりってめんどいですよね?
いちいち代入とかやってらんないよ!
っと言う方の為に小技を公開しちゃいます。


<NSDictinary to MO>


Entity * entity = ... ;
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:
    @"value",@"title",
    @"createDate",@"data",
     nil];
[entity setValuesForKeysWithDictionary:dic];

ま、これは厳密にいうとDate型とかFommaterで変換しなきゃいけないのでそんなに使わないですねw
よく使うのがMO to Dictionaryでしょう。

<MO to Dictionary>


Entity *entity = [[DataManager EntityListFrom:@"Entity" sort:nil pred:nil]lastObject];
NSDictionary *dic = [entity dictionaryWithValuesForKeys:[[[entity entity] attributesByName] allKeys]];


ちなみに前回のデータ取得の共通メソッドにて一行

[fetchRequest setResultType:NSDictionaryResultType];

と書けば最初からDictionaryでリストをとれます。

CoreData データ呼び出しの共通メソッド

前回のCreateに続いてReadの共通メソッド書きます。

ま、こんな感じ。
パラメータにエンティティの名前。そしてSortDescriptorとPredicateとlimitです。
SortDescriptorとPredicateについては他のところでも解説が多いので、そちらをみてください。
気が向いたら書くかもしれませんが。。。

DataManager.m
+(NSArray *)EntityListWithName:(NSString *)entityName  sort:(NSSortDescriptor *)sort
  pred:(NSPredicate *)pred  limit:(int)limit {

//※Moを拡張してます
NSManagedObjectContext* managedObjectContex=[NSManagedObjectContext managedObjectContextForCurrentThread];
    
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // 取得するエンティティを設定
    NSEntityDescription *entityDescription;
    entityDescription = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContex];
    [fetchRequest setEntity:entityDescription];
if(sort!=nil){
        NSArray *sortDescriptors;

        sortDescriptors = [[NSArray alloc] initWithObjects:sort, nil];
        [fetchRequest setSortDescriptors:sortDescriptors];
}else{
        NSArray *sortDescriptors;
        sortDescriptors = [[NSArray alloc] initWithObjects: nil];
        [fetchRequest setSortDescriptors:sortDescriptors];
    }
    
    // 取得条件の設定
if(pred!=nil)[fetchRequest setPredicate:pred];
    // 取得最大数の設定
    if(limit>0)[fetchRequest setFetchBatchSize:limit];
    // データ取得用コントローラを作成
    NSFetchedResultsController *resultsController;
 
    resultsController = [[NSFetchedResultsController alloc]
                          initWithFetchRequest:fetchRequest
                          managedObjectContext:managedObjectContex
                          sectionNameKeyPath:nil
                          cacheName:entityName];  
    // DBから値を取得する
NSError* error = nil;
    if (![resultsController performFetch:&error]) {
        abort();
    }
    NSArray *result = resultsController.fetchedObjects ;
    resultsController=nil;
    managedObjectContex=nil;
    
return result;
}


ちなみにカテゴリ実装でNSManagedObjectに下記を実装してます。
+ (NSManagedObjectContext *)managedObjectContextForCurrentThread {
    return [NSManagedObjectContext managedObjectContextForThread:[NSThread currentThread]];
}


呼び出しで共通メソッド作っておくと、さくっとArrayで返ってくるのでです(^^)

CoreData データ取得の共通メソッドを作っておく

こんにちは!ひさしぶりの投稿です。

今回はCoreDataについて。
基本的な部分エンティティの設定やら何やらは本でも読んでもらうとして。
それらを実装済みの状態で簡単にCoreDataを扱うサンプルを書いて行きたいと思います。

DBっていえばCRUD(クラッド)できないとですね。ちなみにCRUDとは

 C=Create
   R=Read
   U=Update
   D=Delete

です。
え?そんなこと知ってるって?
そーですね。失礼しましたw


とりあえずはRDBでいうSelect投げられないとですね。
でもCreateしないとReadできないか。

そんなわけでまずはCreateから。


とりあえずの仕掛けとして、シングルトンでmanagerクラス作るのが常識かもしれませんが、簡単にAppDelegateにてcoreDateの設定周りを書ききりmanagedObjectContextとかもAppDelegateに保持する感じで説明します。

AppDelegate.h

@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;

ただし、ほかのCoreData周りのコードも含めて別途シングルトンの管理クラスを作ります。
ここではDataManagerとでもしておきましょか。

DataManager.m


+(NSManagedObjectContext *)managedObjectContext{
     AppDelegate *delegate=(AppDelegate*)[UIApplication     sharedApplication].delegate;
return delegate.managedObjectContext;
}

続いて呼び出し側

簡単に言うと、インスタンス作ってそいつのプロパティに値入れて保存。
ちなみにUpdateの場合もインスタンスを呼び出して保存でいけちゃいますw

YourClass.m
Order *orderEntity = [NSEntityDescription insertNewObjectForEntityForName:@"Order" inManagedObjectContext:[DataManager managedObjectContext]];

    orderEntity.pos_order_id = order.orderId;
    orderEntity.amount = [NSNumber numberWithInt:order.orderAmount];
    orderEntity.created = order.orderDate;
    orderEntity.updated = order.orderDate;
    
        NSError *error = nil;
    [[DataManager managedObjectContext] save:&error];
    if (error) {
        //ここにエラー制御書きます
    }



はい、簡単ですね。
次回はReadについて書きたいと思います。


2012年2月27日月曜日

アプリのテンプレートを作ってみる

オレオレテンプレートがらみの話です。
ちょっとでも開発を楽にする為に
「テンプレートでも作っとこうかなぁ」

なんて事を言い出して、作り始めたら結構はまって
逆に大変な労力を費やしてしまう。。。

そんなパターンに僕もハマりつつありますが、 
そのまま前進することにします。 

まずは必要そうな機能をリストアップ。


  • ナビゲーションで画面遷移
  • ローディングビュー
  • デバッグログ
  • ローカライズ(Localizable.strings / InfoPlist.Strings)
  • モデル実装(モデルオブジェクト,モデルリストクラス,データマネージャークラス)
  • リクエストマネージャークラス(通信の仕組み)
  • FNCクラス(各種情報の定義、ユーザデフォルト管理、C言語化した関数)
  • SNS連携
  • plistにドキュメント登録
  • URLスキーム
  • アプリ内課金View
  • アプリ紹介などのWebView
  • jsonライブラリ
  • アドモブSDK
  • サウンド再生関係
  • メール送信機能
  • 設定画面
  • OpenGLにてobjファイルを回転させるView
  • TableViewパーツとり用クラス
  • ViewControllerのお決まりテンプレート

NavigationControllerにて画面遷移するようにしておく

俺俺テンプレート第一弾ってことで、まずは画面遷移を作っていきたいと思います。

AddSubViewパターンとかmodalViewパターンはいつでも使えるので、ここではやらない。
NavigationControllerを使ったパターンを実装していきます。



まずはsingleViewのテンプレートにて新しいプロジェクトを作る

1、NavigationControllerによる画面の遷移を実装する。
AppDelegate.h
rootControllerプロパティを追加

#import <UIKit/UIKit.h>

@class ViewController;

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (nonatomic,retain) UINavigationController* rootController;
@property (strong, nonatomic) ViewController *viewController;

@end



AppDelegate.m
起動時に呼ばれるメソッドを少しいじる

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];
   
    //起点となるViewControllerを設定
    rootController = [[UINavigationController alloc]initWithRootViewController:_viewController];//追加
   
    self.window.rootViewController = self.rootController;//変更
    [self.window makeKeyAndVisible];
    return YES;
}




#動作を確認の為の準備
適当なViewControllerをプロジェクト上に作る。ここではSecondViewControllerとする。


ViewControllerに #importする。
ViewControllerに適当なボタンを作ってIBActionのメソッドを実行できるようにする。

メソッドの中は下記の通り

-(IBAction)buttonDidPush:(id)sender{
    SecondViewController* viewController =
    [[SecondViewController alloc]initWithNibName:@"SecondViewController" bundle:nil];
    [self.navigationController pushViewController:viewController animated:YES];
    [viewController release];
}



アプリを起動してボタンを押したら画面が遷移したら成功だ。
 ちゃんちゃん


2012年2月14日火曜日

Plistから配列にする


アプリ上で使う要素を配列にする時にこんなコードは書いてないだろうか?

  NSMutableArray* array = [NSMutableArray alloc]init];
      [array addObject:@"Source1"];
      [array addObject:@"Source2"];
      [array addObject:@"Source3"];
            -----続く---------

もちろんこれでも間違いじゃないけれど、要素が100個くらいあると
しんどいしコードが長くなる。

そんな時はPlistを使って配列に起こすようにすると色々と楽だ

よくあるサンプルだと下記のようにやっているけれど、Xcode4.xにて作ったplistはこれじゃ読込めない。 試しに実行してみるとarrayWithContentsOfFileの戻り値がnilにて返ってくるはずだ。
    NSMutableArray* array = [[NSMutableArray alloc]init];
    NSBundle* bundle = [NSBundle mainBundle];
    NSString* path = [bundle pathForResource:@"list" ofType:@"plist"];
    NSArray* list = [NSArray arrayWithContentsOfFile:path];   
   
    for(NSString* str in list){
        [array addObject:str];
    } 

  
Plistがきちんとした形式になっていないとnilが返ってくる仕様だが、xcode上で作ったplistが読込めない。

Plistを右クリックしてSourceにて開いてみると。。。

一番頭のタグが<dict>になっている。

 下はXcode3.xにて作ったPlist。

  
頭のタグが<array>になってますね。

要するにXMLの階層構造がXcode4から変わっているってことです。
なので、 dictionaryWithContentsOfFile を使ってNSDictionaryを生成するのが正解。
まず、keyをきちんととれるように下記のようにplistを作りかえます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Root</key>
    <array>
        <string>要素1</string>
        <string>要素2</string>
    </array>
</dict>
</plist>



取得するコードは下記の通り。
一度 NSDictionaryにしてからobjectForKeyにて配列を取得するんですね。

    NSBundle* bundle = [NSBundle mainBundle];
    NSString* path = [bundle pathForResource:@"list" ofType:@"plist"];
    NSDictionary* dic = [NSDictionary dictionaryWithContentsOfFile:path];
    NSArray *items =[dic objectForKey:@"Root"];
   
    for(NSString* str in items){
        [array addObject:str];
    }

plistの作りようでは、配列の中にdictionaryを入れてそこからモデルオブジェクトを格納した配列にするなんてこともできちゃいます♪


2011年12月6日火曜日

画像を縮めますかね? え? いいって? まあ、そんなこと言わないでw

今回は画像を小さいくしていきます。
下のメソッドは、引数にUImageとサイズをぶっこんでいって 
小さく なったUIImageを返すというものです。

こりゃ解説するまでもないね。
コンテキスト作って、そこに描画して、それをgetなんちゃらしてUIImageにする。

でもあえて書くとすると、
なぜ  [image drawInRect:rect]; なんだ?ってことかな。 

もちろん
CGContextDrawImage(context, rect, image.CGImage);という書き方もあります。
でもこれだとY軸が反転しちゃうんだな。



-(UIImage*)shrinkImage:(UIImage*)image size:(CGSize)size{
   
    // 計算した描画領域を指定して描画準備。
    CGRect rect = CGRectMake(0, 0, (int)size.width, (int)size.height);
    UIGraphicsBeginImageContext(rect.size);
   
    // 描画はすべて新しい描画領域が対象となる。
    [image drawInRect:rect]; // イメージ描画。
    // 新しい描画領域からUIImageを作成。
    image = UIGraphicsGetImageFromCurrentImageContext();// スケーリングされたUIImageを設定。
    UIGraphicsEndImageContext(); // 解除。
   
    return  image;
}

画面遷移の3パターン

こんにちは、こーじーです。

iPhoneアプリの開発を始めて僕が最初にハマったのは画面遷移です。
画面を移動する為に主に3つの方法があるのですが、そのうちNavigationControllerを使う方法でかなりはまりました。
基底となるViewControllerを設定していなかったり、もともとIBを使わずにコードだけで画面を作っていたものを後からXib化すると動かないとか。


3つの方法って?という方もいらっしゃるのではないでしょうか?



これです!
 1、 AddSubViewを使ったパターン
 2、 modalViewを使ったパターン
 3、   NavigationControllerを使ったパターン


そのうち一番めんどうなのがNavigationControllerを使ったパターンだと思いますねー

基本となるのが1番目のAddSubViewのパターンです。
でも、僕が一番好きなのは2番のパターンなのでこちらから。







modalViewControllerのパターン
-(void)ch{

    SecondViewController * viewController =
[[SecondViewController alloc]initWithNibName:@"SecondViewController" bundle:nil];
[self presentModalViewController:viewController animated:YES];
[viewController release];}


戻る側のViewには
-(void)back{
   [self dismissModalViewControllerAnimated:YES];
}


このパターンは戻る側のコードが変化しないで書けるので、
ViewControllerを部品化しやすいのと、
アニメーションが簡単なのが便利です。



UIViewControllerのプロパティmodalTransitionStyleを変更することでアニメーションを変化させることができます。
  • UIModalTransitionStyleCoverVertical
    • 下から上にせり出してくる。デフォルトはこれ。
  • UIModalTransitionStyleCrossDissolve
    • 画面がフェードアウト、フェードインする
  • UIModalTransitionStyleFlipHorizontal
    • 水平方向に画面がくるっと回る(フリップする

使い方は、呼び出し側でviewControllerインスタンスを生成して
[self present〜 を呼び出す前に

viewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;  
などの一行を書くだけ。








AddSubViewパターン
これはViewControllerのインスタンスを作ってaddSubViewするだけです。
コードで書くと

-(void)ch{
    SecondViewController * viewController =
[[SecondViewController alloc]initWithNibName:@"SecondViewController" bundle:nil];
[self.view addSubView:viewController.view];
[viewController release];
 }

戻る側のSecendViewControllerの実装は
-(void)back{
    [self.view removeFromSuperView];
 }


NavigationControllerパターン
  
まずAppDelegateに宣言をします。
// ヘッダにて宣言を追加
@interface AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
        UIViewController* rootController;
     FirshViewController* viewController;
 



つづいて、起動時に呼び出されるメソッドに記述をします。
  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {   
   
    FirstViewController *top = [[[instrumentViewController alloc]init]autorelease];
   
    //起点となるViewControllerを設定
    rootController = [[UINavigationController alloc]initWithRootViewController:top];
   
    // Add the view controller's view to the window and display.
    [window addSubview:rootController.view];
    [window makeKeyAndVisible];


これでNavigationControllerによる画面遷移の準備が整いました。

次にFirstViewContollerから次のViewに画面遷移するコードです。
   
-(void)ch{ 

SecondViewController *viewController = [[Config alloc] initWithNibName:@"SecondViewController" bundle:nil];  //これはxibからViewVontrollerのインスタンスを作っている。

.ctrl = self;//値を設定するものがあればここで入れる

    if(conf){
        [self.navigationController pushViewController:viewController animated:YES];
    }
}
}


この方法で画面遷移すると、移動後のViewにNavigationBarと戻る為のボタンが自動で表示されます。NavigationControllerのスタック領域にViewControllerのインスタンスをPushして画面を移動し、戻るとPopされて格納したデータが破棄されます。

動き的にブラウザのリンクを辿っていって、戻るボタンで戻るといった動きと同じと思っていただければイメージしやすいですね^^
スタックとは要するに後入先出しのデータ格納領域のことです。

もちろんこの領域に直接アクセスして画面遷移することもできます。
例えば、今は5番目の画面だけれど2番目に開いた画面に戻るとか。




ではまた!






※NavigationControllerパターンについては、オレオレテンプレートを作るにちょっと詳しく書き直しましたw




  

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 角をばつんと落とす。

2011年5月26日木曜日

よく使う文字列操作その2

良く使う文字列操作を書き終わった後に色々思いついちゃったので、続編を書きたいと思います。
そういえば文字列の長さを取得するメソッドとかも書いてなかったし。。。
まあ、だいたいどの言語でもlengthなんでobj-cのルールに乗っ取って書けば [str length]; になりますね。
ちなみに、前回で解説してきたNSMutableStringクラスはNSStringクラスのサブクラスになるので、NSStringクラスで使えるメソッドは使えます。


文字列の比較。
これは [str isEqualToString:str2]; です。
例えば、
NSString *str = [NSString stringWithString:@"山田”];
if ( [str isEqualToString:@"田中"]) {
NSLog(@"%@!この野郎!",str);
}

って感じで、strが田中だった場合は、何だかぶっそうな展開になります。
上の例では isEqualToString:メソッドの戻り値はNO(Boolean)で返ってくるので、特に修羅場にはなりません。


パスからディレクトリ名などを切り出す。

まず、バンドルのリソースファイルを取得します。

NSString *path;
path = [bundle pathForResource:@"background" ofType:"@png"];

NSLog(@"%@",path);

これの実行結果が" /user/document/background.png" だとします。

//ファイルの拡張子を取得
NSString *extension;
extension = [path pathExtension];

NSLog(@"%@",extension);
//実行結果:png

//ファイル名を取得
//例ではファイル名入れてpathForResourceしてるんですが、まあ練習ということで (^^;)

NSString *fileName;
fileNamee = [path lastPathComponent];
NSLog(@"%@",fileName);
//実行結果: background


//ファイルが存在するディレクトリを取得
NSString *directory;
directory = [path stringByDeletingLastPathComponent];
NSLog(@"%@",directory);

//実行結果: /user/document


そうそう、忘れていました!型変換でもつまずく型は結構いるんじゃないでしょうか。

他の言語なら、異なる型で宣言した変数に入りさえすれば。。。ふふふ、なんて事にもなりますが、obj-cではそうはいきません。
無理矢理キャストというのも無いみたいです。
NSString *str = [NSString stringWithString:@"123"];
NSInteger int = 35 + (NSInteger) str;
なんてやったら確実に怒られますw

[str intValue];
でinteger に型変換できます。ダブルの場合は
[str double];
です。


Obj-Cのメソッドの名前って覚えずらいですよね。
何かを見ながらコード書くより声に出してみた方が案外覚えられることに最近気づきました。僕だけかもしれませんが。

2011年5月25日水曜日

良く使う文字列変換をまとめてみる

Objective-Cに慣れちゃったという人は読み飛ばしてください。
今回はかなりの初級編。

Excelの関数から始まり、VBAでプログラムデビューした自分にとってObj-Cの文字列変換ってどうにも親しみづらいイメージがありました。
ネットや本であれこれ調べて、最近はようやく慣れましたが。
そこで、良く使うパターンをまとめちゃいます☆


NSStringってクラスはご存知ですか?
Obj-cの文字を扱うクラスです。一度設定したら変更できないですね。

例えば。。。
NSString *str = @"str";
str = @"str2";

とかは怒られてしまいます。
なので、変更可能なクラスである NSMutableStringを個人的には多用します。
まあ、変更する必要がなければNSStringの方がプログラムの効率が良いのですがね。


文字列変換でやりたい事って、大体決まってますよね。
文字列連結に文字列置換に文字列取り出しってところでしょうか。おまけで型変換。特にC言語のStringにしたいってケースは良くあるかも。

生成を含めてズバリしたの5つ

文字列生成 > [NSMutableString stringWithFormat:str];
文字列連結 > [NSMutableString appendString:str];
文字列置換 > [NSMutableString stringByReplacingOccurrencesOfString:str1 withString:str2]
文字列取り出し > [str substringWithRange:NSMakeRange(0,1)];
UTF8に変換 > [str UTF8String];



まずは良く使う形。
NSMutableString *str1 = [NSMutableString stringWithFormat:@"SELECT * FROM TABLE WHERE id = %d",100];

stringWithFormatメソッド。これは文字列が格納された変数を生成するときによく使います。
最初の@””に囲まれた文字列が格納したい本体。%dには数字(Integerなど)を表す変数みたいなもの。
C が書ける人にはおなじみですね。
で、カンマで区切ってその「%d」の中に入れる数字が続きます。この「100」の部分は変数でもいいです。
VBのformat関数みたいなものですね。


少し発展させるとこんな感じになります。

NSString *str = [NSString stringWithFormat:@"%02d:%02d",Number/60,Number % 60];

変数Numberには数字が入っています。まあ、秒数だとしましょう。
上のコードは秒数から「00:00」に表記を変えるコードです。
%02dは二桁の数字という意味です。 1 = 01 ,11 = 11 ってな感じです。
%02dがコロンを挟んで二つならんでいると思います。そしてカンマで区切られた式が二つ。
分かりやすく構造だけ書くと下のようになります。

[NSString stringWithFormat:@"%d%d", (一つ目の%dに対応) , (二つ目の%dに対応) ];

要するに%何とかの個数が増えれば、それに対応させてカンマで区切られた値なり式が増えるんですね。
実際にSQLなんかを合成させてみるとこんな感じになります。
%dの代わりに使われている%@には文字列を格納しています。
一行目のコードで生成した文字列に appendString:メソッドで文字列を連結しています。
連結する文字列は stringWithFormat: で別途生成したも文字列になります。
末尾の NSLog関数で生成したSQLの内容をコンソールに表示させています。
NSLogの使い方は、ほぼStringWithFormatと同じ書式です。

NSMutableString *str1 = [NSMutableString stringWithFormat:@"%@",@"INSERT INTO Data1 VALUES"];
[str1 appendString:[NSMutableString stringWithFormat:@" (%d,'%@',%d,%d,%d,'%@','%@','%@');"
,[Array count]
,[Name_ stringByReplacingOccurrencesOfString:@"'" withString:@"''"]
,Number_
,info_
,SoundType_
,[soundName_ stringByReplacingOccurrencesOfString:@"'" withString:@"''"]
,infoSoundName_
,itemCode_
]];
NSLog(@"%@",str1);

文字列連結は
[NSMutableString appendString:@"文字列”]; です。
このメソッドを使うと、末尾に任意の文字列を連結できます。
 
NSMutableString *str = [NSMutableString stringWithFormat:@"今日は%d月%d日です。”,12,25];
[str appendString:@"なんだクリスマスじゃないか!”];
[str appendString:[NSMutableString stringWithFormat:@" じゃあ%d円くらいなら、おごってあげるよ。"]];

と、連結しまくりです。
上のコードでは文字列置換もやっています。痴漢じゃないですよ。置換。
この部分。
[Name_ stringByReplacingOccurrencesOfString:@"'" withString:@"''"]

Nameに含まれるシングルクォートをエスケープして['']シングルクォート二つに変更しています。
今時はみなさんCoreDataを使っているでしょうが、もしSqliteを使っているならば
生成したSQLに文字列が含まれるようなものを扱っているならば、シングルクオートをエスケープしとかないと
ユーザーがシングルクォーテーション付きの文字列を入れて登録〜っとやった瞬間にエラーぶっこきますよw

と、余談はさておき、

文字列置換は
[NSMutableString stringByReplacingOccurrencesOfString:str1 withString:str2]
となっていて、str1とstr2を入れ替えるんですね。

NSMutableString *hatugen = @"今回のプロジェクトは田中君にまかせることになった。がんばりたまえ”;

もし、田中が気に入らなくて鈴木さんに変更したいのならばこうだ。
[hatugen stringByReplacingOccurrencesOfString:@"田中” withStirng:@"鈴木"];


最後に文字列取り出し。
obj-cはVBとかエクセルの関数みたいにLeftとかMidとかじゃないんだけど、
にたようなものがあるのでそれを使う。

NSString *str = [NSString stringWithFormat:@"%02d:%02d",Second/60,Second % 60];
n1.text = [str substringWithRange:NSMakeRange(0,1)];//一文字目
n2.text = [str substringWithRange:NSMakeRange(1, 1)];//二文字目
n3.text = [str substringWithRange:NSMakeRange(3, 1)];//三文字目
n4.text=[str substringWithRange:NSMakeRange(4, 1)];//四文字目

NSMakeRange( 開始位置, 文字数) なので [str substringWithRange:メソッドを使えば、
エクセルの関数のMid(ミドル)的に取り出せる。


後は、変換した文字列の使い道としては、UILabelか UIButton かといったところでしょうか。
UILabel は Label.text = @"ラベルだどぉ";
UIButtonは [button setTitle:@"ボタンタイトルです。" forState:UIControlStateNormal];
って感じです。


今回は「良く使う文字列変換」についてでした~


2011年4月29日金曜日

アプリをローカライズする手順メモ

Localizable.strings を用意する.




  • ファイル>新規ファイル>Resource>Strings Filesと選択












  • Localizable.string をResourcesフォルダに入れる




  • Localizable.string を右クリックし[情報を見る] を選択





    [一般] タブの下部にある[ファイルをローカライズ可能にする] ボタンを押下





  • [一般] タブに、"ローカリゼーション"欄ができる
    [ローカリゼーションを追加] ボタンを押下。一覧に出てこない国名はISO-639の省略形をつければ良い。韓国なら「kor」かな?







  • ファイルを開いてローカリゼーションの追加をおこなっていく
    例:"Hellow"="こんにちは";








アプリ名のローカライズ



  • Localizable.stringを作った時と同じような手順で、"InfoPlist.string"というファイルを作成する.
  • InfoPlist.string は、アプリの設定ファイルである Info.plist の項目を、ローカライズ毎に上書きするために用いるファイルとなる.
  • 特に、Info.plist の内容をローカライズする必要が無いときには、 InfoPlist.string を作成する必要は無い.


CFBundleDisplayName = "Hellow Timer"; CFBundleDisplayName = "Hellow Timer";

プログラム側をLocalizedStringに対応させる



正式に書くなら下のような感じ。 NSString *localizedString = [[NSBundle mainBundle] localizedStringForKey:@"Hoge" value:@"Hoge" table:nil]; ただし、マクロが用意されているので下記で書くのがふつう NSString *localizedString = NSLocalizedString(@"String", @"message"); messageは特に表示されるわけでは無いので@""と空にしても良い。

Xibのローカライズ




これの右クリック>情報をみる から設定が可能。
でも、かりにIBで画面を作っていたとしてもViewDidLoadのところでラベルやボタンのタイトルにlocalizedStringでテキストを再設定するように書いておいた方が明らかに便利。

国によって表示する画像や色を変えたりという場合に使うのかな。
でも、どの国でどういうデザインがうけるのかリサーチが必要だな。。。


その他、Sqliteのファイルもローカライズする設定がでてくるんだけれど、国別にファイルを分けられるって事?
うーん、必要にかられたら今度実験してみよう。
でも、必要なカラムを持っておいてコードで分岐させる方が楽かな。

NSArray *languages = [NSLocale preferredLanguages];
//NSLog(@"preferredLanguages : %@", languages);

language = [languages objectAtIndex:0];

こんな感じで NSStringで持って来ちゃえばいいんだもんなぁ。

2011年4月22日金曜日

とりあえずプロジェクトを作ってみる

順序がおかしいかもしれませんが、ようやくXcodeを使ってプロジェクトを作ってみるところを解説したいと思います。

  • Xcodeを起動


  • 新規プロジェクトを選択


  • Window-Basedにてプロジェクトを作成



  • プロジェクト名はとりあえず「Hellow-World」としますか。
  • とりあえずビルドしてみる。


ビルドしてみて真っ白な画面が出れば成功です。 シュミレーター(実機でもよい)にもインストールされて真っ白なアイコンが表示されていますね。

それではプロジェクトの中身を色々と見て行きます。


グループとファイル>Hellow-Worldの左横の▶をクリックするとツリー状に整列されたフォルダーが出てきますね。 これがHellow-Worldというアプリの中身になります。
  • Classes
    Hellow-WorldAppDelegate.hとHellow_WorldAppDelegate.mがあります。Objective-Cのクラスファイルは.hと.mのファイルが2つで一組になります。プロジェクト名+AppDelegateという名前のファイルがこのアプリの全ての動作を全てまかされた代表のファイルのなります。ちなみにDelegateとは代理という意味です。
  • Other Sources
    1. アプリ名_Prefix.pch
      コンパイル開始時に実行する事を書くファイル。今は変更しない。
    2. main.m
      このファイルが一番最初に実行される。が、いじる事はない。
  • Resources
    • MainWindow.xib
      アプリケーションの内容を描画する為のウインドウ。
    • アプリ名-info.plist
      プロパティリスト。XML形式でアプリのさまざまなプロパティ情報を保持する。アプリをリリースするまでには必ずいじる。
  • Frameworks
    • UIKit.framework
      アプリケーション・ユーザインターフェイスの構築と管理に必要なクラスの集合体
    • Foundation.framework
      Cocoaフレームワークの基礎的な部分を担当するAPIの集合体です。
    • CoreGraphics.framework
      グラフィックのAPI。
  • Products
用語解説
  • API
    要するにプログラムの固まり。これにより、機械語レベルのプログラミングを人間が書かないですむ。
  • フレームワーク
    APIを寄せ集めたものだと個人的には理解。


次回はiOSの概要について解説します。