アプリ内課金について その1 準備編

自分のためのメモなので、アプリをリリースした事がある人を対象に書いていきます。
アプリ内課金って何? という方は、概要を説明しているサイトは沢山あるのでそちらをどうぞ。

アプリ内課金は、サーバー型とコンテンツ内蔵型があるのだけれど
今回はコンテンツ内蔵型について。
最初から機能をアプリの中に組み込んでおいて、購入処理が済むとロックを解除してその機能を使えるようにするということをやりたい。

  1. デブセンのAPP IDsにて InAppPurchaseがEnableになっている事を確認
  2. itunesConnectにてバイナリをアップする直前の状態にする。ステータスは「Waiting For Upload」
  3. itunesConnect-> ManageUsers -> Test User からテスト用アカウントを登録
    1. あくまで登録のみ。実アカウントとは関係のないアドレスを設定する
    2. 本番の環境に作成したテストアカウントでログインしてしまうと無効になってしまう。
    3. 使用するのは、sandboxにてテスト時に入力する時。
  4. itunesConnect-> ManageUsers -> Manage Your In App Purchases にてプロダクトを作成
    1. Create New -> プロダクトを作成するアプリを選ぶ -> 必要事項を入力
    2. 一通り項目を入力したら、画像ファイルをアップする前にSave
    3. その後、画像ファイルまでアップする必要があるかはわかりません。
    4. Typeは Non-Consumable 、Cleared for Sale はYESにしないと有効にならない。

組み込み編に続く

※後日「Horigoodの日記」さんの記事を見て、アプリのバイナリが上がっていないとテストができないとか何とか。ここははまりどころ。




参考
iTunes Connect開発者ガイド
https://itunesconnect.apple.com/docs/iTunesConnect_DeveloperGuide_JP.pdf

Horigoodの日記
http://iphone-dev.g.hatena.ne.jp/horigood/20100105/1262696433

UIAlertViewのカスタマイズ「addTextFieldWithValue:label:」を乗り越える その2


NSLog(@"%@",NSStringFromClass([view class])); をループの中に書いてクラス名を拾ってみる

2011-03-29 19:03:02.636 ApplicationName [8352:307] UIImageView
2011-03-29 19:03:02.639 ApplicationName [8352:307] UILabel
2011-03-29 19:03:02.641 ApplicationName [8352:307] UILabel
2011-03-29 19:03:02.644 ApplicationName [8352:307] UIThreePartButton
2011-03-29 19:03:02.646 ApplicationName [8352:307] UIThreePartButton
2011-03-29 19:03:02.648 ApplicationName [8352:307] UITextField

なんと!! 枠は UIImageView じゃないですか?
これは、勝手に写真とかを入れちゃえるってことですよね?

ボタンはというと。。。
UITreePartButton ってなんだ?
この名前を使ってクラス判定すればよいんだけど、これ自体が非公開だったらいやなので
下記のようにしてUIImageViewを捕まえて、その他にこのUITreePartButtonが来るようにする。

for(UIView *view in self.subviews)
{
 if ([view isKindOfClass:[UILabel class]]) {
				
   CGRect viewFrame = [view frame];
   viewFrame.origin.y = viewFrame.origin.y + ObjectMaxY;
   [view setFrame:viewFrame];
   ObjectMaxY = ObjectMaxY + viewFrame.size.height;

  }else if([view isKindOfClass:[UITextField class]]){
   CGRect viewFrame =CGRectMake(kUITextFieldXPadding
                                ,labelMaxY + kUITextFieldYPadding
                                , alertWidth - 2.0*kUITextFieldXPadding
                                , kUITextFieldHeight);
   [view setFrame:viewFrame];
				

  }else if([view isKindOfClass:[UIImageView class]]){


  }else{
   CGRect viewFrame = [view frame];
   viewFrame.origin.y = labelMaxY + kUITextFieldYPadding +kUITextFieldYPadding + kUITextFieldHeight;
   [view setFrame:viewFrame];
}
}

実のとこ、これでもUILabelの位置が重なっておかしいのだけれど
僕はTitleを @””にて設定して使っているので、まあいいや。

UIAlertViewのカスタマイズ「addTextFieldWithValue:label:」を乗り越える その1

アプリも完成間近にさしかかり、深刻なエラーはないものの、警告が多かったのでそれをつぶしにかかる。
あれこれ調べているうちに「addTextFieldWithValue:label:」というメソッドが非公開APIという位置づけにある事を知った。
ということは、リジェクトを食らうってこと?


TextFieldからの値を取得したり、レイアウトを決めるのには元々のUIAlertViewをカスタマイズしたクラスを作れる必要があるんだろうなと思っていたところに、ちょうどいいものを発見!

「TextAlertView.m」
http://discussions.apple.com/message.jspa?messageID=8445879#8445879

すでに誰かが作ってくれているならこれを参考に作っちゃいましょう♪


中を見てみると、

  • (id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate

cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ...;
にて TextField付きのUIAlertViewを作っている事が分かる。



呼び出しもとはこんな感じ

TextAlertView *alert = 
[[TextAlertView alloc] initWithTitle:@"title" message:@"message"
			   delegate:self
			cancelButtonTitle:@"Cancel"
			otherButtonTitles:@"Add",nil];
[alert show];

ボタンを押されたときのアクションはこれ,でもTextFieldの値を取得している部分で警告になっちゃうのね。もしかすると、ここもカスタマイズが必要かもしれない。

-(void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
	switch (buttonIndex) {
		case 0:
		   break;
		case 1:
			Text = [[alertView textField] text];
			
			if([appDelegate.timerName length]<1){
				UIAlertView *alert = [[UIAlertView alloc] init];
				alert.delegate = self;
				alert.title = @"title";
				alert.message = @"message No input";
				[alert addButtonWithTitle:@"OK"];
				[alert show];
				return;
			}
			[self addBookmark];
			 
			break;
	}
	
}

さらに layoutSubview でレイアウトを整えている。イニシャライズされた後に呼ばれている事が分かる。
素直に実行してみるとうまくいかない。
横向きのアプリを作っているからかもしれないけれど、修正が必要な箇所は以下のとおりでした。

  1. タイトルがアラートの枠からはみ出ている。
  2. TextFieldの横幅がアラートを突き抜けている。
  3. ボタンの位置が高すぎる


どうすればカスタマイズできるか?
[alertView subViews]objectAtIndex:i]でオブジェクトを拾って来れる事が分かった。
参考
http://viksiphoneblog.blogspot.com/2010/08/how-to-customize-alert-view.html

どれがどのオブジェクトさえ分かれば

[[[alertView subviews] objectAtIndex:4] setTitleColor:[UIColor grayColor];

とかで色とかサイズを決めていってしまえばいい。


そこでTextAlertViewのlayoutSubviewsメソッドの中身をいじってみることに。
下のコードだとラベルから高さを決定していく。


for(UIView *view in self.subviews)でオブジェクトを拾ってきて
if ([view isKindOfClass:[UILabel class]]) にてクラス判定している部分があるので
ここで位置などを書き換えてみる。

あれれ?何かおかしい?
if ([view isKindOfClass:[UIButton class]])
で引っかかってくるオブジェクトがない?
もちろんObjectAtIndexで指定して行けばいいんだけれど、Indexは{枠、タイトル、メッセージ、キャンセルボタン、ボタン ×n、テキストフィールド}の順になるのでボタンを増やしたときに対応できなくなってしまう。
なので、やはりfor(UIView *view in self.subviews)の中でクラスを判定して
レイアウトを整えたい。

オブジェクトの数をNSLog(@"%d",[[self subviews]count]); で調べると6個だった。
タイトル、メッセージ、テキストフィールド、OKボタン、キャンセルボタン、アラートの枠だとすると6個でつじつまが合う。
layoutSubviewsを実行した感じでは、UILabelとUITextFieldは拾って来れているみたいだ。
あとは、ボタン2つと枠を拾ってこれればよい。

つかれたので次回へ続く。

池上さんおすすめ書籍

昨日の「そうなんだニッポン」で池上彰氏が行きつけの本屋さんに行くという企画があったんだけど、
そのなかで池上氏が勧めていた本がとても気になったのでメモ。

特に池上氏が小さい頃に読んでいたものでクオレ (少年少女世界文学館 22)とか君たちはどう生きるか (岩波文庫)はとても気になった。


池上氏の説明は本当に分かりやすい。分かりやすすぎて、もしこんな先生に小学生のころからマンツーマンで教えられていたら誰でもちょっとしたすごい人になっちゃうんじゃないのかな。
ただ説明がうまいというだけじゃなくて、見せ方なんかもものすごく考え抜いているんだろうなぁ。
自分もああいうプレゼンをできるようになりたいものだ。



もしドラ効果でドラッカーのちゃんとした本も売れているらしいね。


ポケットジャンベ (PocketDjembe)

Koji Okada


加速度センサーを使って音の強弱を表現!?
アフリカの伝統的な太鼓、ジャンベのアプリです。



iphone/ipad/ipodのタッチスクリーンに対して器具・道具を使用したり過度な強さで押さないでください。故障の原因となります。




Contact
oktechinfo@gmail.com

iphoneアプリリリースに必要な手順

アプリ提出の手順のメモ書き


1、必要なもの
  提出用のアプリ
  アプリのスクリーンショット
  512×512のアイコンファイル
  アプリの説明文(海外で売るなら英語のも)

  ディストリビューション用のプロビジョニング

2、info.plistの設定

Bundle display name = アプリの名前(長すぎると切れてしまうので注意)
日本向けアプリならLocalization native development regionをjapanに。
Bundle identifier=アプリごとの識別ID
Bundle version =1.0

3、ディストリビューション用のプロビビジョニングの作成
証明書の作成
developerCenter>Certificates>Distribution[タブ]

プロビジョニングファイルの作成
Provisioning>Distribution
Distribution Method = appstoreを選択(adhoc はappstoreを通さないでソースを配布するための手順)
プロファイルを先ほど作成した証明書にならって入力

証明書とプロビジョニングファイルをダウンロードしてダブルクリックしてインストール


4、プロジェクトの構成にDistributionを追加
プロジェクト>プロジェクト設定の編集>「構成」タブ
releaseをコピーしてDistributionにリネーム
これで、ビルドメニューにdebug,release,Distributionの三つが表示されるはず。
一度クリーニングしてからビルドメニュー「ビルド」。


5、アプリファイルを作成
プロジェクトフォルダ>build>>Distribution-iphoneos>XXXX.app
をzipにしておく。
これは最後にApplicationloaderというソフトで提出することになる。

6、ituneConnectにログインして設定。
https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa
Manage Your Application>「Add New Application」をクリック

初めての場合は
デフォルトの言語=English
開発元の名前を設定

これらは一度設定するとずっと変更できないので注意。



Application Name = アプリの名前
Application Description = アプリの説明
Device = 対応するデバイス
Primary Category = アプリのカテゴリ
Copyright = 著作権表示。開発者の名前などを入力。
Version Number =1.0(アプリに設定したバージョンと同じもの)
SKU Number = 製品番号。ユニークなIDを任意に設定
Support URL =App Storeに表示されるサポートのリンクに設定するURL
Support Email Address = メールアドレス

すべて入力したら次へ。
  画面ショットなどのファイルを画面にならってアップロードし、価格などの情報を入力。

iAdの情報を設定。二回目からはEnable or Disableと17歳以下を対象にするかどうかの設定のみ。初回は有料アプリと同じく口座情報などを設定する必要がある。(これはけっこう面倒くさい)


7、すべての情報を設定したら、右下のアップロードが準備ができましたボタンを押す。
ApplicationLoaderのダウンロードボタンがあるのでDLする(初回のみ)

8、ApplicationoLoadeを立ち上げて、アップロードの準備が整っているアプリ(zip)を選択してsend.

ここでもしエラーがでるようであれば、プロビジョニングファイル周りがおかしいのでDevCenterにログインして設定を見直して、Xcodeのプロビジョニングを入れ替えて再度ビルド。

Excel小ネタ1

B列に値が入っていない行をまとめて削除する

Sub delete_row()

Dim i As Integer

    For i = 4 To 200 'とりあえず200行までループ
        If Cells(i, 2).Value = "" Then
          Rows(i & ":" & i).Delete
        End If
    Next i

End Sub


セルにセットされているハイパーリンクを隣のセルに書き出す。

Public Sub getUrl()
  Dim h As Hyperlink
  Dim address As String
  Dim subAddress As String
  
    For Each h In ActiveSheet.Hyperlinks
    address = h.Address
    subAddress = h.SubAddress
    
        If subAddress <> "" Then
      address = address & "#" & subAddress
    End If
    h.Range.Offset(0, 1) = address
  Next
End Sub


セルの番号から列名を取得

i = ActiveCell.Column
 
 If i >= 1 And i <= 256 Then
    t2 = Mid(Cells(1, i).Address, 2, InStr(Cells(1, i).Address, "1") - 3) & "4"
  Else
    t2 = ""
  End If


ハイパーリンクの解除

Sub deleteLink()

Dim link As Hyperlink

For Each link In ActiveSheet.Hyperlinks
  link.Delete
Next link
End Sub