iOS開発:MyTweet+リリース

ようやく、私のiOSアプリ(MyTweet+)がリリースされました!
MyTweet+ (iTunes App Store)

な、長かった〜

どんなアプリ?

MyTweet+は、ツイートを管理するアプリ。お気に入りにしたツイートを、後から見返したい時などに便利。「あのトリビアなんだっけ・・?Twitterで見たけど思い出せない・・」って時に、サッとツイートを取り出すことができる。

今の機能はこんな感じ。

  • お気に入りツイート、自分のツイートを読み込み
  • ツイートをタグで管理
  • タグがついたツイートを表示
  • ツイートのローカル保存(画像キャッシュもあり)
  • 保存したツイートの検索
  • 過去のツイートのダウンロード

続きを読む

iOS開発:アプリケーション再申請


以前に申請していたアプリだが、見事にリジェクトされてしまった。予想通りだけど、少し凹む・・。

リジェクトの理由は、iOS Data Storage Guidelinesに従っていないためだった。
これの内容を見ていくと、「iCloudバックアップされるディレクトリには、ユーザが作成したデータを置く。再ダウンロード可能なデータなどは、別のディレクトリに置きなさい」とのこと。つまり、「何でも、iCloudバックアップさせないように!」という意味。

以下のサイトが参考になった。

対応する

対応は簡単だった。今まで「[Application_Home]/Documents」に全データを置いていたのだが、データの配置場所を変更することにした。

画像イメージは「[Application_Home]/Library/Caches」に、データベースファイルは「[Application_Home]/Library/Private Documents」に置くことにした。

Caches以下は、ディスク容量が足りなくなると消される可能性があるので、データベースファイルは置けない。そこで別ディレクトリを作成する。注意するのは、このディレクトはiCloudバックアップされてしまうのだ。そこで、no backup属性を付与して、iCloudバックアップさせないように設定する。

no backup属性を付与するためのコードは、Technical Q&A QA1719: Technical Q&A QA1719を参考にした。これを呼び出せば、バックアップされなくなる。

少し悩んだ箇所は、NSString型のファイルパスをNSURLに変換するやりかた。以下のようにすれば問題なく動いた。
[c]
// fileURLWithPathを使う
[DatabaseHelper addSkipBackupAttributeToItemAtURL:[NSURL fileURLWithPath:dbPath];
[/c]

iPhoneシミュレータで起動した後、属性がついていることを確認する。
[bash]
$ cd /Users/ei/Library/Application Support/iPhone Simulator/6.0/Applications/AA98DACC-4167-4A98-A6C5-EFC709CA80D2
$ xattr Library/Private\ Documents/app.db
com.apple.metadata:com_apple_backup_excludeItem
[/bash]
xattrコマンドでファイルの属性を見ると、バックアップ対象外となっている。

再申請


再度、バイナリをアップロードして、「Waiting For Review」ステータスになった。また、リジェクトになる気がするなぁ・・。

iOS開発:UIWebViewで表示しているコンテンツの高さを取得

UIWebViewで表示しているコンテンツの高さを取得する。Webでやり方を検索していると、2通りのやり方が見つかる。

1つ目は、「document.documentElement.clientHeight;」を使うやり方。
2つ目は、「document.getElementById(\”contentsDiv\”).clientHeight;」を使用するやり方。

どっちが良いのか分からずに、1つ目のやり方を使っていた。しかし、いろいろと検証した結果、2つ目のやり方の方が良いように思った。

検証結果

1つ目のやり方の問題点は、コンポネント(UIWebView)の高さを取得してしまう事がある点だ。

上の画像のように、UIWebViewの表示領域を大きくした場合で、表示内容が少ない場合、スクロースなく表示することが出来る。そうなると、「document.documentElement.clientHeight;」は、コンポネントの高さの取得となる。スクロールが発生するような場合は、コンテンツの高さが取得できる。常にコンテンツの高さが取得できるわけではないのだ。

2つ目のやり方だと、コンテンツの内容によらず、コンテンツの高さが取得できる。

サンプルコード

まずは、HTMLを表示させる。コンテンツのdivのidは、”contentsDiv”とした。
[c]
NSString *html1 = @"<html><head><style type=\"text/css\">body{font-family:Noteworthy-Bold,\"Apple Color Emoji\";}</style></head>"
"<body><div id=\"contentsDiv\" style=\"background-color:#dddddd\">☀٩(・×・。)۶☀<br><a href=\"http://www.google.com/\">Google</a><br>あああ<br>あああ<br>あああ</div></body>"
"</html>";
[/c]

以下のDelegateメソッドで、コンテンツの高さを取得する。そして、コンテンツの高さに合わせて、UIWebViewの高さを変更する。
[c]
-(void)webViewDidFinishLoad:(UIWebView *)webView {
NSString *output = [webView stringByEvaluatingJavaScriptFromString: @"document.getElementById(\"contentsDiv\").clientHeight;"];
int contentHeight = [output intValue] + 20;

CGRect frame = self.webView.frame;
frame.size = CGSizeMake(webView.frame.size.width, contentHeight);
self.webView.frame = frame;

NSLog(@"contentHeight is %d", contentHeight);
}
[/c]

実行すると、こんな感じになる。