「中学生でもわかる iOSアプリ開発講座」の訂正情報と更新情報です。出版社の訂正情報のページでも案内していますが、こちらもでも必要に応じて情報を追加しています。
書籍が書かれた当時と、XcodeやiOSのバージョンが変わっているため、最新環境に対応するためには、注意するべきことや変更が必要なことなどがあります。また、Xcodeのバージョン違いにより、ボタンの配置や種類が変わっていますが、役割は変わっていません。
図はクリックすると拡大されます。
この記事の訂正履歴
2016年1月31日 Xcode 7 + iOS 9への対応方法を公開しました。
書籍が書かれた当時の動作環境
- Xcode 5
- iOS 7
第2講座 道具を揃えよう
LESSON 06 iOSアプリで使うプログラミング言語は何?
Xcode 6とiOS 8からiOSアプリの開発言語が増えました。従来はObjective-Cが主役でしたが、Swiftが追加されています。本書はObjective-Cで解説しているので、プロジェクトを作るときや、ソースファイルを作るときに「Objective-C」を指定する必要があります。
第4講座 画面を作ってみよう
LESSON 09 プロジェクトを作成しよう
Xcode 5では、プラットフォームはiOSとOS Xだけでしたが、Xcode 7ではiOS, OS X, tvOS, watchOSの4種類があります。iOSのApplicationのSingle View Applicationを選択してください。
Objective-Cを使ってコードを書くので、46ページ、「プロジェクトファイルを作成するには」の「3 オプションの設定」で、「Language」を「Objective-C」を設定してください。「Use Core Data」「Include Unit Tests」「Include UI Tests」は使わないのでオフにします。
LESSON 10 シミュレータでアプリを実行しよう
Xcode 7に付属しているシミュレータは英語版のみです。シミュレータを終了するには、「Simulator」メニューから「Quit Simulator」を選択します。
また、iOSデバイスの解像度が上がっているため、ディスプレイに表示しきれないことがあります。このようなときは、表示倍率を小さくします。表示倍率を小さくするには、「Window」メニューの「Scale」から表示倍率を選択します。「コマンド」キーを押しながら「1」から「5」までのキーを押しても変わります。
LESSON 11 タイトル画面とプレイ画面を作成しよう
Xcode 6, iOS 8でサイズクラスが登場したために、Storyboardの編集画面が正方形に変わっていますが、書籍で解説している操作方法で同様に編集できます。
サイズクラスは、色々なアスペクト比の画面に対応するための仕組みです。
ラベルの自動レイアウトの設定
60ページ、「10 ラベルの自動レイアウトの設定」で表示されるボタンの種類が変わっています。整列位置のコンストレイントを表示するボタンは次の図のようになります。
明示的に設定していないコンストレイントの設定
62ページ、「13 明示的に設定していないコンストレイントの設定」で選択するコマンドは、Xcode 7では「All Views in View Controller」の下側に表示される「Add Missing Constraints」を選択します。コマンドを表示するためのボタンは、右端のボタンを使用します。
セグエの選択
66ページ、「3 セグエの選択」は、Xcode 7では「modal」は「Deprecated」になってしまったので、「Show」を選択してください。
セグエについて
モーダル表示とプッシュ表示は、Xcode 7とiOS 9でも存在する表示方法です。セグエの選択で「Show」を選択すると、ナビゲーションコントローラ(階層表示を行うための管理クラス)内ではプッシュ表示になり、本書のようにナビゲーションコントローラに属していないものでは、モーダルになります。
ナビゲーションコントローラ内でもモーダルにしたい場合には、「Present Modally」を選択します。
プレイ画面のコンストレイントの設定
本書ではプレイ画面で表示している、「Score」と「Time」のコンストレイントを設定していないため、正方形の編集画面の座標がそのまま使われてしまい、画面の外に出てしまいます。次のように操作して、コンストレイントを設定してください。
(1) 「Score」のテキストフィールドを選択する。
(2) 整列位置のコンストレイントを設定するボタンをクリックして、上と下の位置、Width, Heightを指定して、「Add Contraints」ボタンをクリックする。
(3) 「Time」のテキストフィールドを選択する。
(4) 整列位置のコンストレイントを設定するボタンをクリックして、上と右の位置、Width, Heightを指定して、「Add Constraints」ボタンをクリックする。
第5講座 クラスを作成しよう
LESSON 12 ビュークラスを作ろう
テンプレートの選択
76ページ、「3 テンプレートの選択」で、ダイアログに表示されるテンプレートの種類が変わっています。書籍では「Objective-C class」になっていますがXcode 7では無くなっています。「Cocoa Touch Class」を選択してください。
他の場所でもクラスを追加するという操作がありますが、同じように操作してください。
クラス名とスーパークラスの設定
77ページ、「4 クラス名とスーパークラスの設定」で、作成するソースファイルの言語も選ばなければいけなくなりました。「Language」から「Objective-C」を選択してから「Next」ボタンをクリックしてください。他のクラスを追加するときも、本書ではObjective-Cを使っているので、「Objective-C」を選択してください。
第6講座 的を表示しよう
LESSON 16 ビューの中に的を表示しよう
的の画像を組み込む
105ページ、「3 追加するファイルの選択」でオンにするチェックボックスは、Xcode 7では初期状態では表示されません。「Options」ボタンをクリックすると表示されます。
第7講座 ターゲットをタップできるようにしよう
LESSON 22 的を消したときにスコアを増やそう
スコアの表示を更新する方法について
161ページ、フォーマット指定子で、「NSInteger」型の整数に使用するフォーマット指定子ですが、「%d」をそのまま使うと次のような警告が表示されます。
Values of type ‘NSInteger’ should not be used as format arguments; add an explicit cast to ‘long’ instead
同様に、「NSUInteger」型の整数で「%u」を使用すると、次のような警告が表示されます。
Values of type ‘NSUInteger’ should not be used as format arguments; add an explicit cast to ‘unsigned long’ instead
Xcode 7のデフォルト設定では、ARMv7とarm64アーキテクチャを使ったCPU向けにビルドされるようになっています。ARMv7は32ビットCPUで、arm64は64ビットCPUです。「NSInteger」は32ビットでは「int」と同じ32ビット整数となり、64ビットでは「long long」と同じ64ビット整数になります。「NSUInteger」も同様で32ビットでは「unsigned int」、64ビットでは「unsigned long long」と同じになります。
このようにサイズが変わる型であるために警告が表示されています。警告されないようにするには、方法が2つあります。
一つは、警告メッセージの通り、「long」や「unsigned long」にキャストします。この場合はフォーマット指定子は「%ld」や「%lu」を使用します。「long」型及び「unsigned long」型は32ビットでは32ビット整数、64ビットでは64ビット整数になる型です。
もう一つの方法は、常に64ビット整数を使うという方法です。「long long」や「unsigned long long」にキャストします。この場合は、フォーマット指定子は「%lld」や「%llu」を使用します。「long long」型、及び、「unsigned long long」型は32ビットでも64ビットでも、常に64ビット整数になる型です。
スコアの更新に合わせてラベルを更新する
162ページと163ページ、「ViewController.m」に追加するコードの文字列を作る処理で、フォーマット指定子に「%ld」を使用するようにし、「long」のキャストも追加します。
str = [NSString stringWithFormat:@"Score %ld", (long)self.score];
アウトレットにコネクションを張る
手順2で、最初にクリックする場所(ビューコントローラ)ですが、Storyboardファイルの編集画面のレイアウト変更により、場所が変わっています。
第8講座 制限時間を作ろう
LESSON 24 ステージの制限時間を作ろう
残り時間をカウントする
175ページ、表示する文字列を作る行を次のように変更します。
NSString *str = [NSString stringWithFormat:@"%ld:%02ld", (long)m, (long)s];
制限時間が来たときの処理を作る
181ページで解説している「UIAlertView」クラスですが、iOS 8で非推奨になってしまいました。iOS 8以降では「UIAlertController」クラスを使用します。出版社の訂正情報のページに、iOS 7とiOS 8以降とで使用するクラスを切り替えるコードを掲載しています。そのコードを使用してください。または、iOS 7未満は動作対象外として、iOS 8以降のコードのみを使うようにしてください。
ここでは、iOS 7未満は対象外とするコードを掲載します。iOS 7にも対応するコードについては、出版社の訂正情報ページをご覧ください。
「ViewController.h」のコード
書籍に掲載している追加部分は必要ありません。
「ViewController.m」のコード
「alertView:clickedButtonAtIndex:」メソッドは必要ありません。次の「countDown:」メソッドを追加してください。
// タイマーで実行する処理 - (void)countDown:(NSTimer *)timer { // 現在の日時を求める NSDate *now = [NSDate date]; // 残り時間を計算する NSTimeInterval t = [self.gameEndDate timeIntervalSinceDate:now]; // 残り時間が0未満 (つまり過ぎている) ときは0とする if (t < 0.0) { t = 0.0; } // 分を求める NSInteger m = t / 60; // 秒を求める NSInteger s = (NSInteger)t % 60; // 文字列にする NSString *str = [NSString stringWithFormat:@"%ld:%02ld", (long)m, (long)s]; // ラベルにセット self.timeLabel.text = str; // 制限時間がきたら、タイマーを止めて、アラートを表示する if (t == 0.0) { // タイマーを停止する [self.countDownTimer invalidate]; // メッセージを作る NSString *msg; msg = [NSString stringWithFormat:@"Score is %ld", (long)self.score]; UIAlertController *alert; alert = [UIAlertController alertControllerWithTitle:@"Time is Up" message:msg preferredStyle:UIAlertControllerStyleAlert]; // OKボタンを作る UIAlertAction *okAction; okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // OKボタンがたっぷされたときの処理 // モーダル表示を閉じる [self dismissViewControllerAnimated:YES completion:nil]; }]; [alert addAction:okAction]; // 表示する [self presentViewController:alert animated:YES completion:nil]; } }
第9講座 効果音を付けてみよう
LESSON 27 タップしたときに効果音を再生しよう
「AVAudioPlayer」クラスのインスタンスを解放する
201ページ、「ViewController.h」の変更後のコードですが、「UIAlertViewDelegate」は使わないので、次のように「AVAudioPlayerDelegate」のみにします。
@interface ViewController : UIViewController <AVAudioPlayerDelegate>
第10講座 レベルを作ろう
LESSON 29 レベルを選択できるようにしよう
アクションシートを表示する
「UIActionSheet」クラスは、iOS 8で非推奨 (Deprecated) になってしまいました。iOS 8以降では、アラートを表示するのにも使用する「UIAlertController」クラスを使用します。「UIAlertController」クラスのインスタンスを確保するときに、引数「preferredStyle」に「UIAlertControllerStyleActionSheet」を指定すると、アクションシートになります。
ボタンがタップされたときの処理の実装方法は、アラートを表示するときと同じで、「UIAlertAction」クラスを使用します。
LESSON 30 タイトル画面用のクラスを追加してセグエを手動実行しよう
ビューコントローラ間にセグエを設定する
216ページ、手順3で選択するセグエですが、「show」を選択してください。
LESSON 31 アクションシートで選択したレベルを取得しよう
レベルを選択するアクションシートを表示する
「UIAlertController」クラスを使ってアクションシートを表示するようにコードを変更します。次のようなコードになります。
「ViewController.m」のコード
// 「START」ボタンがタップされたときの処理 - (IBAction)startGame:(id)sender { // アクションシートを作る UIAlertController *sheet; sheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; // 「Easy」ボタンのアクションを作る UIAlertAction *easyAction; easyAction = [UIAlertAction actionWithTitle:@"Easy" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { }]; // 「Middle」ボタンのアクションを作る UIAlertAction *middleAction; middleAction = [UIAlertAction actionWithTitle:@"Middle" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { }]; // 「Hard」ボタンのアクションを作る UIAlertAction *hardAction; hardAction = [UIAlertAction actionWithTitle:@"Hard" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { }]; // アクションシートにアクションを追加する [sheet addAction:easyAction]; [sheet addAction:middleAction]; [sheet addAction:hardAction]; // アクションシートを表示する [self presentViewController:sheet animated:YES completion:nil]; }
タップされたレベルを覚える
224ページから226ページのコードを、「UIActionController」クラスを使ったコードに変更します。次のようなコードになります。
「ViewController.h」のコード
このコードは、書籍では238ページで追加するコードです。しかし、「UIAlertController」クラスを使うように変更したときに、この定義があった方が良いため、先に書くようにしました。
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
// 以下の定義を追加する
// レベルのインデックス番号
enum {
kLevelEasy,
kLevelMiddle,
kLevelHard
};
// 以下省略
「TitleViewController.h」のコード
#import <UIKit/UIKit.h>
@interface TitleViewController : UIViewController
// 次の2行を追加する
// タップされたレベル
@property (assign) NSInteger level;
// 「START」ボタンがタップされたときの処理
- (IBAction)startGame:(id)sender;
@end
「TitleViewController.m」のコード
#import "TitleViewController.h" #import "ViewController.h" // この行を追加する @interface TitleViewController () @end @implementation TitleViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } // 「START」ボタンがタップされたときの処理 - (IBAction)startGame:(id)sender { // アクションシートを作る UIAlertController *sheet; sheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; // 「Easy」ボタンのアクションを作る UIAlertAction *easyAction; easyAction = [UIAlertAction actionWithTitle:@"Easy" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // 以下の行を追加する // タップされたレベルをプロパティにプロパティに入れる self.level = kLevelEasy; // セグエを実行する [self performSegueWithIdentifier:@"showViewController" sender:nil]; }]; // 「Middle」ボタンのアクションを作る UIAlertAction *middleAction; middleAction = [UIAlertAction actionWithTitle:@"Middle" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // 以下の行を追加する // タップされたレベルをプロパティにプロパティに入れる self.level = kLevelMiddle; // セグエを実行する [self performSegueWithIdentifier:@"showViewController" sender:nil]; }]; // 「Hard」ボタンのアクションを作る UIAlertAction *hardAction; hardAction = [UIAlertAction actionWithTitle:@"Hard" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // 以下の行を追加する // タップされたレベルをプロパティにプロパティに入れる self.level = kLevelHard; // セグエを実行する [self performSegueWithIdentifier:@"showViewController" sender:nil]; }]; // アクションシートにアクションを追加する [sheet addAction:easyAction]; [sheet addAction:middleAction]; [sheet addAction:hardAction]; // アクションシートを表示する [self presentViewController:sheet animated:YES completion:nil]; } @end
プレイ画面にレベルを渡す
228ページ、「TitleViewController.m」のコードで、変数「viewController」の型を「id」にすると、Xcode 7では、複数の「setLevel:」メソッドのどれを使うのかが判断出来ないというエラーが表示されます。
Multiple methods named ‘setLevel:’ found with mismatched result, parameter type or attributes
ここではコメントに書いてある通り、「ViewController」クラスになるはずなので、次のように「ViewController」と明示的に記述するようにします。
「TitleViewController.m」のコード
// セグエが実行されるときに呼ばれる
- (void)prepareForSegue:(UIStoryboardSegue *)segue
sender:(id)sender
{
// セグエによって表示されるビューコントローラを取得する
// ここではセグエは1つしか作っていないので、取得できる
// インスタンスは、「ViewController」クラスのインスタンス
ViewController *viewController;
viewController = segue.destinationViewController;
// レベルを設定する
[viewController setLevel:self.level];
}
LESSON 32 同時に作られる的の個数を変えてみよう
同時作成する的の個数を変更する
231ページのコードと、232ページから235ページまでのコードですが、出版社の訂正情報ページにも書かれています通り、ファイル名が逆になってしまっています。正しくは、231ページのコードが「MyGameView.h」ファイル、232ページから235ページにかけてのコードが「MyGameView.m」ファイルです。