中学生でもわかる iOSアプリ開発講座 訂正情報・更新情報

中学生でもわかる 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」は使わないのでオフにします。

中学生でもわかるiOSアプリ開発講座 オプションの設定

中学生でもわかるiOSアプリ開発講座 オプションの設定

LESSON 10  シミュレータでアプリを実行しよう

Xcode 7に付属しているシミュレータは英語版のみです。シミュレータを終了するには、「Simulator」メニューから「Quit Simulator」を選択します。
また、iOSデバイスの解像度が上がっているため、ディスプレイに表示しきれないことがあります。このようなときは、表示倍率を小さくします。表示倍率を小さくするには、「Window」メニューの「Scale」から表示倍率を選択します。「コマンド」キーを押しながら「1」から「5」までのキーを押しても変わります。

LESSON 11  タイトル画面とプレイ画面を作成しよう

Xcode 6, iOS 8でサイズクラスが登場したために、Storyboardの編集画面が正方形に変わっていますが、書籍で解説している操作方法で同様に編集できます。
サイズクラスは、色々なアスペクト比の画面に対応するための仕組みです。

ラベルの自動レイアウトの設定

60ページ、「10 ラベルの自動レイアウトの設定」で表示されるボタンの種類が変わっています。整列位置のコンストレイントを表示するボタンは次の図のようになります。
2016-01-24_10-14-13

明示的に設定していないコンストレイントの設定

62ページ、「13 明示的に設定していないコンストレイントの設定」で選択するコマンドは、Xcode 7では「All Views in View Controller」の下側に表示される「Add Missing Constraints」を選択します。コマンドを表示するためのボタンは、右端のボタンを使用します。
2016-01-24_10-23-47
2016-01-24_10_25_26

セグエの選択

66ページ、「3 セグエの選択」は、Xcode 7では「modal」は「Deprecated」になってしまったので、「Show」を選択してください。
2016-01-24_11_11_28

セグエについて

モーダル表示とプッシュ表示は、Xcode 7とiOS 9でも存在する表示方法です。セグエの選択で「Show」を選択すると、ナビゲーションコントローラ(階層表示を行うための管理クラス)内ではプッシュ表示になり、本書のようにナビゲーションコントローラに属していないものでは、モーダルになります。
ナビゲーションコントローラ内でもモーダルにしたい場合には、「Present Modally」を選択します。

プレイ画面のコンストレイントの設定

本書ではプレイ画面で表示している、「Score」と「Time」のコンストレイントを設定していないため、正方形の編集画面の座標がそのまま使われてしまい、画面の外に出てしまいます。次のように操作して、コンストレイントを設定してください。
(1) 「Score」のテキストフィールドを選択する。
(2) 整列位置のコンストレイントを設定するボタンをクリックして、上と下の位置、Width, Heightを指定して、「Add Contraints」ボタンをクリックする。
2016-01-24_11-37-52
(3) 「Time」のテキストフィールドを選択する。
(4) 整列位置のコンストレイントを設定するボタンをクリックして、上と右の位置、Width, Heightを指定して、「Add Constraints」ボタンをクリックする。
2016-01-24_11-38-25

第5講座  クラスを作成しよう

LESSON 12  ビュークラスを作ろう

テンプレートの選択

76ページ、「3 テンプレートの選択」で、ダイアログに表示されるテンプレートの種類が変わっています。書籍では「Objective-C class」になっていますがXcode 7では無くなっています。「Cocoa Touch Class」を選択してください。
他の場所でもクラスを追加するという操作がありますが、同じように操作してください。

クラス名とスーパークラスの設定

77ページ、「4 クラス名とスーパークラスの設定」で、作成するソースファイルの言語も選ばなければいけなくなりました。「Language」から「Objective-C」を選択してから「Next」ボタンをクリックしてください。他のクラスを追加するときも、本書ではObjective-Cを使っているので、「Objective-C」を選択してください。
2016-01-24_13-01-05

第6講座  的を表示しよう

LESSON 16  ビューの中に的を表示しよう

的の画像を組み込む

105ページ、「3 追加するファイルの選択」でオンにするチェックボックスは、Xcode 7では初期状態では表示されません。「Options」ボタンをクリックすると表示されます。
2016-01-25_08-09-20

第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ファイルの編集画面のレイアウト変更により、場所が変わっています。
2016-01-30_23-39-28

第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」ファイルです。
 

著書紹介

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

Akira Hayashi (林 晃)のアバター Akira Hayashi (林 晃) Representative(代表), Software Engineer(ソフトウェアエンジニア)

アールケー開発代表。Appleプラットフォーム向けの開発を専門としているソフトウェアエンジニア。ソフトウェアの受託開発、技術書執筆、技術指導・セミナー講師。note, Medium, LinkedIn
-
Representative of RK Kaihatsu. Software Engineer Specializing in Development for the Apple Platform. Specializing in contract software development, technical writing, and serving as a tech workshop lecturer. note, Medium, LinkedIn

目次