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を入れてそこからモデルオブジェクトを格納した配列にするなんてこともできちゃいます♪