24/7 twenty-four seven

iOS/OS X application programing topics.

miil 1.0.1 がリリースされました。


miil

miil miil

miil.me


miil 1.0.1 がリリースされました。

バージョン 1.0.1 の変更点

  • 利用規約を変更しました。

機能改善

  • ユーザー一覧画面のフォローボタンのタップ領域を拡大し、押しやすくしました。
  • Twitterから友だちを検索する際のUIを改善しました。
  • 現在地以外の位置情報を投稿できるようになりました。
  • お店を新しく登録する際の手順を改善しました。

不具合の修正

  • HOTタイムラインの並び順が更新されない問題を修正しました。
  • フォローボタンが正しく動かない問題を修正しました。
  • ユーザー登録できないことがある問題を修正しました。
  • お店の情報が正しく追加されないことがある問題を修正しました。
  • iPod touchで電話をかける画面が表示されてしまう問題を修正しました。
  • 「お知らせ」を表示する際にクラッシュすることがある問題を修正しました。
  • 「続きを読みこむ…」を押した際にクラッシュすることがある問題を修正しました。
  • 新着の「お知らせ」バッジが表示されないことがある問題を修正しました。

関連リンク


東日本大震災緊急支援募金募集中。国際NGOワールド・ビジョン・ジャパン

miil 1.0.0 がリリースされました。


miil

miil miil

miil.me


私がプログラムを担当しました、miil 1.0.0 がリリースされました。


食べものの写真を通して「おいしい!」を共有するアプリケーションです。


写真を撮って投稿したり、ほかの人の写真をみたり、


ほかの人の写真をみたり、感想を書き込んだり、


食べたい写真があったら、お店を調べたりできます。


眺めているだけでも楽しい気分になるアプリケーションですので、ぜひダウンロードしてみてください。

関連リンク


東日本大震災緊急支援募金募集中。国際NGOワールド・ビジョン・ジャパン

i-Radio 1.2.0 がリリースされました。


i-Radio


i-Radio i-Radio


ネットラジオのアプリケーション i-Radio のバージョン 1.2.0 が審査を通過しました。
自動更新購読 (Auto-Renewable subscriptions) による月額プレミアム会員がスタートしました。
プレミアム会員になると、季節ごとのバックナンバーが聴取できるようになるほか、すべての画面で広告が非表示になります。

主な変更点

  • 自動更新購読 (Auto-Renewable subscriptions) によるプレミアム機能の追加

ColorChooser が便利


カラーピッカーで選択した色を自動的に UIColor や NSColor のコードに変換してくれるユーティリティです。
同様のものに Developer Color Picker がありますが、 それのメニュー常駐版のような感じです。
コードを書いているときにどこからでも呼び出せるので私はこちらのほうが便利だなと思います。

ColorChooser - Pairote Leelaphattarakij

UINavigationBar に複数の UIBarButtonItem を配置するには

UINavigationBar は基本的に左右 (leftBarButtnItem, rightarButtonItem) に一つずつしかボタンを配置することができません。
しかし、ちょっと工夫をするとその制限を突破することができます。
(まあ物理的なスペースの関係でせいぜい2つか3つがやっとなのですけどね)

方法その1. UIToolbar を UIBarButtonItem として配置し、その中に UIBarButtonItem を並べる


もっとも見た目がキレイに仕上がる方法です。

UINavigationBar の leftBarButtnItem と rightarButtonItem は UIBarButtonItem のインスタンスをそれぞれ1つずつしか代入できませんが、UIToolbar を UIBarButtonItem として作成することで、その UIToolbar に複数のボタンを配置することができるようになります。

UIBarButtonItem *sendButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Send", nil) style:UIBarButtonItemStyleBordered target:self action:@selector(send:)];

UIBarButtonItem *cameraButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:@selector(cancel:)];
cameraButton.style = UIBarButtonItemStyleBordered;

UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

UIToolbar *toolbar = [[MyToolbar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 110.0f, 44.0f)];
toolbar.backgroundColor = [UIColor clearColor];
toolbar.autoresizingMask = UIViewAutoresizingFlexibleHeight;
UIBarButtonItem *toolbarBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:toolbar];
[toolbar release];

toolbar.items = [NSArray arrayWithObjects:space, cameraButton, sendButton, nil];
[space release];
[cameraButton release];
[sendButton release];

self.navigationItem.rightBarButtonItem = toolbarBarButtonItem;
[toolbarBarButtonItem release];


ただ、標準の UIToolbar の外観は UINavigationBar の外観と微妙な差異があるので、このままでは境界が目立ってしまいます。


そこで UIToolbar のサブクラスを作成し、空の drawRect: メソッドでオーバーライドし、標準の描画を無効にします。

@interface MyToolbar : UIToolbar
@end

@implementation MyToolbar

- (void)drawRect:(CGRect)rect {
    
}

@end


すると、このような状態になります。


真っ黒になってしまったので、背景色を透明に設定します。
drawRect: メソッドの処理は backgroundColor と無関係というのがミソですね。

toolbar.backgroundColor = [UIColor clearColor];


キレイになりました。


もし、横方向の画面をサポートする場合、ナビゲーションバーは横方向では 30 ピクセルの幅に変わりますので、ツールバーの autoresizingMask プロパティに UIViewAutoresizingFlexibleHeight を設定しておきましょう。

toolbar.autoresizingMask = UIViewAutoresizingFlexibleHeight;



UIViewAutoresizingFlexibleHeight を指定しない場合は下のようになります。すこしボタンの大きさがアンバランスですね。


色をつけると違いが分かりやすくなります。


tintColor を設定すれば色も変えられます。

方法その2. UISegmentedControl をボタンのように使用する

標準のメールアプリでも採用されている方法です。
メールアプリの「前へ」「次へ」のように同じような動作をするボタンを並べる場合は良い方法だと思います。


titleView プロパティに乗せると3つのボタンを並べても余裕があります。


UISegmentedControl をボタンとして使用するには、momentary プロパティを YES に、アクションは UIControlEventValueChanged を設定します。

segmentedControl = [[UISegmentedControl alloc] initWithItems:items];
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControl.momentary = YES;
segmentedControl.frame = CGRectMake(segmentedControl.frame.origin.x, segmentedControl.frame.origin.y, segmentedControl.frame.size.width + 16.0f * [items count], segmentedControl.frame.size.height);
[segmentedControl addTarget:self action:@selector(segmentedControlAction:) forControlEvents:UIControlEventValueChanged];
[self.navigationItem setTitleView:segmentedControl];
[segmentedControl release];

方法その3. UIToolbar を上部のナビゲーションバーの位置に配置する

簡単ですがオススメしません。
というのも UIToolbar は画面の下部に配置するようにデザインされているため、上部に配置するとどうしても外観に違和感がでてしまうからです。
(iOS 4.x までの iPhone の場合。iPad のツールバーは上下どちらに配置してもいいようにデザインされている。)


ナビゲーションバーの位置に配置したツールバー。
ステータスバーとの境界が不自然ですね。

NSNull のインスタンスは nil として振舞ってくれると嬉しいなって


とか思ってたのですが、そう考える人はやっぱりほかにもいるようです。



たとえば私がいちばん面倒だなと思うのはjson-frameworkがnullをNSNullにマッピングするので(nilはNSArrayやNSDictionaryに格納できないため)でWeb APIからのレスポンスをParseする際に、値がセットされるときとnullがセットされるときと両方あるような場合、ハンドリングがとたんに面倒になるのですね。

 NSString *results = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
 NSDictionary *dic = [results JSONValue];
 NSString *shortURL = [[[dic objectForKey:@"results"] objectForKey:longURL] objectForKey:@"shortUrl"];

上記の場合、longURL の値が NSNull だったとすると objectForKey: の呼び出しが失敗してクラッシュします。
このとき NSNull が nil だとしたら、nil へのメッセージは単に無視されるので問題ないわけなのでそうなっていたら便利なのにという話です。


というわけで、下記のようなカテゴリをどこかに書いておくと、NSNull へのメッセージはすべて無視されるので、まるで nil のように扱えて便利です。
何をしているかというと、メッセージフォワーディングの仕組みが動作するように methodSignatureForSelector: および forwardInvocation: をオーバーライドします。
そうすると存在しないメソッドを呼びだそうとするとこれらのメソッドが呼ばれるので、forwardInvocation: メソッドで NSNull に存在しないメソッドの呼び出しは無視するように処理を変更しています。

[参考]Does Objective-C use short-circuit evaluation? - Stack Overflow

@implementation NSNull(IgnoreMessages)

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    if ([self respondsToSelector:[anInvocation selector]]) {
        [anInvocation invokeWithTarget:self];
    }
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    NSMethodSignature *sig=[[NSNull class] instanceMethodSignatureForSelector:aSelector];
    // Just return some meaningless signature
    if (sig == nil) {
        sig = [NSMethodSignature signatureWithObjCTypes:"@^v^c"];
    }
    
    return sig;
}

@end


東日本大震災緊急支援募金募集中。国際NGOワールド・ビジョン・ジャパン

MKMapView に CATransform3D を適用するときの注意



@さんがつぶやいてたので気になって調べてみました。

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = 1.0f / -500.0f;
    transform = CATransform3DRotate(transform, 60.0f * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);
    
    mapView.layer.transform = transform;
}

こんなふうに書いてみたところ、どうもズーム機能が正常に動作しなくなるようです。
(ズームはするけど拡大率に合わせて再描画してくれない)


で、いろいろ試した結果、どうやら mapView の親ビューのレイヤーに transform を適用した上で、mapView のレイヤーにはその逆行列を適用することで打ち消してあげると正しく動作するようです。
(単純に親ビューのレイヤーに適用するだけではダメ。親ビューのレイヤーに適用した transform は自動的にサブビューのレイヤーにも適用されるので。)
下記がコード例です。

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = 1.0f / -500.0f;
    transform = CATransform3DRotate(transform, 60.0f * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);
    
    contentView.layer.transform = transform;
    
    // mapView に逆行列を適用する
    CATransform3D t = CATransform3DInvert(transform);
    mapView.layer.transform = t;
}


実行した結果は下のようになります。ちゃんとズームできてますね。


ちなみに、ズームできなくなるのは行列の m34 要素を変更したときのみで、単に回転やスケールするだけなら問題ないぽいです。


東日本大震災緊急支援募金募集中。国際NGOワールド・ビジョン・ジャパン

kotobank for iPhone 1.0.0 がリリースされました。


kotobank - コトバンク

kotobank - コトバンク kotobank - コトバンク

株式会社ジェネシックス | genesix


私がプログラムを担当しました、kotobank for iPhone 1.0.0 がリリースされました。


データを内部に持ち、オフラインで使用できる辞書アプリケーションです。
このアプリケーションの特長は、複数の辞書を一度に横断検索できる点です。

初期状態では付属しているポケットプログレッシブ国語辞典だけの検索になりますが、追加の辞書を購入することでひとつの言葉をいろいろな辞書で一度に調べられます。

以下が初期状態の検索結果です。


現在、購入可能な辞書をすべてインストールした場合、同じ語でも次のような結果になります。


「企業がわかる事典」など、普段あまり使わない辞書に意外な結果が出ておもしろかったりします。


検索結果を選択すると、詳しい意味を見ることができます。
この画面からは、調べた単語を単語帳に登録したり、メールで送信することができます。


また、この画面からさらに気になる言葉を選択して、検索しなおすことが可能です。
この機能でどんどん言葉を検索していくと、ついつい時間をわすれてしまいそうになります。


単語帳に登録した言葉は、単語帳タブの画面から見ることができます。


アプリケーションのストアから辞書を購入して追加することができます。
現在は「プログレッシブ和英中辞典 第3版」「プログレッシブ英和中辞典 第4版」「企業がわかる事典」の3つが購入できます。
和英と英和辞書はそれぞれ 1,600 円ですが、「英和中辞典セット」という商品を購入すると、2,000 円で両方の辞書を一度に購入できるのでおトクです。


そのほか、普段あまり使用しない辞書は検索対象外にしたり、ひとつの辞書だけで検索したりといった設定ができます。


ということで、辞書を追加していくことでどんどん調べる楽しさが増えていくアプリケーションです。
ぜひダウンロードして使ってみてくださいませ。

LCD Clock HD 1.1.2 がリリースされました。


LCD Clock HD

LCD Clock HD LCD Clock HD

バージョン 1.1.2 がアップルの審査を通過しました。
iOS 4.3の動作と、日本以外の国において2011年後半の移動休日のデータを更新しました。

変更点

  • iOS 4.3の動作を確認しました。
  • 日本以外の国において2011年後半の移動休日のデータを更新しました。


東日本大震災緊急支援募金募集中。国際NGOワールド・ビジョン・ジャパン

iPhone アプリにおいて Interface Builder を使って Grouped Style の UITableView を作るときは separatorStyle の値に注意

Grouped スタイルのテーブルビューを使用した iPhone アプリケーションの中に、下の画像のように先頭セクションの区切り線が2重に表示されているものをチラホラ見かけます。
実用上の問題は無いのですが、ちょっと不恰好なので気になりますよね。



この現象は、UITableView の separatorStyle に UITableViewCellSeparatorStyleSingleLineEtched が指定されていることが原因で発生します。

コードでインスタンスを生成した場合の separatorStyle デフォルト値は UITableViewCellSeparatorStyleSingleLine なのですが、Interface Builder で UITableView を Grouped スタイルで作成した場合はデフォルト値として UITableViewCellSeparatorStyleSingleLineEtched が自動的に選択されるようになりました。
(もともとはそんなことはなかったのですが、UITableViewCellSeparatorStyleSingleLineEtched が iOS SDK 3.2 から導入され、おそらくそのあたりのタイミングで動作が変更されたようです。)


ということですので、iPhone の場合に Grouped スタイルのテーブルビューを Interface Builder を使って作成するときは、separatorStyle の値を UITableViewCellSeparatorStyleSingleLine など、UITableViewCellSeparatorStyleSingleLineEtched 以外に設定しましょう。

コードでインスタンスを生成した場合のデフォルト値は UITableViewCellSeparatorStyleSingleLine ですので問題はありません。



公式のドキュメントによる言及が見つからないのですが、UITableViewCellSeparatorStyleSingleLineEtchedは(おそらく)iPad 専用の値です。
次のように iPad で Grouped Style のテーブルに対して指定した場合はキレイにハマります。



というわけで、コードで作る場合にはデフォルト値はドキュメントに書いてあるとおりなのですが、Interface Builder を使って作る場合にはデフォルト値は (IB が空気を読んで?) ドキュメントと異なる場合が多いので注意したほうがいいですね。

Interface Builder で作った場合とコードで書いた場合のデフォルト値の違いは、ほかにも各種ビューの backgroundColor や autoresizingMask などがありますので、余計な色が付いていないかどうかなど、きちんと確認したほうがいいでしょう。


東日本大震災緊急支援募金募集中。国際NGOワールド・ビジョン・ジャパン

英辞郎検索ランキング(アルク) 1.0.0 がリリースされました。

英辞郎検索ランキング(アルク)

英辞郎検索ランキング(アルク)

英辞郎検索ランキング(アルク)


私が開発を担当しました、「英辞郎検索ランキング(アルク)」 が Apple の審査を通過しました。


このアプリケーションはアルクの「英辞郎 検索ランキング 英和編」「英辞郎 検索ランキング 和英編」という2冊の書籍を ひとつのiPhoneアプリケーションとしてまとめたものです。

「英辞郎 on the WEB」で検索される単語をランキング化し、収録してありますので日常的によく使う単語や例文を学習することができます。

すべての単語と例文に音声が付属していますので、発音の勉強にもいいと思います。



UIDocumentInteractionController で特定のファイルを開くことのできるアプリケーションを調べたり、直接開いたりする。

南東京iPhone開発者勉強会 #5 - Togetterまとめ
UIDocumentInteractionController
UIDocumentInteractionController で、特定の拡張子のファイルを開けるアプリがあるかどうかを調べる方法 - iOS プログラミングメモ - iPhoneアプリ開発グループ


昨日、南東京iPhone開発者勉強会 5回目で UIDocumentInteractionController について話してきました。
UIDocumentInteractionController は下記のようにあるファイルをサポートしている(開くことのできる)アプリケーションがデバイスにインストールされているとき、そのファイルを別のアプリケーションで開くというアプリケーション連携を実現するためのクラスです。
Safari で PDF ファイルを開いたときに別のアプリケーションで開くメニューが表示されたりするので見たことがあるかもしれません。


そのとき、その機能で特定のファイルについて開けるアプリがあるかどうかだけ調べたりとかできないかという話がでたので調べてみました。


まあ、そのときの結論としては UIDocumentInteractionController はプレビューするか、そのファイルを開けるアプリがある場合に選択メニューを出すかで基本的にお任せで使うものなので正攻法では無理ということなのですが、選択メニューが出せてる以上、内部的にはそういう仕組みはきっと普通にあるだろうということで調べてみました。


とりあえず、class-dump してみます。

UIDocumentInteractionController-Private.h
UIDocumentInteractionController-QLPreviewController.h
UIDocumentInteractionController-QLPreviewControllerDataSource.h
UIDocumentInteractionController-UIActionSheetDelegate.h
UIDocumentInteractionController-UIPopoverControllerDelegate.h
UIDocumentInteractionController.h


UIDocumentInteractionController-Private.h といういかにも怪しそうなファイルがあるので見てみましょう。

#import <UIKit/UIDocumentInteractionController.h>

@class UIPopoverController, _UIPreviewItemProxy;

@interface UIDocumentInteractionController (Private)
@property(readonly, nonatomic) id previewController;
@property(readonly, nonatomic) UIPopoverController *popoverController;
@property(readonly, nonatomic) _UIPreviewItemProxy *previewItemProxy;
- (void)_presentPreview:(id)arg1;
- (void)_presentOpenIn:(id)arg1;
- (void)_presentOptionsMenu:(id)arg1;
- (id)_applications:(BOOL)arg1;
- (void)_openDocumentWithApplication:(id)arg1;
- (void)_openDocumentWithCurrentApplication;
- (void)openResourceOperation:(id)arg1 didFinishCopyingResource:(id)arg2;
- (void)_finishedCopyingResource;
- (BOOL)_setupForOptionsMenu;
- (BOOL)_setupForOpenInMenu;
- (BOOL)_delegateExistsAndImplementsRequiredMethods:(id *)arg1;
- (BOOL)_setupPreviewController;
- (void)_invalidate;
- (void)_interfaceOrientationWillChange:(id)arg1;
- (id)_applicationToOpen;
- (void)_setApplicationToOpen:(id)arg1;
- (void)_setUnzippedDocumentURL:(id)arg1;
- (id)_unzippedDocumentURL;
- (BOOL)_canUnzipDocument;
- (BOOL)_isFilenameValidForUnzipping:(id)arg1;
- (BOOL)_isValidURL:(id)arg1;
- (void)_unzipDocument;
- (void)_unzipDocumentToDirectory:(id)arg1;
- (void)_zipOperationCompleted;
- (void)_cleanUpUnzippedDocument;
@end


それっぽいものが見つかりましたね。

- (id)_applications:(BOOL)arg1;
- (void)_openDocumentWithApplication:(id)arg1;


引数の意味が分かりませんがきっとこのメソッドはそのファイルを開けるアプリケーションの Array が返ってくるのでしょう。
とりあえず、呼んでみました。

NSLog(@"%@", docInteractionController.UTI);
NSLog(@"%@", [docInteractionController _applications:YES]);


私の環境では結果はこのようになりました。ちなみに引数を NO に変えてみても結果は変わらなかったので引数の意味は分かりませんです。

2011-01-31 23:20:31.788 DocInteraction[1959:307] public.plain-text
2011-01-31 23:20:31.929 DocInteraction[1959:307] (
    "LSApplicationProxy: com.hogbaysoftware.PlainText",
    "LSApplicationProxy: com.evernote.iPhone.Evernote"
)
2011-01-31 23:20:32.138 DocInteraction[1959:307] public.jpeg
2011-01-31 23:20:32.223 DocInteraction[1959:307] (
    "LSApplicationProxy: com.evernote.iPhone.Evernote"
)
2011-01-31 23:20:32.259 DocInteraction[1959:307] com.adobe.pdf
2011-01-31 23:20:32.289 DocInteraction[1959:307] (
    "LSApplicationProxy: com.lexcycle.stanza",
    "LSApplicationProxy: com.yourcompany.OpenIn",
    "LSApplicationProxy: com.evernote.iPhone.Evernote",
    "LSApplicationProxy: jp.tatsumi-sys.sidebooks",
    "LSApplicationProxy: com.apple.iBooks"
)
2011-01-31 23:20:32.315 DocInteraction[1959:307] public.html
2011-01-31 23:20:32.334 DocInteraction[1959:307] (
    "LSApplicationProxy: com.evernote.iPhone.Evernote"
)


思ったとおりそのファイルをサポートしているアプリケーションのリストが返ってきています。

LSApplicationProxy は MobileCoreServices.framework に含まれるクラスですね。

#import <MobileCoreServices/LSResourceProxy.h>

@class NSArray, NSString;

@interface LSApplicationProxy : LSResourceProxy
{
    NSArray *_privateDocumentIconNames;
    LSApplicationProxy *_privateDocumentTypeOwner;
}

+ (id)applicationProxyForIdentifier:(id)arg1;
+ (id)applicationProxyForIdentifier:(id)arg1 roleIdentifier:(id)arg2;
- (id)_initWithApplicationIdentifier:(id)arg1 roleIdentifier:(id)arg2 name:(id)arg3 resourcesDirectoryURL:(id)arg4 iconFileNames:(id)arg5 iconIsPrerendered:(BOOL)arg6;
- (void)dealloc;
@property(readonly, nonatomic) NSString *applicationIdentifier;
@property(readonly, nonatomic) NSString *roleIdentifier;
- (id)resourcesDirectoryURL;
- (id)privateDocumentIconNames;
- (void)setPrivateDocumentIconNames:(id)arg1;
- (id)privateDocumentTypeOwner;
- (void)setPrivateDocumentTypeOwner:(id)arg1;
- (id)localizedName;
- (BOOL)isEqual:(id)arg1;
- (unsigned int)hash;
- (id)description;

@end


戻り値の Array から適当なオブジェクトを引数として、先のもうひとつのメソッドに呼んであげると見事そのアプリケーションをドキュメントに関連付けて起動することができました。

NSArray *applications = [docInteractionController _applications:YES];
for (id app in applications) {
    if ([[app localizedName] isEqualToString:@"Stanza"]) {
        [docInteractionController _openDocumentWithApplication:app];
        break;
    }
}


と、まあこんな感じなのですが、なにぶん Undocumented API なのでそのまま使うのは難しいですね。

ただ使えるといろいろと便利な API だと思いますので、開放してほしいと思う方はバグレポートから要望を送ってみるといいと思いますよ。

Bug Reporting - Apple Developer

はてな touch 1.2.6 をリリースしました。



Hatena touch

はてな touch/Hatena touch はてな touch / Hatena touch

はてな touch 1.2.6 がアップルの審査を通過しました。
はてなの AtomPub API の WSSE 認証が厳格化したことにより投稿できない問題を修正しました。


AtomAPIの脆弱性対策として、WSSE認証をより厳密にしました - はてなブックマーク日記 - 機能変更、お知らせなど
AtomAPIの脆弱性対策として、WSSE認証をより厳密にしました - はてなフォトライフ日記 - 機能変更、お知らせなど

変更点

  • WSSE 認証の厳格化による問題を修正。

iTunes Connect Developer Guide の Appendix が便利

iTunes Connect Developer Guide は本文はもちろん必読なのですが、最近追加された Appendix に載っている情報がけっこう便利です。

Appendix A: App Information Table

アプリケーションの申請に入力する情報について項目ごとに「1度申請すると編集不可」「アップデート時のみ編集可能」「いつでも編集可能」および「アプリケーション全体に有効」「バージョンごとに有効」という関係をマトリックス図に整理したものです。


Appendix B: Game Center Info Table

同様に、Game Center の情報についてまとめたものです。


Appendix C: Device Compatibility Matrix

デバイスごとの機能の有無をマトリックス図に整理したものです。
Info.plist の UIRequiredDeviceCapabilities を使って、カメラや GPS などの機能の有無によってアプリケーションのインストールを制限したいときに参照すると便利です。
この表によると中国仕様の iPhone 3GS は iOS デバイスで唯一 Wifi の使えないデバイスということです。