iPhoneアプリ開発 熟達テクニック

【その1】(初版のみ)

対象となる章

CHAPTER 01 ダウンロードアプリの開発

対象となるページ

P.20●Webサーバの準備

Mac OS X 10.7 Lionでは、操作方法が変更になっており、本書の通りに操作するとエラーになります。Mac OS X 10.7 Lionでは、「★HTTPベーシック認証で保護された領域を作成する」の手順(3)と(4)は、次のように操作してください。

(3)「「htpasswd -c userdb ユーザ名」と入力します。たとえば、ユーザ名が「akira」であれば、次のように入力します。
====

sudo htpasswd -c userdb akira
====

(4)まず、「Password:」というプロンプトが表示されるので、「sudo」を実行するためログインユーザの管理者パスワードを入力し、次に「New password:」というプロンプトで、追加するユーザに設定したいパスワードを入力します。

【その2】(初版のみ)

対象となる章

CHAPTER 03 ページスクラップブックの開発

対象となるページ

P.163-256

iOS 8で行われた、いくつかの変更により動作しなくなっています。
次のような修正を行うことで、動作するようになります。

[1] 「UIAlertController」クラスへの置き換え
iOS 8から、「UIAlertView」クラスは非推奨となり、「UIAlertController」クラスが導入されました。これらを置き換える必要があります。

・「ConnectionViewController.m」の「connection:didFailWithError:」メソッド

====
- (void)connection:(NSURLConnection *)connection
  didFailWithError:(NSError *)error
{
    NSString *errMsg = @"Error occurred.";
    if (error)
    {
        errMsg = [errMsg stringByAppendingString:
                  [error localizedDescription]];
    }
    
    if (NSClassFromString(@"UIAlertController"))
    {
        // iOS 8以降は「UIAlertController」クラスを使用する
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Connection Error"
                                                                       message:errMsg
                                                                preferredStyle:UIAlertControllerStyleAlert];
        
        UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK"
                                                         style:UIAlertActionStyleCancel
                                                       handler:^(UIAlertAction *action) {
                                                           // 通信画面を閉じる
                                                           [self dismissViewControllerAnimated:NO
                                                                                    completion:nil];
                                                       }];
        [alert addAction:action];
        [self presentViewController:alert
                           animated:YES
                         completion:nil];
    }
    else
    {
        // iOS 8未満は「UIAlertView」クラスを使用する
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Connection Error"
                                                        message:errMsg
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];
        
        // 通信画面を閉じる
        [self dismissViewControllerAnimated:NO
                                 completion:nil];
    }
}
====

[2] 非同期動作への対応
モーダル表示は、従来は同期的な動作でしたが、非同期動作に変更になりました。
次のように、モーダル表示直後の処理は、完了ブロックに移動する必要があります。

・「RootViewController.m」の「viewDidAppear:」メソッド
(「presentModalViewController:animated:」メソッドを「presentViewController:animated:completion:」メソッドに置き換えて、「presentModalViewController:animated:」の後の処理を引数「completion」内に移動しています)

===
// ビューが表示された直後の処理
- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    
    // 通信画面が閉じた後に表示されたのか、そうでないかの判定を行う
    if (self.connectionViewController)
    {
        // 通信画面が閉じた後に表示されたタイミングなので
        // 受信データから表示データを用意する
        [self reloadFromReceivedData];
        
        // 通信画面は必要なくなったので解放する
        // これにより、他のビューコントローラを表示して
        // 再表示されるときには、通信が行われる
        [self setConnectionViewController:nil];
    }
    else
    {
        // 通信前なので、サーバと通信する
        // 接続先のURLを作成する
        // ここでの接続先は、情報の一覧を取得するAPIへのURL
        NSURL *url = [NSURL URLToDoList];
        
        // 接続要求を作成する
        NSURLRequest *req;
        req = [NSURLRequest requestWithURL:url];
        
        // 通信画面を表示して、通信を開始する
        ConnectionViewController *vc;
        vc = [[ConnectionViewController alloc] initWithNibName:nil
                                                        bundle:nil];
        [vc setUrlRequest:req];
//        [self presentModalViewController:vc
//                                animated:NO];
        
        [self presentViewController:vc
                           animated:NO
                         completion:^{
                             // もし、通信画面が既に非表示になっていたら、通信を開始できなかった
                             // ということなので、プロパティにセットしない
                             if (vc.view.window)
                             {
                                 [self setConnectionViewController:vc];
                             }
                         }];
        
        
        [vc autorelease];
    }
}
===