CS193p - Lecture 15

iTunes U スタンフォード大学のiOSアプリ開発講義のLecure 15(Modal View Controllers, Text, Animation) の講義メモです。

Modal View Controllers

モーダルビューは、何かのモード状態にあるという意味のビューで、ユーザが質問に答えるなどしてモードを完了させないと他の画面に移るなどのそのビュー外の操作ができないようにするビューである。
モーダルビューコントローラはネスト可能で、モーダルビューコントローラからモーダルビューコントローラを呼び出せる。

■作成方法
・storyboardで作成

SegueタイプをmodalにしてSegue先として指定する。

・コードで作成

- (IBAction)lookupAddress
{
    AddressLookupViewController *alvc = [self.storyboard

instantiateViewControllerWithIdentifier:@“AddressLookup”];

    [self presentModalViewController:alvc animated:YES completion:^{

    // alvcが画面に表示されている状態。たいていここですることはない

    }];
}

 

■モーダル状態の終了
モーダルビューを起動した元のビューコントローラに次のメッセージを送る。

- (void)dismissModalViewControllerAnimated:(BOOL)animated;

 

・モーダルビューが自身で終了させる方法
起動元のビューコントローラに対して上記のメッセージを送る。

[[self presentingViewController] dismissModalViewController:YES];

※全てのビューコントローラは自分を起動したビューコントローラ(presentingViewController)を知っている。

<起動元のビューコントローラからモーダルビューを終了させる例>

※アドレス帳をモーダルビューとして起動している場合

//モーダルビューはsegueの1つなので、prepareForSegueでdelegate登録する
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@“Lookup Address”]) {
        AddressLookupViewController *alvc =

(AddressLookupViewController *)segue.dest...;

        // 他の設定…
        alvc.delegate = self; // delegate登録
    }
}
// AddressLookupViewControllerのdelegate methodを起動元で実装
// アドレス帳からアドレスが選択された後に呼び出されるdelegateメソッド
- (void)addressLookupViewController:(AddressLookupViewController *)sender didSelectAddress:(Address *)anAddress
{ 

    // 起動したモーダルビューを終了

    [self dismissModalViewControllerAnimated:YES];  

}

 

・モーダルビューコントローラのアニメーションの種類

@property UIModalTransitionStyle modalTransitionStyle;
UIModalTransitionStyleCoverVertical // 下からスライドアップしてスライドダウン
UIModalTransitionStyleFlipHorizontal // フリップしてモーダルビューを表示
UIModalTransitionStyleCrossDissolve // フェードアウト後、新ビューがフェードイン
UIModalTransitionStylePartialCurl // ページめくりで表示(フルスクリーンの時だけ)

・iPadでの考慮点

iPhoneでは常に画面全体がモーダルビューでよいが、iPadでは画面の一部に小さなモーダルビューが表示された方がよい場合がある。
@property UIModalPresentationStyle modalPresentationStyle; // in the modal VC
UIModalPresentationFullScreen // フルスクリーンで
UIModalPresentationPageSheet // 小さなカードのように画面の一部で
UIModalPresentationFormSheet //画面中央に
UIModalPresentationCurrentContext // 起動したビューの全領域を使って

UITextField

UITextFieldは文字入力用のフィールドでUILabelと同じように使える。
UITextFieldが"first responder"になった時にキーボードが表示される。
※first responderとは、文字入力部分に文字入力を促すようにカーソルが点滅している状態

・first responderになる方法
    a) ユーザがタップ
    b) becomeFirstResponderを送信

・first responderの終了
resignFirstResponderがUITextFieldに送られるとfirst responder状態が終了する。

・入力された文字を取得する方法

- (BOOL)textFieldShouldReturn:(UITextField *)sender; //リターンキーが押された時にコールされる(入力チェック時に使う)

- (void)textFieldDidEndEditing:(UITextField *)sender; //入力終了時にコールされる

 

・キーボード

@property UITextAutocapitalizationType autocapitalizationType; // 大文字
@property UITextAutocorrectionType autocorrectionType;
@property UIReturnKeyType returnKeyType; //リターンキーの表示を"Go"などに変更
@property BOOL secureTextEntry; //パスワード入力
@property UIKeyboardType keyboardType; //ASCII, URL, PhonePadなど

・UITextFieldのプロパティ

@property BOOL clearsOnBeginEditing;
@property BOOL adjustsFontSizeToFitWidth;
@property CGFloat minimumFontSize; // adjustsFontSizeToFitWidthセット時はこれも
@property NSString *placeholder; // 未入力時に表示される入力例などのグレーの文字列
@property UIImage *background/disabledBackground;

・その他のUITextFieldの機能
検索フィールドの虫眼鏡アイコンや入力文字列を削除する×ボタンなどMKAnnotationViewのように左右にオーバーレイを持つことが出来る。

 

UITextView

UITextViewは、複数行でスクロール可能な入力領域。
UITextFieldではリターンキーで入力終了となるが、UITextViewはリターンキーで改行となる。
UITextViewで表示される文字のフォントは単一なので、部分的にフォントを変更したい場合はUIWebViewとHTMLを使用する。

UIView Animation

アニメーションはUIViewのクラスメソッドである。(インスタンスメソッドではない)
UIViewのアニメーションはCore Animationフレームワークで作られているので、高パフォーマンスなアニメーションを行いたければ直接Core Animationフレームワークを使う。

■アニメーション可能なプロパティ
hidden
frame
transform (translation, rotation and scale)
alpha (opacity)

アニメーションは、実際には設定した瞬間に変更後の値に変化しているが、画面上は指定した時間を使って表示される。
※アニメーション設定時に"completion block"を指定するが、このブロックはすぐに実行される(非同期ではない)。
そして、画面上のアニメーションの表示はメインスレッド以外のスレッドで処理される。

・UIViewのアニメーションクラスメソッド

+ (void)animateWithDuration:(NSTimeInterval)duration
     delay:(NSTimeInterval)delay
   options:(UIViewAnimationOptions)options
animations:(void (^)(void))animations
completion:(void (^)(BOOL finished))completion;

 

<例>

[UIView animateWithDuration:3.0
                      delay:0.0
                    options:UIViewAnimationOptionBeginFromCurrentState
                 animations:^{ myView.alpha = 0.0; }
                 completion:^(BOOL fin) { if (fin) [myView removeFromSuperview]; }];

※myViewが3秒かけてフェードアウトし、フェードが完了した場合はビューの階層から削除される。 この3秒間の間に誰かがalphaを0以外の値にアニメーション設定したら削除は行われない。

・UIViewAnimationOptions

BeginFromCurrentState    // 他の実行中のアニメーションを中断する
AllowUserInteraction         // アニメーション実行中のジェスチャを有効にする
LayoutSubviews                // サブビューのレイアウトをアニメーションさせる
Repeat                             // 延々とリピート
Autoreverse                     // 進んで戻ってくるアニメーション
OverrideInheritedDuration // 指定しないと、実行中のdurationが使われる
OverrideInheritedCurve     // 指定しないと、実行中のCurve(ease-in/outなど)が使われる
AllowAnimatedContent     // 指定しないと、現在の状態から終了状態の間に割り込むだけ
CurveEaseInEaseOut        // ゆっくり始まり、通常の状態で進み、ゆっくり終わる
CurveEaseIn                    // ゆっくり始まり、あとは一定で進む
CurveLinear                     // 一定のスピードで進む
TransitionFlipFromLeft/Right // ビューの階層から隠したり削除するのに使う
TransitionCurlUp/Down    // ビューの階層から隠したり削除するのに使う

・ビューの階層を変更するアニメーション
サブビューを削除したり追加したりするようなビューの階層を変更するアニメーションは次のメソッドで行う。

+ (void)transitionFromView:(UIView *)fromView
                    toView:(UIView *)toView
                  duration:(NSTimeInterval)duration
                   options:(UIViewAnimationOptions)options

completion:(void (^)(BOOL finished))completion;

 

ビューのプロパティにhiddenを設定したい場合は、UIViewAnimationOptionShowHideTransitionViewsをオプションに含める。
もしくは、次のメソッドのブロックの中で追加/削除/隠す処理を行う。

+ (void)transitionWithView:(UIView *)view
                  duration:(NSTimeInterval)duration
                   options:(UIViewAnimationOptions)options
                animations:(void (^)(void))animations
                completion:(void (^)(BOOL finished))completion;

 

NSTimer

NSTimerはメインキューの中のスケジュール処理である。そのため、メインスレッドがビジー状態であれば、設定した時間間隔では処理されない。

NSTimer *timer =

[NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval)seconds
                                                  target:self
                                                selector:@selector(doSomething:)
                                                userInfo:(id)anyObject
                                                 repeats:(BOOL)yesOrNo];

 

デモ(モーダル画面で入力&アニメーション)

実装時の注意点

・テキストフィールドのdelegateメソッドを使用する時には、viewDidLoadなどで、そのテキストフィールドのdelegateを設定する。

self.answerTextField.delegate=self;

 

・テキストフィールドがあるビューでは、viewWillAppear: で first responderを設定する。

[self.answerTextField becomeFirstResponder];

 

・prepareForSegueの中でアウトレットの設定はしない

Xcodeの操作

・storyboardでジェスチャを追加する方法
1. オブジェクトライブラリからジェスチャをドラッグアウト
2. アウトラインのジェスチャをctrl-ドラッグしてコードにアクションを作成する。