<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Selfkleptomaniac &#187; Apple</title>
	<atom:link href="http://selfkleptomaniac.org/archives/category/apple/feed" rel="self" type="application/rss+xml" />
	<link>http://selfkleptomaniac.org</link>
	<description>Blogging is a disease: selfkleptomania, your normal condition.</description>
	<lastBuildDate>Tue, 07 Feb 2012 06:53:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>Titanium MobileではAnalyticsを切っておきましょう</title>
		<link>http://selfkleptomaniac.org/archives/2046</link>
		<comments>http://selfkleptomaniac.org/archives/2046#comments</comments>
		<pubDate>Mon, 06 Feb 2012 10:07:17 +0000</pubDate>
		<dc:creator>y</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Titanium]]></category>

		<guid isPermaLink="false">http://selfkleptomaniac.org/?p=2046</guid>
		<description><![CDATA[2年前の記事ですが、AppStoreのトップ無料や人気上位のアプリの68%がUDID（Universal Device Identifier）を送信しているという報告がありました（関連の日本語記事）。 利用状況などを収集 [...]]]></description>
			<content:encoded><![CDATA[<p>2年前の記事ですが、AppStoreのトップ無料や人気上位のアプリの<a href="http://www.appleinsider.com/articles/10/10/04/security_review_finds_68_of_top_ios_apps_transmit_udids.html" target="_blank">68%がUDID（Universal Device Identifier）を送信している</a>という報告がありました（<a href="http://gajethouse.blog3.fc2.com/blog-entry-276.html" target="_blank">関連の日本語記事</a>）。</p>
<p>利用状況などを収集してアプリの改善に利用するのはよくあることだとは思います。行動分析のためにデータを収集する場合、端末の識別のために何らかのIDが必要となるわけですが、スマートフォンでは最も簡単に利用できるのがこのUDIDです。このようなIDは以前から日本の携帯電話のサービスプロバイダでは広く利用されており、中にはウェブサービスの認証にまで使われているケースもありましたので、ある意味われわれにとっては非常に身近なものでもあります。</p>
<p>しかし、端末固有の一意なIDとして何かと便利に思われるUDIDですが、これを第三者に送信するのはあまり感心できません。上の報告ではHTTP通信のGETリクエストで送信しているアプリもあったようですが、これは論外です。しかし、もちろんそれだけが理由ではありません。</p>
<p>UDIDの送信がなぜ問題なのかについては諸説あるでしょうが、主な理由として考えられるのがエンドユーザの行動をトラッキングできてしまうことがプライバシーの侵害になるかもしれないという懸念です。同じようなことがいわれてきたブラウザのクッキーであれば、第三者のクッキー（Third-party Cookie）はブラウザの設定などでオプトアウトできるわけですが、UDIDは変更することができないため一度送信されてしまえば相手側の対応がなければ削除されません。アプリによってはその性格上、いつ起動していつ利用されたのか他人に知られたくないケースもあるでしょう。しかしUDIDが取得されてしまえば、第三者にその情報が漏れてしまいます。この手の試みはこれまでもウェブ広告の世界などでプライバシーとビジネスの間のせめぎ合いが何度も繰り返されてきた歴史があるわけですが、たいていはプライバシーの擁護が重視される結論に至っています。</p>
<p>ところでTitanium Mobileですが、Appcelerator社のサービスに登録している方なら一度くらいはAnalyticsの画面を見たことがあるかと思います。アプリのインストールされた数の推移や様々な行動分析が見られるので、開発者だけでなく企画等の担当者も大変重宝します。これらの情報はTitanium MobileのAnalyticsという機能を利用して送信されています。送信はSSLで暗号化されたPOSTリクエストになっているので、途中で覗き見られることについては、iPhoneの3G回線の通信がEnd-to-endのSSLではないなんてことはないでしょうから（<a href="http://blog.tokumaru.org/2011/07/ssl.html" target="_blank">ガラケーだとゲートウェイとウェブサーバ間のSSLになっていたりするようですが</a>）、さほど憂慮する必要はなさそうです。さらに、当然ながらAppcelerator社は集積したデータをさらに第三者に転売したり、広告などに悪用したりするようなことはしないと明言しています。その点で現時点で懸念する必要はないと思います。しかし、いくつか問題はあります。（１）データを集積しているAppcelerator社はアプリの配信元、エンドユーザにとっては無関係の第三者であること（２）送信される情報についてアプリの利用者から明確な許諾を得ていないこと（３）UDIDが送信されていること、などがそうです。</p>
<p>これらの対応策は非常に簡単で、tieapp.xmlをテキストエディタなどで開いて</p>
<pre>
&lt;analytics&gt;false&lt;/analytics&gt;
</pre>
<p>とするだけでこの機能をオフにすることができます。個人的な意見ですが、上記の理由から、現時点ではリリースされるアプリについては必ずこれをやっておく方がよいでしょう。もちろん、UDIDの送信が即、何か悪いことをしている証拠にはならないと思います。しかし、このような取り扱いに注意が必要なデータについては、トラブルを避けるためにも万全な状況でなければ利用しない方がいいはずです。また、iOS5から<a href="http://wirelesswire.jp/Watching_World/201108221335.html">UDIDの取得が非推奨となった</a>ことに伴い、やはりUDIDの送信は避けるべきでしょう。</p>
<p>実際のところどうなっているのか確認してみましたが、残念なことに1.8系の実装（iphone/Classes/PlatformModule.mやiphone/Classes/TiUtils.mを参照のこと）を見る限り、Titanium.Platform.idを送信していますね。1.8.0.1の場合はiphone/Classes/AnalyticsModule.mmを見るとわかります。実際にデータをダンプするには（SSLの通信をキャプチャするような面倒なことが好きな人を除いて）このファイルを下のように変更します。</p>
<pre>
$ git diff iphone/Classes/AnalyticsModule.mm
diff --git a/iphone/Classes/AnalyticsModule.mm b/iphone/Classes/AnalyticsModule.mm
index f76a472..46c6e81 100644
--- a/iphone/Classes/AnalyticsModule.mm
+++ b/iphone/Classes/AnalyticsModule.mm
@@ -217,6 +217,9 @@ NSString * const TI_DB_VERSION = @"1";
        [request setUseCookiePersistence:YES];
        [request setShouldRedirect:YES];
        NSString * stringifiedData = [SBJSON stringify:data];
+  //debug
+  NSLog(@"[DEBUG] Analytics sending data: %@", stringifiedData);
+  //debug
        [request appendPostData:[stringifiedData dataUsingEncoding:NSUTF8StringEncoding]];
        [request setDelegate:self];
</pre>
<p>ご覧頂ければわかる通り、UDIDが送信されていますので、やはり上に書いた方法でAnalyticsは停止した方がいいですね。それと、Appcelerator社が悪意をもってこの機能を実装しているのではないこともおわかり頂けるかと思います。だって、そうじゃなきゃソース公開してないですよね？個人的にはこういうところがTitanium Mobileを使い続けることの大きな理由になっています。</p>
<p>＊決してここの部分をいたずらして集積サーバに変なデータを送り込んでしまおうとか考えてるわけじゃないですからね！</p>
<p>また、この点について各方面に問い合わせたところ、Analytics自体は非常に有望なサービスなので、今後はUDIDを利用しないよう変更する予定になっているとのことでした。そのときが来たら再度検討してみたいと思います。</p>
<p>この数日、エントリを書いておきながら公開するべきか非常に悩んでいました。上で説明はしたつもりですが、これは別に情報が勝手に第三者に集積されてしまったというような事件ではなく、単純に機能としてソースまで公開され、ドキュメントにも書かれていることなわけで、簡単に調査も可能なことですから、開発者としては知っていてある意味当然なことです。ただ、どこかで誰かがこの機能について悪意的にかき立てるようなことがあれば、まだまだ少数のコミュニティで活発にやり取りしている状態のTitanium Mobileが今後プラットフォームとして成長する妨げになってしまうような打撃を受けると嫌だな、と思ったので、情報の周知徹底を目的に公開することにしました。</p>
<p>もう一度まとめます。</p>
<p>（１）Analyticsはオフにできるよ<br />
（２）オフにしとけばなんにも怖くないよ<br />
（３）UDIDは今後は使われなくなるよ</p>
<p>以上です。</p>
<img src="http://selfkleptomaniac.org/?ak_action=api_record_view&id=2046&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://selfkleptomaniac.org/archives/2046/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Titanium Mobileでアプリ内課金（iOS編）</title>
		<link>http://selfkleptomaniac.org/archives/2032</link>
		<comments>http://selfkleptomaniac.org/archives/2032#comments</comments>
		<pubDate>Fri, 03 Feb 2012 18:08:20 +0000</pubDate>
		<dc:creator>y</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Titanium]]></category>

		<guid isPermaLink="false">http://selfkleptomaniac.org/?p=2032</guid>
		<description><![CDATA[アプリ内課金の実装方法について知りたいという声があったので、参考になればと書いておきます。アプリ開発者の方は権利の15%で取引に応じますの苦労がこれで少しでも減るなら喜ばしいことです。とはいえ、世知辛い世の中ですから、こ [...]]]></description>
			<content:encoded><![CDATA[<p>アプリ内課金の実装方法について知りたいという声があったので、参考になればと書いておきます。アプリ開発者の方<s>は権利の15%で取引に応じます</s>の苦労がこれで少しでも減るなら喜ばしいことです。とはいえ、世知辛い世の中ですから、このコードで生じた金銭的問題の責任は放棄しますので、ご利用の際はあくまでも参考程度にとどめ、十分検証した上で実装されるようお願いします。</p>
<p>一応、動作は<a href="https://marketplace.appcelerator.com/apps/794" target="_blank">TiStorekit</a>1.4、Titanium Mobile SDK 1.8.1、非消費型コンテンツで確認しています。</p>
<p>iOSの場合、課金の手続きは</p>
<ul>
<li>In App Purchaseが有効になっているかを確認する</li>
<li>正しいProduct IDかを確認する</li>
<li>購入開始</li>
<li>成功ならレシートを受信してチェック、キャンセルやエラーならエラー処理</li>
</ul>
<p>となります。ここではAppcelerator社から公開されている<a href="https://marketplace.appcelerator.com/apps/794" target="_blank">TiStorekit</a>を使った実装の例で説明します。以前に実装したものを参考にざっと書いた関係で、細かい条件は検証していませんのであしからず。CoffeeScriptだけどいいよね？</p>
<p>事前にiTunes ConnectでIn App Purchaseの設定が完了していることが前提になります。iTunes Connectの使い方は割愛しますが、支払い関連の設定が完了していないとIn App Purchaseは有効になりません。またProvisioning Portalで設定を確認して、正しいProvisioning Profileでビルドしましょう。iOS5からシミュレータからも利用できるようになったようですが、必ず実機で動作確認してください。</p>
<p>そうそう、下のコードではコンストラクタで@SANDBOXをtrueにしていますが、リリース時には変更しましょう！</p>
<pre class="prettyprint">

class InAppPurchase
  constructor:()->
    @ERROR_PRODUCT_ID = {type:'product_id', message:L('inapp_error_product_id')}
    @ERROR_CANMAKEPAYMENT = {type:'canmakepayment', message:L('inapp_error_settings')}
    @ERROR_UNKNOWN = {type:'unknown', message:L('inapp_error_unknown')}
    @SANDBOX = true

  start:(data, success, error)->
    ###
    args  dataは課金対象の商品オブジェクト（{product_id:プロダクトID}）
          sccess、errorはそれぞれcallback関数
    ###

    storekit = require 'ti.storekit'
    if data.product_id == '' || data.product_id == null || data.product_id == undefined
      # なんて防衛的なコード！ #
      error(@ERROR_PRODUCT_ID)
    else if !storekit.canMakePayments
      # AppStoreが有効になっていない #
      error(@ERROR_CANMAKEPAYMENT)
    else
      # 正しいProduct IDかどうかチェック #
      storekit.requestProducts([data.product_id], (e)=>
        if e.success
          product = e.products[0]
          if product != null
            _success = success
            _error = error
            storekit.purchase(product, (elem)->
              if elem.state == storekit.FAILED
                error(@ERROR_PRODUCT_ID)
              else if elem.state == storekit.PURCHASED
                callback = (response)=>
                  if response.success &#038;&#038; response.valid
                    _success()
                  else
                    _error(@ERROR_UNKNOWN)

                # subscriptionの場合は下のオブジェクトにsharedSecretプロパティを追加 #
                args = {
                  receipt:elem.receipt
                  sandbox:@SANDBOX
                  callback:callback
                }
                storekit.verifyReceipt(args)
              else if elem.state == storekit.RESTORED
                storekit.restoreCompletedTransactions()
                success()
              else
                Ti.API.info "purchasing..."
            )
          else
            error(@ERROR_UNKNOWN)
        else
          error(@ERROR_PRODUCT_ID)
      )
TiStorekit = new InAppPurchase()
TiStorekit.start(product, success, error)
</pre>
<p>canMakePaymentsは定数でiOSの設定画面でAppStoreが有効になっていないのでそもそもアプリ内で課金ができない場合はfalseになります。requestProductsでProduct IDが正しいかどうかを確認し、purchaseで購入処理を開始します。successが返ればveryfyReceiptで確認して完了処理を実行します。</p>
<p>レシートの確認まで実装しましたが、ここは迷うところですね。通信に時間がかかったり、またはこのタイミングで処理が中断してしまった場合、利用者にとってはお金を払ったのに購入が正常に完了しないように見えてしまいます。時間がかかるようならキューに入れてレシートは後で確認し、いったん完了処理をしてから、不正があったらそれなりの処理をする、といったような手段で対応するしかないでしょう。かといってレシートを確認しないと、不正な利用を完全に防ぐことができなくなります。</p>
<img src="http://selfkleptomaniac.org/?ak_action=api_record_view&id=2032&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://selfkleptomaniac.org/archives/2032/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>どうしてTitanium Mobileなの？</title>
		<link>http://selfkleptomaniac.org/archives/2011</link>
		<comments>http://selfkleptomaniac.org/archives/2011#comments</comments>
		<pubDate>Sat, 28 Jan 2012 02:07:10 +0000</pubDate>
		<dc:creator>y</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Titanium]]></category>

		<guid isPermaLink="false">http://selfkleptomaniac.org/?p=2011</guid>
		<description><![CDATA[ウェブ開発者がiOSやAndroid向けアプリを作ろうと思い立った場合、今なら大きく分けて2つの選択肢があります。ひとつは他の人たちと同じようにObjective-CやJavaで素直にアプリを作ることです。まあ、当たり前 [...]]]></description>
			<content:encoded><![CDATA[<p>ウェブ開発者がiOSやAndroid向けアプリを作ろうと思い立った場合、今なら大きく分けて2つの選択肢があります。ひとつは他の人たちと同じようにObjective-CやJavaで素直にアプリを作ることです。まあ、当たり前ですね。もうひとつの方は、<a href="http://phonegap.com/" target="_blank">PhoneGap</a>や<a href="http://www.appcelerator.com/products/titanium-mobile-application-development/" target="_blank">Titanium Mobile</a>のようなサードパーティーのツールを利用してJavascriptなどウェブ開発者の慣れ親しんだ言語で開発するやり方です。それぞれ一長一短があります。先のやり方では、ネイティブな開発用言語だけあって全ての機能を最大限に活かすことができます。AppleやGoogleも最大限の開発支援を提供してくれることでしょう。しかし、Objective-CやJavaに慣れ親しんでいた人でなければ学習曲線がなかなか上昇してくれないかもしれません。特にウェブ開発者はWebObjectsをやっていた人でもない限りはObjective-Cに馴染みの無い人が多いでしょう。また、ヘッダファイルを書くことやDelegateみたいなまだるっこしいデザインに疲れてしまうかもしれません。そんな場合、サードパーティーのツールで素早く開発しながら徐々に慣れていく方が安全なやり方といえます。一方で、サードパーティーのツールには最上位のベンダつまりAppleやGoogleの意向でいつ排除されてしまうかわからないというリスクもあります。これまで見たところでは、今年や来年にそんなことが起きるとは到底考えられないのですが、それでも細かいトラブルはあるでしょう。</p>
<p>以上のような状況を鑑みるに、もしあなたがObjective-CやJavaでの開発に不安が残る状態であるなら、迷わず後者の方を選択するべきでしょう。その上で、自分の開発しているプラットフォームについて知ることは重要であり、そうであればいずれはネイティブな言語での理解が必須になるでしょうから、得られる知見を最大限に活かしてObjective-CやJavaでの開発について学んでいくのが理想です。例えば、PHPを使って開発をしていても、それだけしか知ろうとせず、ウェブサーバやPHP自体の実装といった抽象化されて隠された部分に分け入って進もうとしない人が、筆者の経験ではありますが、競争に耐えうる優秀な人材であった試しはありません。幸いにもサードパーティーのツールにはソースコードにアクセスできるものもあるので、良い手本になることがたくさん見つかるでしょう。</p>
<p>では、数あるサードパーティーのツールの中で、一体どれを選べばいいのでしょうか。</p>
<p>もちろん、おみくじで決めたとしても、それは当人の責任の範疇ですから、全く構いません。しかし、それでもやはり、いくらなんでももう少し真面目に考えないと不安になるかもしれません。なので、そうですね、それぞれのツールの特徴を掴んだ上で判断する方がいいでしょう。私自身も決定的な答えを用意しているわけではないので、知っている範囲で自分の意見を述べたいと思います。情報は最新とは限りませんので、ここは違う、いや今はこうなっている、などなどご意見あれば是非聞かせてください。いずれにせよ、現段階ではちょっとした宗派の争いみたいになりがちな話題なので、リラックスしてお読みくださいね。</p>
<p>サードパーティーのツール、と上ではひとくくりにしましたが、大きく分けるとこれも二種類に分かれます。ひとつはPhoneGapやRhodesのようにHTMLとJavaScriptで作ったUIをWebView（UIWebView）を使って表示させる、ウェブアプリとネイティブアプリが合体したようなもの、もうひとつはTitanium MobileのようにネイティブなAPIを叩いてJavascriptで記述しながらネイティブアプリとして動作するものです。ここでは実際に使ったことのあるPhoneGapとTitanium Mobileを比較します。</p>
<p>私見では、PhoneGapのいいところは第一にそれがシンプルであることです。例えば生成されるJavaのクラスは非常にシンプルで、実際に使ってみたところカスタマイズも容易でした。APIも数えるほどしかなく、プラグインの作成もそれほど難しいものではありません。また、UIはHTMLとJavascriptで作るので、ウェブ開発者やデザイナのこれまでに培った技術を活用することができそうです。</p>
<p>それに、例えばFacebookアプリは現在PC向けのものはHTMLで作られていますが、モバイル向けも今後は同じくHTML5を利用して記述され、Facebookのモバイル用アプリ内で動作するといったものになっていくことが予想されます。クロスプラットフォームでの開発が容易なのはHTMLの強みですから、こうした流れにソーシャルゲームのプラットフォームも追随していくのではないかと思います。</p>
<p>しかし、欠点もないわけではありません。jQuery MobileやSencha Touchといったツールを使ってなるべくネイティブアプリに似せることは出来ますが、それでもUIはネイティブなものではありません。これらのツールキットはまだ開発されてから日も浅くベストプラクティスも少ないので、<a href="http://www.sencha.com/learn/a-sencha-touch-mvc-application-with-phonegap/" target="_blank">開発はお世辞にも快適とはいえない</a>のですが、それなのに特にiOSではHTMLとCSSででっち上げた「ネイティブっぽい」UIの「偽物」っぽさが際立ちます。動作もまだまだ快適とはいえません。またネイティブな機能への橋渡しをしてくれるAPIも豊富とは言い難いので、少しでも複雑なことに挑戦すると結局Objective-CやJavaでプログラムを作成する必要が生じます。UIレベルの話ならまだしも、例えばiCloudへの対応といった要求にはツール側での対応を待つかそれなりの工数を費やしてプラグインを作成することになってしまうでしょう。それに、これは年月が解消してくれる問題なのかもしれませんが、例えばSnapdoragonの第1世代のIS03のような貧弱なハードウェアではWebViewのようなリソースを消費するものはどうしても動作が遅くなります。オリエンテーションの変更の際にレイアウトが酷く崩れるといったユーザに不安を与えるような現象が発生することもあります。</p>
<p>最近、PhoneGapの開発元がAdobeに買収されることが発表されましたが、資金的には大きな後ろ盾を得たと同時に、大企業であり、これまで数々のプロダクトをディスコンにしてきたAdobeにその命運を握られてしまったともいえます。</p>
<p>以上、駆け足ですが個人的に思うところを述べてみました。先ほども書きました通り、ここは違う、いや現在はこうなっているといったご意見などございましたらお知らせください。</p>
<p>さて、その一方でTitanium Mobileの場合、Javascriptで記述した内容は評価された後にプロキシを通じてiOSやAndroidのAPIに渡されて実行されるため、実際に動作するのは通常のアプリと同じものなので外観は全くネイティブなアプリと変わりません。と同時に、Titanium.UI.WebViewというものが用意されているので、やろうと思えばHTMLとJSでUIを作ってしまうことも可能です。またこのJSとネイティブな機能を繋ぐのも非常に容易なので、この点でも大きなアドバンテージがあります。動作速度はネイティブアプリと比較すれば、インタプリタとコンパイル言語ほどではなくても、まあある程度の差はあります。しかし、シビアな反応が求められるゲームや電子書籍リーダといった特定用途のアプリでなければ実際に問題になるほどではありません。ネットワーク越しにデータをやり取りするアプリ、ウェブサービスのフロントエンド用アプリとして利用するには十分といえます。それに、驚くべきことに、最近では<a href="http://code.google.com/p/quicktigame2d/" target="_blank">QuickTiGame2d</a>のような高速で動作するゲームエンジンも開発されていますので、ゲームの開発に利用されるようになる日も近いでしょう。また、このようなサードパーティーのモジュール開発も盛んで、<a href="https://marketplace.appcelerator.com/home" target="_blank">Open Mobile Marketplace</a>で有料、無料を問わずたくさんの機能拡張用モジュールが公開されています。Githubにソースコードが公開されているものも少なくありません。</p>
<p>それから、jQuery MobileやSencha Touch(Ext.JS)といった一種独特なJavascriptよりも、commonJSといったモダンなJavascriptで記述することが推奨されているのもポイントです。最近ではNode.jsのようなサーバサイドのJavascriptもありますが、Titanium MobileのJavascriptもCoffeeScriptやcommonJSのような今時の技術を習得する近道となるでしょう。というのも、Titanium Mobileは基本的にはよくあるイベント駆動型のGUIのプログラミングなので、Node.jsのようなコールバックにつぐコールバックの連続にも面食らうことはありません。</p>
<p>と、いいことばかり並べましたが、もちろん問題もないわけではありません。Aptanaを買収してEclipseベースの独自のIDEがリリースされましたが、Eclipseがそうであるように人によってはあまり快適とはいえないものです。もちろん使わないで開発することも可能ですが、最初はやはり公式なツールを使いたくなる方も多いでしょうから、そこら辺で面食らうこともあるかもしれません。またビルドスクリプト内部にビルドにかかる時間短縮のため高速化する工夫があるのですが、何度も繰り返してビルドするうちにそれが邪魔をしてアプリの挙動がおかしくなることがありますので、ときどきCleanしてあげる必要があるといった癖のあるところも見受けられます。また海外製品にありがちなことですが、Pythonを使ったビルドスクリプトはUTF-8のMac OS Xで日本語の処理に問題がある箇所が多数ありますのでアプリ名称やプロジェクト名、ソースコードのフルパスに日本語が含まれていると辛い目に遭います。その辺りは、日本語でも<a href="http://ti.masuidrive.jp/" target="_blank">有志によるサポートコミュニティ</a>がありますので、活用してください。</p>
<p>これらは今後改善されるべきことではありますが、一方で大半は公開されたソースコードから追いかけることも可能なことであり、ついでにいえばパッチを送って直してしまうことだって出来ます。個人的には、いつか大金持ちになって暇を持て余すようになったら、面倒の多いPythonの部分を全部Rubyにしてしまいたいと思っています。また、Titanium Mobileを入り口としていろいろと学びましたが、逆にネイティブな言語で開発しなくてもいいやという気にもなってきました。やっぱりDelegateとかってうんざりますよね？</p>
<p>以上、駆け足で比較していきましたので粗雑な部分、間違いなどもあるかもしれません。上にも何回か申し上げましたように、これは違うぞ、といったところがあればどしどしご指摘ください。よろしくお願いします。</p>
<img src="http://selfkleptomaniac.org/?ak_action=api_record_view&id=2011&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://selfkleptomaniac.org/archives/2011/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Titaniumでリジェクト・iCloud関連</title>
		<link>http://selfkleptomaniac.org/archives/1857</link>
		<comments>http://selfkleptomaniac.org/archives/1857#comments</comments>
		<pubDate>Tue, 22 Nov 2011 17:40:10 +0000</pubDate>
		<dc:creator>y</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Titanium]]></category>

		<guid isPermaLink="false">http://selfkleptomaniac.org/?p=1857</guid>
		<description><![CDATA[Titanium Mobileで作ったアプリがリジェクトされたので記念に。 今回リジェクトされた理由は、iCloud対応でデータの格納場所が厳密に定められ、チェック内容が変更になったからです。これからのアプリは生成された [...]]]></description>
			<content:encoded><![CDATA[<p>Titanium Mobileで作ったアプリがリジェクトされたので記念に。</p>
<p>今回リジェクトされた理由は、iCloud対応でデータの格納場所が厳密に定められ、チェック内容が変更になったからです。これからのアプリは生成されたデータを格納する際には以下のルールに従う必要があります。</p>
<p>(1) アプリが再生成できないファイルは/Documentsに保存</p>
<p>例えば、メモ帳アプリでユーザが書いたメモなんかはこちらに保存しないといけません。iCloudで自動的にバックアップされます。</p>
<p>(2) 再生成可能なファイルは/Library/Cachesに</p>
<p>データベースのキャッシュも含む、とありますが、ダウンロードされたファイルなどもここに置くのが正しいようです。</p>
<p>(3) 一時的なファイルはちゃんと/tmpに</p>
<p>アプリ終了時に消すのをお忘れなく。</p>
<p>(4) バックアップされては困るデータは&#8221;do not back up&#8221;</p>
<p>オフラインでの利用などで使いたい、iCloudやiTunesにバックアップされては困るファイルにはこの属性を追加しましょう。</p>
<p>さて、Titanium Mobileですが、例えばsqliteを使った場合、データファイルは/Library/Application Support/database以下に保存されてしまいます。残念ながら、Appleの新しい規制ではこれはリジェクトの理由になります。</p>
<pre>
Ti.Database.install('Resouces以下に置いたdbファイル', 'my_app');
</pre>
<p>このようにinstallを使って設置したデータファイルは/Library/Application Support/database/my_app.sqlとして保存されます。</p>
<p>これをAppleの規制に適応されるためには、例えば</p>
<pre>
Ti.Database.install('Resouces以下に置いたdbファイル', '../../Caches/my_app');
</pre>
<p>とすることで、/Library/Caches/my_app.sqlとして保存することができるようになります。</p>
<p>また、ファイルを保存する際にTi.Filesystem.applicationDataDirectoryを使っていた場合は</p>
<pre>
var root_dir = Ti.Filesystem.applicationDataDirectory + '../Library/Caches/';
</pre>
<p>このように変更すると/Library/Cachesを指定することができます。</p>
<p>既存のアプリをアップデートする場合は、Ti.Database.installを上のようにしてあげて、アプリの起動時に古いデータファイルを新しい場所に移動してあげるとかしないといけませんね。途中、スペースを含むパスがありますのでこんな風に指定します。</p>
<pre>
var db_file = 'my_app.sql';
var old_file = Ti.Filesystem.applicationDataDirectory + '../Library/Application%20Support/database/' + db_file;
var new_file = Ti.Filesystem.applicationDataDirectory + '../Library/Caches/' + db_file;
var old = Ti.Filesystem.getFile(old_file);
if(old.exists()){
  old.move(new_file);
}
</pre>
<img src="http://selfkleptomaniac.org/?ak_action=api_record_view&id=1857&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://selfkleptomaniac.org/archives/1857/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Titanium Mobileでアプリがリジェクト?!</title>
		<link>http://selfkleptomaniac.org/archives/1850</link>
		<comments>http://selfkleptomaniac.org/archives/1850#comments</comments>
		<pubDate>Sat, 12 Nov 2011 01:19:47 +0000</pubDate>
		<dc:creator>y</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Titanium]]></category>

		<guid isPermaLink="false">http://selfkleptomaniac.org/?p=1850</guid>
		<description><![CDATA[Appleのアプリ検証ツールのバグでTitanium Mobileで作成されたアプリがリジェクトされるようです。回避方法が発表されていたのでざっくり訳しておきました。 再度追記：Appleが審査用ツールを更新してこの問題 [...]]]></description>
			<content:encoded><![CDATA[<p>Appleのアプリ検証ツールのバグでTitanium Mobileで作成されたアプリがリジェクトされるようです。<a href="http://developer.appcelerator.com/blog/2011/11/layout-keyword-and-apple-app-analysis.html" target="_blank">回避方法が発表されていた</a>のでざっくり訳しておきました。</p>
<p>再度追記：Appleが審査用ツールを更新してこの問題はなくなったそうです。もう大丈夫。</p>
<p>追記：なんと、この方法ではうまくいかなかったとのこと。</p>
<blockquote><p>
Update: 2:42pm 11/13/11<br />
Appleの審査でのスキャンを回避する修正がCIサーバ上の全てのリリースブランチでご利用頂けるようになりました。こちらのビルドでアプリを再度申請して頂ければ問題を解消することが出来るはずです。ただし、現在も私たちは今後アプリが「プライベートAPIの利用」と判定されることがないよう、申請済みのアプリでこの修正をテストしています。</p>
<p>Update 6:11pm 11/12/11:<br />
下記の方法では問題は解消されないことが判明しました。現在、Appleの審査で「プライベートAPI」の利用と誤判定されるのを回避できるかどうか、別の方法を内部テスト中です。ご不便をおかけしておりますが、この問題の解決を最優先として取り組んでおります。</p>
<p>元の投稿：<br />
登録したアプリがプライベートなAPIを利用しているというAppleからのフィードバックについてコミュニティから何件か報告がありましたが、まだ「layout」であるとしか確認されていません。TitaniumのアプリケーションはプライベートなAPIを利用してはいないので、私たちはこれはAppleのアプリ解析ツールに何か変更があり、それが間違ってTitaniumのアプリのプロパティを検知しているのではないかと考えています。</p>
<p>Appleの解析ロジックにおけるこの不具合の回避方法ですが、私たちは実装ロジックから「layout」というキーワードの使用を避ける新しいビルドを用意しました。現在もこの修正が正しいものかどうかAppleのApp Storeで検証しているところです。この特別版ビルドのインストールして利用するには、下記の手順に従ってください。</p>
<p>今回のエラーはAppleの処理ロジックが原因でしたが、皆様がApp Storeへの登録作業を問題なく出来るようにするのが私たちの希望です。本件についてご質問、フィードバックなどございましたら、直接私(kwhinnery at appcelerator dot com)までご連絡頂ければ喜んでお手伝い致します。
</p></blockquote>
<p>というわけで、インストール方法は<a href="http://developer.appcelerator.com/blog/2011/11/layout-keyword-and-apple-app-analysis.html" target="_blank">こちらの手順</a>に従ってください。</p>
<img src="http://selfkleptomaniac.org/?ak_action=api_record_view&id=1850&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://selfkleptomaniac.org/archives/1850/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VMware FusionでBootcampは使うな</title>
		<link>http://selfkleptomaniac.org/archives/1836</link>
		<comments>http://selfkleptomaniac.org/archives/1836#comments</comments>
		<pubDate>Tue, 18 Oct 2011 07:17:26 +0000</pubDate>
		<dc:creator>y</dc:creator>
				<category><![CDATA[Apple]]></category>

		<guid isPermaLink="false">http://selfkleptomaniac.org/?p=1836</guid>
		<description><![CDATA[今までずっとVMWare FusionでBootcamp領域のWindowsを起動していたのだけれど、正直なところ遅すぎてあまり使い物にならなかった。そもそも、Windows用クライアントしか用意されていないYAMAHA [...]]]></description>
			<content:encoded><![CDATA[<p>今までずっとVMWare FusionでBootcamp領域のWindowsを起動していたのだけれど、正直なところ遅すぎてあまり使い物にならなかった。そもそも、Windows用クライアントしか用意されていないYAMAHAのルータ経由のVPNを利用するなど特殊な用途でVMwareを起動して使っていたのだけれど、ただでさえ面倒くさいその手の作業が本当にストレスになるほどVMware FusionのWindowsは遅かった。</p>
<p>で、HDDが激安な昨今、MacbookProをSSDにするか悩んだ末に、メインマシンなので容量重視と<a href="http://www.amazon.co.jp/o/ASIN/B0045Y0J4Y/lovemorgue-22/ref=nosim" target="_blank">1TBのHDD</a>にしたのをきっかけに、ふと複数のWindowsの試験環境を作成してみたのだが、イメージから起動するWindowsの速さに驚いた！ぜんぜんストレスなく使える！Bootcamp領域のWindowsの遅さでよく調教されてしまったせいかもしれないが、それでもいいじゃないか！</p>
<p>というわけで、Bootcampに入れたWindowsの遅さで白髪が増えたという方は、一度普通にイメージでVMを作成してみるといいと思いますよ。</p>
<img src="http://selfkleptomaniac.org/?ak_action=api_record_view&id=1836&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://selfkleptomaniac.org/archives/1836/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Phone Story</title>
		<link>http://selfkleptomaniac.org/archives/1794</link>
		<comments>http://selfkleptomaniac.org/archives/1794#comments</comments>
		<pubDate>Tue, 13 Sep 2011 11:10:47 +0000</pubDate>
		<dc:creator>y</dc:creator>
				<category><![CDATA[Apple]]></category>

		<guid isPermaLink="false">http://selfkleptomaniac.org/?p=1794</guid>
		<description><![CDATA[The Yes Menのアプリが登場した。 Phone Storyはスマートフォン製造の隠れた社会的コストを学ぶ教育ゲームです。カラフルなミニゲームを通じて、あなたの電話がコンゴのコルタン鉱山からパキスタンの電子部品廃棄 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://itunes.apple.com/us/app/phone-story/id462806536?ls=1&#038;mt=8" target="_blank">The Yes Menのアプリ</a>が登場した。</p>
<blockquote><p>
Phone Storyはスマートフォン製造の隠れた社会的コストを学ぶ教育ゲームです。カラフルなミニゲームを通じて、あなたの電話がコンゴのコルタン鉱山からパキスタンの電子部品廃棄現場へと巡る旅を追いかけてみましょう。終わりのない技術の陳腐化スパイラルを強いるマーケットの力と競争です。</p>
<p>あなたが自分でやっていることが世界にどんな影響を及ぼしているのか忘れないよう、お好きなデバイスにPhone Storyを入れておきましょう。このアプリの売り上げから得られる利益は全てゲームの中に登場する問題の解決に向けて活動している団体に寄付されます。
</p></blockquote>
<p>いつまで入手可能な状態なのか不明なので、あなたが世界を汚染するスマートフォンのオーナーであり、それがAppleの製品であるなら、このゲームをAppleがAppStoreから消してしまう前に<a href="http://itunes.apple.com/us/app/phone-story/id462806536?ls=1&#038;mt=8" target="_blank">ゲットしよう</a>！</p>
<img src="http://selfkleptomaniac.org/?ak_action=api_record_view&id=1794&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://selfkleptomaniac.org/archives/1794/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iOS向けアプリでやってほしくない仕様変更</title>
		<link>http://selfkleptomaniac.org/archives/1760</link>
		<comments>http://selfkleptomaniac.org/archives/1760#comments</comments>
		<pubDate>Tue, 23 Aug 2011 03:13:38 +0000</pubDate>
		<dc:creator>y</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[Titanium]]></category>

		<guid isPermaLink="false">http://selfkleptomaniac.org/?p=1760</guid>
		<description><![CDATA[そんなにたくさんアプリを作ってきたわけではないので、これは偏った意見かもしれませんが、iOS向けアプリを作っていて、こんな仕様変更は困るな、というのがいくつかありました。 たとえばアプリ内の特定の機能はIn-App pu [...]]]></description>
			<content:encoded><![CDATA[<p>そんなにたくさんアプリを作ってきたわけではないので、これは偏った意見かもしれませんが、iOS向けアプリを作っていて、こんな仕様変更は困るな、というのがいくつかありました。</p>
<p>たとえばアプリ内の特定の機能はIn-App purchaseを利用して購入が完了しないと使えない、という仕様はよくあると思います。この購入フローで、購入手続きが完了したら、前の画面の見栄えが変わっていたりするとかいうのは勘弁してほしいです。全く不可能というわけではもちろんないのですが、不要なレベルで複雑化しがちになってしまいます。</p>
<p>
<a href="http://selfkleptomaniac.org/wp-content/uploads/2011/08/ios_app12.png"><img src="http://selfkleptomaniac.org/wp-content/uploads/2011/08/ios_app12.png" alt="" title="ios_app1" width="394" height="491" class="aligncenter size-full wp-image-1767" /></a><br />
<a href="http://selfkleptomaniac.org/wp-content/uploads/2011/08/ios_app22.png"><img src="http://selfkleptomaniac.org/wp-content/uploads/2011/08/ios_app22.png" alt="" title="ios_app2" width="404" height="410" class="aligncenter size-full wp-image-1778" /></a>
</p>
<p>こんな感じ。ほら、購入して戻ると前の画面が勝手に変更されてるでしょ？</p>
<p>最初から計画されていたら構わないんですが、後からこういうのを追加するのが一番困ってしまいます。ウェブから転身した人だと、こんなのJavaScriptで親ウィンドウのノードを書き換えるだけみたいに考えたりしがちなのですが、どちらかというとiOSとかAndroidのアプリだと、画面遷移に「戻る」ボタンを多用すると考えた方がしっくりくるかもしれません。戻るボタンを押して戻った先の画面の内容を書き換えろ、というのはちょっと変だな、って思いませんか？</p>
<p>前にも書きましたが、こういうアプリって、画面をスタックに積んでは降ろすという性質があって、ひたすら前進することを基本にしているウェブとはちょっと違うんですよね。これでうまく伝わるといいんですが。</p>
<img src="http://selfkleptomaniac.org/?ak_action=api_record_view&id=1760&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://selfkleptomaniac.org/archives/1760/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Titaniumで作ったアプリの表示名を国際化対応(iOS)</title>
		<link>http://selfkleptomaniac.org/archives/1659</link>
		<comments>http://selfkleptomaniac.org/archives/1659#comments</comments>
		<pubDate>Wed, 13 Jul 2011 11:56:45 +0000</pubDate>
		<dc:creator>y</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Titanium]]></category>

		<guid isPermaLink="false">http://selfkleptomaniac.org/?p=1659</guid>
		<description><![CDATA[Titaniumで作成したアプリの表示名はデフォルトでtieapp.xmlのnameで指定されたものになる。iPhoneだと生成されるInfo.plistではCFBundleDisplayNameが${PRODUCT_N [...]]]></description>
			<content:encoded><![CDATA[<p>Titaniumで作成したアプリの表示名はデフォルトでtieapp.xmlのnameで指定されたものになる。iPhoneだと生成されるInfo.plistではCFBundleDisplayNameが${PRODUCT_NAME}になっている。ここにはデフォルトではプロジェクトディレクトリの名前がそのまま入るのだが、例えば日本語のアプリ名にしようとすると、プロジェクト名は日本語に出来ないので、iPhoneなら一度ビルドして作成されるbuild/iphone/Info.plistをプロジェクトのディレクトリ直下にコピーして、CFBundleDisplayNameを書き換える。AndroidだとAndroidManifest.xmlを同じくコピーして中身を書き換える。</p>
<p>でも、このやり方だと画面に表示するアプリの名称を国際化対応することができない。そこで調べてみたら、iOSだとこんなやり方でできた。</p>
<p>（１）例えば英語ならResources/English.lproj/InfoPlist.stringsを作成する<br />
（２）中身を下のようにする。</p>
<pre>
CFBundleDisplayName = "English Name!";
</pre>
<p>（３）このInfoPlist.stringsをUTF-16で保存する。<br />
（４）念のためbuild/iphone/以下のファイルを全部消してリビルドする</p>
<p>日本語の場合はJapanese.lprojになる。ところで中国語だが、zh_TW.lprojが繁体字、zh_CN.lprojが簡体字になる。Info.plistはそのままCFBundleDisplayNameは${PRODUCT_NAME}で大丈夫。</p>
<img src="http://selfkleptomaniac.org/?ak_action=api_record_view&id=1659&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://selfkleptomaniac.org/archives/1659/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TitaniumのHTTPClient</title>
		<link>http://selfkleptomaniac.org/archives/1649</link>
		<comments>http://selfkleptomaniac.org/archives/1649#comments</comments>
		<pubDate>Wed, 06 Jul 2011 12:03:22 +0000</pubDate>
		<dc:creator>y</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Titanium]]></category>

		<guid isPermaLink="false">http://selfkleptomaniac.org/?p=1649</guid>
		<description><![CDATA[TitaniumでTitanium.Network.createHTTPClientをネストさせて使おうとするとうまくいかない。 var url = 'http://example.com/a'; var http =  [...]]]></description>
			<content:encoded><![CDATA[<p>TitaniumでTitanium.Network.createHTTPClientをネストさせて使おうとするとうまくいかない。</p>
<pre>
var url = 'http://example.com/a';

var http = Ti.Network.createHTTPClient();
http.onload = function(){
  var url2 = this.responseText;
  var http2 = Ti.Network.createHTTPClient();
  http2.onload = function(){
    //素敵なサムシング
  };
  http2.open('GET, url2);
  http2.send();
};
http.open('GET', url);
http.send();
</pre>
<p>詳しく調べていないが、なんとなく試してみたら下のようにするとうまく動作する。</p>
<pre>
function http_client_two(url){
  var http = Ti.Network.createHTTPClient();
  http.onload = function(){
    //素敵なサムシング
  };
  http.open('GET', url);
  http.send();
}
function http_client_one(){
  var url = 'http://example.com/a';
  var http = Ti.Network.createHTTPClient();
  http.onload = function(){
    var url2 = this.responseText;
    http_client_two(url2);
  };
  http.open('GET', url);
  http.send();
}

http_client_one();
</pre>
<p>こんな感じでネストするHTTPクライアントを関数として外に出す。とりあえずのメモ。</p>
<img src="http://selfkleptomaniac.org/?ak_action=api_record_view&id=1649&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://selfkleptomaniac.org/archives/1649/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

