fc2ブログ

Control Fun(3)~SwitchとSegmented Control

2010. 08. 13
続いてセグメンテッドコントロールとスイッチを設置します。

674

セグメンテッドコントロールには2つのボタンがあり、その下に配置するスイッチを2個配したビューの表示/非表示を切り替えます。

ビュー上の2つのスイッチは連動しており、片方を操作するともう一方も追従します。


●サンプルコードと旧版本との違い

Apress社のサイト内にサンプルコードの『Beginning iPhone Development Projects Oct 12 2009/04 Control Fun』は、手元にある旧版『はじめてのiPhoneプログラミング』とレイアウトが異なります。

665

サンプルコードでは、セグメンテッドコントロールのボタンが、スイッチを配したビューの表示/非表示ではなく、スイッチと(後述するアクションシートを呼び出す)ボタンとの表示/非表示の切り替えになっています。

ここでは旧版本の内容を説明し、サンプルコードの内容は後日別途解説します。


●セグメンテッドコントロールとスイッチの設置

セグメンテッドコントロールやスイッチを設置するにあたり、本書のP.89の図にはP.63にあるようなアクションシートを呼び出すボタンが考慮されていません。

したがって手順を参考にレイアウトはそれっぽく決めます。
(頼りのサンプルコードは前述の通り異なりますので)

まずLibraryウィンドウからSegmented Controlをドラッグ&ドロップでViewウィンドウに置き、X:20、Y:244、W:280、H:44とします。

Viewウィンドウのテキスト部分をダブルクリックし、左側のSegment 0を『First』から『Show』に、右側のSegment 1を『Second』から『Hidden』に変更します。

気になる方は、InspectorウィンドウのAttributesタブで、『View』の『Drawing』でデフォルトでチェックされているClear Context Before DrawingとAutoresize Subviewsのチェックを外してください。

666

次にセグメンテッドコントロールで表示/非表示を切り替えるビューを設置します。

このビューの上にサブビューとしてスイッチ(とラベル)を配することで、複数のオブジェクトを一度に表示制御できます。

LibraryウィンドウからViewをドラッグ&ドロップでViewウィンドウに置き、X:20、Y:295、W:280、H:100とします。
(間違ってImage Viewを置くと、その上にスイッチが置けなくて悩むので注意してください)

View領域を明示するため、InspectorウィンドウのAttributesタブで、『View』の『Background』を『Light Gray Color』にします。
(逆に『Clear Color』に設定すれば、View領域を意識させなくできます)

気になる方は、『Drawing』でデフォルトでチェックされているClear Context Before DrawingとAutoresize Subviewsのチェックを外してください。

『Opaque』のチェックは入れたままにします。
(『Opaque』のチェックが入っていても、『Background』で『Clear Color』を選択した場合には、ちゃんと透明化されます)

『Interaction』の『User Interaction Enabled』はチェックを入れたままにします。
(Viewそのものは操作しませんが、サブビューとしてスイッチを配する際に継承されるため)

667

次にViewの上にLabelとSwitchを2個ずつドラッグ&ドロップします。

各パーツの位置とサイズは下表の通りです。

 XYWH
Label (Left)46244221
Label (Right)192244221
Switch (Left)20539427
Switch (Right)166539427

ラベルの属性はInspectorウィンドウのAttributesタブで、『Label』の『Text』をそれぞれ『Left』と『Right』に、『Layout』の『Alignment』を中央揃えにします。

気になる方は、『View』の『Drawing』でデフォルトでチェックされているClear Context Before Drawing、Clip Subviews、Autoresize Subviewsのチェックを外してください。

668

スイッチの属性は特に設定する項目は無く、強いて言えば識別を容易にする為に、DocumentウィンドウのNameを修正するくらいです。

気になる方は、『View』の『Drawing』でデフォルトでチェックされているClear Context Before DrawingとAutoresize Subviewsのチェックを外してください。

『Interaction』の『User Interaction Enabled』はチェックを入れたままにします。

669

Documentウィンドウでは下図のような構成になります。

670


●アウトレットとプロパティ、アクションの宣言

パーツのレイアウトが済んだので、Interface BuilderからXcodeに戻りコードの記述を行います。

まずControl_FunViewController.hを開いて、アウトレットとプロパティ、アクションを宣言します。
(太字が追加した部分)

#import <UIKit/UIKit.h>

#define kShowSegmentIndex 0

@interface Control_FunViewController : UIViewController {
    IBOutlet UITextField *nameField;
    IBOutlet UITextField *numberField;
    IBOutlet UILabel *sliderLabel;
    IBOutlet UISwitch *leftSwitch;
    IBOutlet UISwitch *rightSwitch;
    IBOutlet UIView *switchView;
}
@property (nonatomic, retain) UITextField *nameField;
@property (nonatomic, retain) UITextField *numberField;
@property (nonatomic, retain) UILabel *sliderLabel;
@property (nonatomic, retain) UISwitch *leftSwitch;
@property (nonatomic, retain) UISwitch *rightSwitch;
@property (nonatomic, retain) UIView *switchView;

- (IBAction)textFieldDoneEditing:(id)sender;
- (IBAction)backgroundClick:(id)sender;
- (IBAction)sliderChanged:(id)sender;
- (IBAction)switchChanged:(id)sender;
- (IBAction)toggleShowHide:(id)sender;

@end

671

最初に#defineで、セグメンテッドコントロールの定数kShowSegmentIndexを設定しています。

この定数はビューの表示/非表示を行うアクションメソッドtoggleShowHide:で使用します。

セグメンテッドコントロールは前回のスライダと同様に、アクションメソッドで選択値を取得するのでアウトレットは不要になりますので、必要なアウトレットはスイッチ2つと表示/非表示を行うビュー用の3つになります。

プロパティはアウトレットと同名のものが3つになります。

アクションは、連動して動作するスイッチ用のswitchChanged:と、ビューの表示/非表示を切り替えるセグメンテッドコントロール用のtoggleShowHide:になります。


●プロパティとアクションの実装

Control_FunViewController.mを開き、宣言したプロパティとアクションを実装します。
(太字が追加した部分)

#import "Control_FunViewController.h"

@implementation Control_FunViewController

@synthesize nameField;
@synthesize numberField;
@synthesize sliderLabel;
@synthesize leftSwitch;
@synthesize rightSwitch;
@synthesize switchView;

- (IBAction)switchChanged:(id)sender {
    UISwitch *whichSwitch = (UISwitch *)sender;
    BOOL setting = whichSwitch.isOn;
    [leftSwitch setOn:setting animated:YES];
    [rightSwitch setOn:setting animated:YES];
}

- (IBAction)toggleShowHide:(id)sender {
    UISegmentedControl *segmentedControl = (UISegmentedControl *)sender;
    NSInteger segment = segmentedControl.selectedSegmentIndex;

    if (segment == kShowSegmentIndex) [switchView setHidden:NO];
    else [switchView setHidden:YES];
}

...

672

switchChanged:メソッドは、ビュー上にある2つのスイッチの内、一方を操作するともう一方も連動させるメソッドです。

前回のスライダ同様、引数のsenderをUISwitchでキャストし、onプロパティでスイッチがONかOFFかを取得します。

そして、取得したプロパティ値で両スイッチを設定し直しています。

普通に考えれば条件分岐を使いそうなところですが、今回のような場合ですと条件分岐で個別に設定するより両方に設定した方が、コードの記述量も減りますし処理が速くなるとのことです。
(『こういうやり方もある』というtipsは、初心者には地味に嬉しいですね)

toggleShowHide:メソッドは、セグメンテッドコントロールの値を取得してビューの表示/非表示を切り替えるメソッドです。

引数のsenderをUISegmentedControlでキャストし、selectedSegmentIndexプロパティで選択されたボタンの値を取得します。

その値をkShowSegmentIndex定数で比較し、hiddenプロパティでビューの表示/非表示を設定します。

setHidden:メソッドはアクセサメソッドの命名規則で、BOOL値のプロパティを表しています。

この場合UIViewのhiddenプロパティで、ゲッタがisHidden、セッタがsetHiddenとなります。
(詳細は『Cocoa Core Competencies:Accessor method』を参照してください)


・on
(UISwitchクラス)

@property(nonatomic, getter=isOn) BOOL on

スイッチのON/OFF状態を決定するブール値です。

このプロパティは、UISwitchオブジェクトがONまたはOFFかどうかを、取得または(アニメーションを除く)値の設定を行います。


・setOn:animated:
(UISwitchクラス)

- (void)setOn:(BOOL)on animated:(BOOL)animated

スイッチをONまたはOFFの状態に設定し、オプションで遷移アニメーションを指定できます。

(※上手く訳せなかったので原文を掲載します)
Setting the switch to either position does not result in an action message being sent.

on:YESの場合、スイッチはONの位置に、NOの場合OFFの位置に反転します。
スイッチが既に指定された位置の場合は何も起こりません。

animated:YESではスイッチの反転アニメーションを行い、NOではアニメーションしません。


・hidden
(UIViewクラス)

@property(nonatomic, getter=isHidden) BOOL hidden

レシーバを非表示にするかを決定するブール値です。

YESの場合はレシーバが非表示に、そうでない場合はNOになります。

デフォルト値はNOです。

ビューを非表示にするとウィンドウからは見えなくなり、入力イベントに応答できなくなります。

しかしスーパービューのサブビューリストには残っており、自動リサイズにも対応します。

ビューを非表示にすると、それらが持つサブビューとすべてのビューの子孫を隠す効果があります。

この効果は暗黙的で、レシーバの子孫の非表示状態を変更しません。

ウィンドウの現在のファーストレスポンダのビューが非表示になると、次に有効なキービューが新しいファーストレスポンダになります。

このプロパティの値はレシーバの状態のみに反映され、ビュー階層内のレシーバの先祖の状態には反映されません。

したがって、先祖が非表示になっているために非表示になっているレシーバは、このプロパティをNOにすることができます。


●アウトレットとアクションの接続

Interface Builderに戻り、DocumentウィンドウでFile's Ownerを選択し、InspectorウィンドウのConnectionsタブを開きます。

アウトレットとアクションを以下のように接続します。

・Outlets

leftSwitch → 左スイッチ
rightSwitch → 右スイッチ
switchView → スイッチの親ビュー

・Received Actions

switchChanged: → 両スイッチ
toggleShowHide: → セグメンテッドコントロール

673

接続が完了しましたら、保存してビルドと実行を行い動作を確認してください。

674

675


●UISwitchクラス

UISwitchクラスは、機内モードなどのサービス設定などで使用されるON/OFFボタンの生成と管理に使用します。

これらのオブジェクトはスイッチとして知られています。

UISwitchクラスは、ON/OFF状態を制御するプロパティとメソッドを宣言します。

UISliderのように、ユーザがスイッチ制御を操作(反転)するとUIControlEventValueChangedイベントが生成され、その制御の結果が(適切に構成されていれば)アクションメッセージとして送信されます。

UISwitchクラスはカスタマイズできません。



参考文献

UISwitch Class Reference

UISegmentedControl Class Reference

UIView Class Reference

Cocoa Core Competencies:Accessor method

はじめてのiPhone3プログラミングはじめてのiPhone3プログラミング
(2009/12/17)
Dave Mark、Jeff LaMarche 他

商品詳細を見る

Control Fun(2)~SliderとLabel

2010. 08. 13
続いてスライダと連動して値を表示するラベルを設置します。

664

●スライダとラベルの設置

LibraryウィンドウからLabelとSliderをドラッグ&ドロップでViewウィンドウに置きます。

位置とサイズは下表のようになります。

 XYWH
Label (Slider)202152921
Slider5521424723

ラベルの属性は、InspectorウィンドウのAttributesタブで『Label』の『Text』をスライダの初期値として『50』とするだけです。

気になる方は、『View』の『Drawing』でデフォルトでチェックされているClear Context Before Drawing、Clip Subviews、Autoresize Subviewsのチェックを外してください。

ラベルの値はスライダの操作に連動して変化しますが、ラベル自体を操作するわけではないので『Interaction』の『User Interaction Enabled』をチェックする必要はありません。

658

スライダは、最小値と最大値、そして初期値を設定する必要があります。

今回は1.00~100.00の範囲で初期値を50.00とします。

InspectorウィンドウのAttributesタブで『Slider』の『Values』を、Minimum:1.00、Maximum:100.00、Initial:50.00とします。

気になる方は、『View』の『Drawing』でデフォルトでチェックされているClear Context Before DrawingとAutoresize Subviewsのチェックを外してください。

ラベルと同様にOpaqueにチェックを入れると、透過部分が黒くなるのでチェックは入れないでください。

660

スライダは操作するので『Interaction』の『User Interaction Enabled』はチェックされたままにしておきます。

659


●アウトレットとプロパティ、アクションの宣言

パーツのレイアウトが済んだので、Interface BuilderからXcodeに戻りコードの記述を行います。

まずControl_FunViewController.hを開いて、アウトレットとプロパティ、アクションを宣言します。
(太字が追加した部分)

#import <UIKit/UIKit.h>

@interface Control_FunViewController : UIViewController {
    IBOutlet UITextField *nameField;
    IBOutlet UITextField *numberField;
    IBOutlet UILabel *sliderLabel;
}
@property (nonatomic, retain) UITextField *nameField;
@property (nonatomic, retain) UITextField *numberField;
@property (nonatomic, retain) UILabel *sliderLabel;

- (IBAction)textFieldDoneEditing:(id)sender;
- (IBAction)backgroundClick:(id)sender;
- (IBAction)sliderChanged:(id)sender;

@end

661

アウトレットはラベル用のsliderLabelだけで、スライダ用には宣言しません。

スライダの値の取得はアクションで行うので、アウトレットは不要だからです。

プロパティはラベル用のアウトレットと同名のものを用意します。

アクションはスライダの値を取得するsliderChanged:メソッドになります。


●プロパティとアクションの実装

Control_FunViewController.mを開き、宣言したプロパティとアクションを実装します。
(太字が追加した部分)

#import "Control_FunViewController.h"

@implementation Control_FunViewController

@synthesize nameField;
@synthesize numberField;
@synthesize sliderLabel;

- (IBAction)sliderChanged:(id)sender {
    UISlider *slider = (UISlider *)sender;
    int progressAsInt = (int)(slider.value + 0.5f);
    NSString *newText = [[NSString alloc] initWithFormat:@"%d", progressAsInt];
    sliderLabel.text = newText;
    [newText release];
}

...

662

sliderChanged:アクションメソッドは、最初に引数のsenderをUISliderクラスの変数sliderにキャストしています。

その引数からUISliderクラスのvalueプロパティでスライダの値を取得しています。
(valueプロパティの詳細は『スライドショーのメソッド(2)』を参照してください)

取得した値valueはfloatなので、整数に丸めるために0.5を加算して、intにキャストしています。

得られたint値progressAsIntを、ラベル表示用の文字列newTextに変換し、textプロパティでラベルのアウトレットsliderLabelに設定します。

最後にメソッド内で生成したNSStringオブジェクトのnewTextを解放します。


・text
(UILabelクラス)

@property(nonatomic, copy) NSString *text

ラベルで表示するテキストです。

この文字列はデフォルトでnilになっています。


●アウトレットとアクションの接続

Interface Builderに戻り、DocumentウィンドウでFile's Ownerを選択し、InspectorウィンドウのConnectionsタブを開きます。

『Outlets』の『SliderLabel』はラベルに接続し、『Received Actions』の『sliderChanged:』はスライダに接続してValue Changedを選択します。

663

接続が完了しましたら、保存してビルドと実行を行い動作を確認してください。

664


●UILabelクラス

UILabelクラスは、読み込み専用のテキストビューを実装します。

このクラスは一行または複数行の静的テキストの描画に使用することができ、ユーザインターフェイスで他のパーツとの識別などに使われます。

基本的にUILabelクラスは、陰影を使用したり強調表示を含む、テキストの外観の制御を提供します。

必要があれば、サブクラス化でテキストの外観を更にカスタマイズすることができます。

UILabelクラスのデフォルトのコンテンツモードはUIViewContentModeRedrawです。

このモードは、矩形領域が変更される度にコンテンツを再描画します。

このモードは、クラスの継承されたcontentModeプロパティで変更することができます。

新規に生成されたラベルオブジェクトは、デフォルトでユーザイベントを無視する設定になっています。

UILabelのカスタムサブクラスでイベント処理を行いたい場合は、オブジェクトを初期化した後に、明示的にuserInteractionEnabledプロパティの値をYESに変更する必要があります。



参考文献

UILabel Class Reference

はじめてのiPhone3プログラミングはじめてのiPhone3プログラミング
(2009/12/17)
Dave Mark、Jeff LaMarche 他

商品詳細を見る

Calendar
07 | 2010/08 | 09
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 - - - -
Recent Articles
Wish List
iOS/iPadOS Devices
Twine
Twine Reference
1. 序章
2. はじめに
2.1. Twineのインストール
2.2. 基本コンセプト
2.3. Twineを使いこなす
2.4. Twineのアップデート
2.5. Twineのアンインストール
2.6. Twineの古いバージョンを使う
3. ストーリーライブラリを使う
3.1. ストーリーの表示
3.2. ストーリーの作成、コピー、インポート
3.3. ストーリーの編集
3.4. ストーリー名の変更
3.5. ストーリーのアーカイブとエクスポート
3.6. ストーリーの削除
3.7. ストーリーへのタグ付け
3.8. ライブラリの場所を変更する
4. ストーリーの編集
4.1. ストーリーマップのナビゲーション
4.2. 取り消しとやり直し
4.3. パッセージの選択と移動
4.4. パッセージの編集
4.5. パッセージのリンク
4.6. パッセージの削除
4.7. パッセージのタグ付け
4.8. テキストの検索と置換
4.9. ストーリー名の変更
4.10. ストーリーフォーマットの変更
4.11. ストーリーの統計の表示
4.12. ストーリーのJavaScriptとCSSを編集する
5. 作品の公開出力
5.1. ストーリーのテスト
5.2. ストーリーの校正
5.3. ストーリーのプレイ
5.4. ストーリーの公開出力
5.5. スクラッチフォルダ
6. ストーリーフォーマットの管理
6.1. ストーリーフォーマットの表示
6.2. デフォルトのストーリーフォーマットの変更
6.3. 校正フォーマットの変更
6.4. ストーリーフォーマットの追加
6.5. ストーリーフォーマットの削除
6.6. ストーリーフォーマットの拡張機能を無効にする
6.7. Twineがストーリーフォーマットのバージョンを管理する方法
7. Twineのカスタマイズ
7.1. 環境設定の設定
7.2. コマンドラインスイッチ
7.3. 高度なカスタマイズ
8. 制限事項
8.1. 大きなストーリー
8.2. ストーリーの組み合わせ
8.3. ストーリーの共同編集
8.4. 画像とマルチメディアの使用
8.5. ソースコントロールでの作業
9. 問題のトラブルシューティング
9.1. バックアップ
9.2. ローカルストレージの直接表示
9.3. 編集中にエラーメッセージが表示される場合
9.4. Twineが起動しない場合
9.5. Twineがあなたのストーリーを失ったら
9.6. ストーリーが破損している場合
9.7. Twineの外観に不具合がある場合
10. リリースノート
10.1. バージョン 2.8
10.2. バージョン 2.7
10.3. バージョン 2.6
10.4. バージョン 2.5
10.5. バージョン 2.4
10.6. バージョン 2.3
10.7. バージョン 2.2
10.8. バージョン 2.1
10.9. バージョン 2.0
10.10. バージョン 1.0
10.11. Tweebox バージョン

Twine Cookbook
詳解Swift
詳解Swift第5版(01)〜Swiftでプログラミング
詳解Swift第5版(02)〜関数
詳解Swift第5版(03)〜構造体
詳解Swift第5版(04)〜オプショナル
詳解Swift第5版(05)〜プロトコル
詳解Swift第5版(06)〜基本的なデータ型
詳解Swift第5版(07)〜パターン
詳解Swift第5版(08)〜クラスと継承
詳解Swift第5版(09)〜メモリ管理
詳解Swift第5版(10)〜拡張
詳解Swift第5版(11)〜エラー処理
詳解Swift第5版(12)〜クロージャ
詳解Swift第5版(13)〜ジェネリクス
詳解Swift第5版(14)〜メモリへのアクセスとポインタ
詳解Swift第5版(15)〜カスタム属性とDSL記法
詳解Swift第5版(16)〜GUI との連携

詳解Swift第4版(01)〜Swiftでプログラミング
詳解Swift第4版(02)〜関数
詳解Swift第4版(03)〜構造体
詳解Swift第4版(06)〜基本的なデータ型
詳解Swift第4版(07)〜パターン
詳解Swift第4版(08)〜クラスと継承
詳解Swift第4版(09)〜メモリ管理
詳解Swift第4版(10)〜拡張
詳解Swift第4版(11)〜エラー処理
詳解Swift第4版(12)〜クロージャ
詳解Swift第4版(13)〜ジェネリクス

詳解Swift第3版(01)〜Swiftでプログラミング
詳解Swift第3版(02)〜関数
詳解Swift第3版(03)〜構造体
詳解Swift第3版(05)〜基本的なデータ型
詳解Swift第3版(06)〜パターン
詳解Swift第3版(07)〜演算子
詳解Swift第3版(08)〜クラスと継承
詳解Swift第3版(09)〜メモリ管理
詳解Swift第3版(10)〜プロトコル
詳解Swift第3版(11)〜拡張
詳解Swift第3版(12)〜エラー処理
詳解Swift第3版(13)〜クロージャ
詳解Swift第3版(14)〜ジェネリクス

詳解Swift改訂版(01)〜Swiftでプログラミング
詳解Swift改訂版(02)〜関数
詳解Swift改訂版(03)〜構造体
詳解Swift改訂版(04)〜オプショナル
詳解Swift改訂版(05)〜基本的なデータ型
詳解Swift改訂版(06)〜パターン
詳解Swift改訂版(07)〜演算子
詳解Swift改訂版(08)〜クラスと継承
詳解Swift改訂版(09)〜メモリ管理
詳解Swift改訂版(10)〜プロトコル
詳解Swift改訂版(11)〜拡張
詳解Swift改訂版(12)〜エラー処理
詳解Swift改訂版(13)〜クロージャ
詳解Swift改訂版(14)〜ジェネリクス

詳解Swift(1)〜Swiftでプログラミング
詳解Swift(2)〜関数
詳解Swift(3)〜構造体
詳解Swift(4)〜オプショナル
詳解Swift(5)〜基本的なデータ型
詳解Swift(6)〜パターン
詳解Swift(7)〜演算子
詳解Swift(8)〜クラスと継承
詳解Swift(9)〜メモリ管理
詳解Swift(10)〜プロトコル
詳解Swift(11)〜拡張
詳解Swift(12)〜クロージャ
詳解Swift(13)〜ジェネリクス
詳解Swift(14)〜C/Objective-Cとのデータ受け渡し
Swift
Site Map
Apple Music


Categories
Tips
ARC
Technical Q&A
情報プロパティリストキー
Start Developing iOS Apps Today
Monthly Archives
Recent Comments
Recent TrackBacks
RSS Link
QR Code
QR
Profile

水月杏香

Author:水月杏香
永遠の初心者プログラマ

Visitors