☆Cocoa Touch UIKit勉強(5)
UIResponder
UIResponderはUIKitのルートとも言えるコントロールで、
その殆どのクラスがこれの子クラスである。
画面タッチやデバイスの傾き検知、シェイクなどのイベントを一括管理している。
UIResponderクラスは、イベントに反応して取り扱うオブジェクトのために、インターフェースを定義する。
これは、UIApplication、UIViewとその子クラス(UIWindowを含む)の親クラスである。
これらのクラスのインスタンスは、レスポンダー(オブジェクト)と呼ばれる。
イベントには大きく分けて「タッチイベント」と「モーションイベント」の2つがある。
touchesで始まる名称のメソッドがタッチイベント用である。
指が画面に触れる・ドラッグされる・画面から離れる時はUIEventオブジェクトが生成される。
指が画面上にあるまたは離れるときのイベントオブジェクトはUITouchオブジェクトを含む。
装置を振る運動;モーションイベントはmotionで始まる名前のメソッドである。
UIMenuControllerを使ったメニューへの応答をする場合にはFirstResponderになる必要がある。
この辺りは画面回転と絡んで結構面倒なので要注意。
UIResponder
メソッド名 | 動作 |
-(BOOL)becomeFirstResponder | ウインドウの第一レスポンダーになる |
-(BOOL)resignFirstResponder | ウインドウの第一レスポンダーを放棄する |
-(BOOL)canBecomeFirstResponder | 第一レスポンダーになれるかどうかを返す |
-(BOOL)isFirstResponder | レシーバーが第一レスポンダーかどうか |
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event | ビューまたはウインドウ内にタッチダウンされた |
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event | ビューまたはウインドウから指が離された |
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event | ビューまたはウインドウ内で指の移動が検出された |
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event | タッチイベントがキャンセルされた |
-(void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event | モーションイベントが開始された |
-(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event | モーションイベントが終了した |
-(void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event | モーションイベントがキャンセルされた |
UITextField/UITextViewでキーボードを表示するには
[textField becomeFirstResponder];
[textView becomeFirstResponder];
、消去するには
[textField resignFirstResponder];
[textView resignFirstResponder];
と記述する。これは定型文なので、覚えておくしかない。
UIApplication
UIApplication・・・通常、このクラス自体を直接操作する必要はない。
Xcodeがひな形を書き出してるAppDelegate.m(だいたいこんな名前にする)がUIApplicationプロトコルに準拠するので、
そのメソッドを実装するだけである。
UIApplication
デリゲートは
UIApplicationDelegate
プロトコルで実装する。プログラム起動時を含め絶対に書かなければならない部分もある。
メソッド名 | 動作 |
-(void)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions |
アプリケーションが起動される時呼び出される。もちろん必須。
|
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
|
UIDocumentInteractionControllerでのファイル共有受信時に呼び出される。
URLで指定されるリソースを開くことができる。
|
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window |
アプリケーションでサポートする画面の回転方向を返す。
通常画面の回転方向は個別のUIViewControllerがsupportedInterfaceOrientationsで返すが、
それがないときに代わりにこれが呼び出される。画面ごとの特別な回転制御が必要ないなら、これだけで良い。
|
-(void)applicationDidFinishLaunching:(UIApplication *)application |
アプリケーションの起動が終わったとき呼び出される
|
-(void)applicationDidBecomeActive:(UIApplication *)application |
アプリケーションが再アクティブになったとき呼び出される。
非アクティブからの復帰時だけでなく、アプリケーション起動時にも呼ばれる。
|
-(void)applicationWillResignActive:(UIApplication *)application |
アプリケーションがアクティブになるとき=HOMEボタンを押したとき呼び出される。
|
-(void)applicationWillTerminate:(UIApplication *)application |
アプリケーションが終了するとき呼び出される。
HOMEボタンを押しただけでは非アクティブになるだけで、これは呼び出されない。
|
-(void)applicationDidEnterBackground:(UIApplication *)application |
アプリケーションがバックグラウンドに入ったとき呼び出される
|
-(void)applicationWillEnterForeground:(UIApplication *)application |
アプリケーションがフォアグラウンドに戻るとき呼び出される
|
-(void)applicationDidReceiveMemoryWarning:(UIApplication *)application |
アプリケーションがシステムからメモリ警告を受信した
|
-(void)application:(UIApplication *)application
willChangeStatusBarOrientation:(UIInterfaceOrientation)newStatusBarOrientation duration:(NSTimeInterval)duration |
didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation |
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken |
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error |
didReceiveLocalNotification:(UILocalNotification *)notification |
didReceiveRemoteNotification:(NSDictionary *)userInfo |
|
ステータスバーの方向が変わる前 |
ステータスバーの方向が変わったとき |
Apple Push Serviceへ正常に登録できたとき |
Apple Push Serviceが登録プロセスを正常に完了することができないとき |
走っているアプリケーションがローカル通知を受信したとき |
走っているアプリケーションがリモート通知を受信したとき |
|
プロパティ名 | 属性 | 内容 |
id <UIApplicationDelegate> delegate | S | デリゲートを設定する |
BOOL applicationSupportsShakeToEdit | | シェイクによるundo/redo操作を可能にする(デフォルトはYES) |
NSInteger applicationIconBadgeNumber | | スプリングボード内のアプリケーションアイコンのバッジの現在番号(0=バッジを隠す;デフォルト) |
UIApplicationState applicationState | R | アプリケーションの実行状態
UIApplicationState(enum値)
UIApplicationStateActive | フォアグラウンドで実行中&イベント受信状態 |
UIApplicationStateInactive | フォアグラウンドで実行中だがイベントは受信していない |
UIApplicationStateBackground | バックグラウンド実行中 |
|
NSTimeInterval backgroundTimeRemaining | R | アプリケーションがバックグラウンドで動く時間 |
BOOL networkActivityIndicatorVisible | G=isNetworkActivityIndicatorVisible | ネットワークが有効かどうかのインジケーターをON/OFFする |
BOOL statusBarHidden | G=isStatusBarHidden | ステータスバーを隠すかどうか |
UIInterfaceOrientation statusBarOrientation | | アプリケーションステータスバー現在の方向 |
UIStatusBarStyle statusBarStyle | | 現在のステータスバーの形状
UIStatusBarStyle(enum値)
UIStatusBarStyleDefault | 灰色(デフォルト) |
UIStatusBarStyleBlackTranslucent | 半透明黒 |
UIStatusBarStyleBlackOpaque | 不透明黒 |
|
メソッド名 | 動作 |
-(UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^)(void))handler |
新しい長く走るバックグラウンドタスクの開始を記録する
UIBackgroundTaskIdentifierはNSUInteger値でバックグラウンドで走るリクエストへのユニークなID
|
-(void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier
| 長く走るバックグラウンドタスクの終わりを記録する
|
-(void)beginIgnoringInteractionEvents | タッチ関連のイベントの取扱いを停止するようにレシーバーに言う |
-(void)beginReceivingRemoteControlEvents | リモートコントロールイベントの受信を始めるようアプリケーションに通知する |
-(void)endIgnoringInteractionEvents | タッチ関連のイベントの取扱いを再開するようにレシーバーに言う |
-(void)endReceivingRemoteControlEvents | 遠隔操作のイベントを受けるのを止めるようにアプリケーションに言う |
-(void)presentLocalNotificationNow:(UILocalNotification *)notification | すぐにローカル通知を発行する |
-(void)scheduleLocalNotification:(UILocalNotification *)notification | 内包された日時に発行するようローカル通知を予定する
|
-(void)cancelAllLocalNotifications | すべての予定のローカル通知の通知をキャンセルする |
-(void)cancelLocalNotification:(UILocalNotification *)notification
| ローカル通知の通知をキャンセルする
|
-(BOOL)canOpenURL:(NSURL *)url | アプリケーションが与えられたURLリソースを開けるかどうか |
-(void)clearKeepAliveTimeout | 前にインストールされた周期起動ハンドラーブロックを除去する |
-(UIRemoteNotificationType)enabledRemoteNotificationTypes | アプリケーションが受け入れる通知のタイプを返す
UIRemoteNotificationType(enum値)
UIRemoteNotificationTypeNone | 通知を受け付けない | |
UIRemoteNotificationTypeBadge | アプリケーションアイコンのバッジ |
UIRemoteNotificationTypeSound | 警告音通知 |
UIRemoteNotificationTypeAlert | 警告メッセージ |
|
-(BOOL)isIgnoringInteractionEvents | レシーバーが画面タッチによって始められるイベントを無視しているかどうか |
-(void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)types |
Apple Push Serviceを通してプロバイダーから指定されたタイプ通知書を受け取るために登録する |
-(void)unregisterForRemoteNotifications | Apple Push Serviceからの通知を登録解除する |
-(BOOL)sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent*)event | targetにactionメッセージを送る |
-(void)sendEvent:(UIEvent *)event | アプリケーション内の適切なレスポンダーにイベントを送る |
-(void)setStatusBarHidden:(BOOL)hidden withAnimation:(UIStatusBarAnimation)animation |
ステータスバーを表示・非表示する
UIStatusBarAnimation(enum値)
UIStatusBarAnimationNone | アニメーションなし |
UIStatusBarAnimationFade | フェードイン・アウト |
UIStatusBarAnimationSlide | スライドイン・アウト |
|
-(void)setStatusBarOrientation:(UIInterfaceOrientation)interfaceOrientation animated:(BOOL)animated |
ステータスバーの方向を設定する |
-(void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle animated:(BOOL)animated |
ステータスバーの形状を設定する |
ということで、iOS6でのAppDelegate.mの基本構造は以下のようになる(私が使っている定型)。
#import "AppDelegate.h"
// iOS6のiPhoneで倒立のPortraitがうまく回転しないのを回避するための処理
@implementation NavigationControllerForiOS6
- (NSUInteger)supportedInterfaceOrientations
{
return supportedInterfaceOrientationsByMain();
}
- (BOOL)shouldAutorotate
{
return shouldAutorotateByMain();
}
@end
@implementation AppDelegate
@synthesize window;
@synthesize navigationController;
@synthesize rootViewController;
@synthesize setup;
-(void)releaseResouces
// バックグラウンドに入るときに開放して良いリソースの開放
{
NSLog(@"releaseResouces");
~
[setup release];
[navigationController release];
}
-(void)reloadResouces
// リソースを読み直す
// バッググラウンドからの復帰時にも読みなおす
// ここに来たときにはmainViewとその中に含まれるrootViewは読み込み済みである
{
NSLog(@"reloadResouces");
~
// setupの読み出し;表示への反映は後で(ここで行っても反映されない)
// 以下の初期化処理の中で参照されるのでここで先に読み込む
setup=[[Setup alloc]init];
// NavigationBarへルートとしての設定
navigationController=[[NavigationControllerForiOS6 alloc]initWithRootViewController:rootViewController];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
// ファイル受け渡し起動時は、この後にopenURLが呼び出される
{
// リソースの読み込み
[self reloadResouces];
// 主画面表示
NSLog(@"主画面表示");
[window setRootViewController:navigationController];
[window makeKeyAndVisible];
return YES; // 画面が表示されるのはこの後
}
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
// UIDocumentInteractionControllerでのファイル共有受信用
// すでに起動中の時はこれだけ呼び出される
{
return [rootViewController importBasicFile:url];
}
//-------------------------------------------
-(void)applicationEnd
// アプリ終了処理
{
NSLog(@"applicationEnd");
// 各種停止処理
[setup saveSetup]; // setupの保存と言うよりスクロール位置の保存
}
- (void)applicationWillTerminate:(UIApplication *)application
// アプリケーションが本当に終了するとき
// iOS4では通常はHOMEボタンを押してもここには来ない
// UIApplicationExitsOnSuspend=YESの時に来る(サスペンド不可設定時)
{
NSLog(@"プログラム終了");
[self applicationEnd];
}
- (void)applicationWillResignActive:(UIApplication *)application
// アプリケーションが非動作になるとき
// iOS4ではHOMEボタンを押すとここに来る
// UIApplicationExitsOnSuspend=NOの時に来る(サスペンド可設定時)
{
NSLog(@"プログラム非動作");
fnonActive=YES; // nonActiveになる
[self applicationEnd];
NSLog(@"プログラム非動作化終了");
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
NSLog(@"プログラム再アクティブ");
if (!fnonActive) {
// 起動時に、applicationWillResignActiveが呼ばれてないのに此処に来ることがあるので回避
NSLog(@"→回避");
return;
}
// マルチタスクで外部で設定が変更されているかもしれないので、読み込んでおく
EnterRunLoop(0.0); // これがないと、「何故か」直前の「設定」での変更が反映されない
~ // 外部SETUP読み込み
}
//-------------------------------------------------------------------
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window_
// iOS6
// 画面回転を許可するために呼び出される・・・ようである
// 個別のUIViewControllerがsupportedInterfaceOrientationsを持ってないときはこれを呼び出すらしい
{
// NSLog(@"application.supportedInterfaceOrientationsForWindow:window=%@",window_);
return ~;
}
//-------------------------------------------------------------------
- (void)applicationDidEnterBackground:(UIApplication *)application
// アプリケーションがバックグラウンドに入った
{
NSLog(@"applicationDidEnterBackground");
}
- (void)applicationWillEnterForeground:(UIApplication *)application
// アプリケーションはフォアグラウンドに入る
{
NSLog(@"applicationWillEnterForeground");
}
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
NSLog(@"メモリ不足:applicationDidReceiveMemoryWarning");
}
- (void)dealloc
{
[self releaseResouces];
[super dealloc];
}
@end
UILocalNotification
UILocalNotificationはiOS4.0で追加された機能で、アプリケーションに通知する機能を強化する(特に周期起動に関する機能)。
UILocalNotificationのインスタンスは、アプリケーションが特定の日付と時間をユーザーに知らせる予定をすることができる通知機能を提供する。
オペレーティングシステムは、通知を適当な時刻に届ける。その時アプリケーションは動作している必要はない。
ローカル通知は、主にタイマーによる単純なカレンダーやTo-Doリストアプリケーションを目的とする。
UILocalNotification
プロパティ名 | 属性 | 内容 |
NSDate *fireDate | C | システムが通知を発送する日時 |
NSString *alertAction | C | アクションボタンまたはスライダーのタイトル文字列 |
NSString *alertBody | C | 警告通知で表示されるメッセージ |
NSString *alertLaunchImage | C | ユーザーがアクションボタンを軽くたたくまたはスライダーをスライドするとき、
起動イメージとして使われるイ画像のファイル名を返す
|
NSInteger applicationIconBadgeNumber | | アプリケーションアイコンのバッジの表示する番号(デフォルト=0;変更なし) |
BOOL hasAction | | 通知がアラートアクションを表示するか否か |
NSCalendar *repeatCalendar | C | 繰り返し通知するときにシステムが参照するカレンダー |
NSCalendarUnit repeatInterval | | 繰り返し通知の周期 |
NSString *soundName | C | 表示されるときに再生される音声ファイル名 |
NSTimeZone *timeZone | C | fireDateのタイムゾーン |
NSDictionary *userInfo | C | 通知されたアプリケーション付加するユーザー情報 |
UIDocumentInteractionController
UIDocumentInteractionControllerは、アプリケーション間でファイルの受け渡しをするために使うクラス、らしい。
詳しくは
ここに紹介があるので読んでもらうとして、
ここでは、独自の拡張子のファイルを受け取る方法のみ説明する。
渡されるアプリケーション側で用意するのは、
- DocumentTypeとExported UTIs
- 受信処理
の2つだけである。受信処理はUIApplicationの
application: openURL:~だけであり、
適当な受信処理(たとえばファイル読み込み)をそこに書くだけで良い。
実際にアプリケーションがどのファイルを受信出来るかと言うことをOSに知らせるのが「DocumentType」「Exported UTIs」の設定である。
ここに適切な設定をしておくと、「ファイルの出力をサポートしたアプリケーション」、一番わかりやすいのは
「メール」でファイルのアイコンをタップすると、出力先としてこのアプリケーションが表示されるようになる。
「DocumentType」は、定義済みのファイルを割り付ける部分である。
Name | 内容 | 単なる説明文 |
Types | 識別子 | 対応するファイル形式 |
Icon | アイコン | ここ参照 |
Typesで指定するファイル形式については
ここに詳細があるがちとわかりにくい。
表の「Identifer」または「Confirms To」を','で区切って羅列する。
どちらでも良いが、後者の方がより幅広いファイルに対応してくれる。
拡張子の大文字小文字は区別されない(両方に対応する)。
なお、「Types」にはpublic.jpegおよびpublic.pngは指定出来ない(他の画像系ファイルもだめかも)。というか、指定しても無視される。
少なくともメールでは設定が無視された。
iOS側で自動設定しているのかもしれない。public.audioは問題ない。
独自の拡張子を持つファイルをサポートさせる場合は、まず「DocumentType」にTypesとして独自の形式名を設定する。

さらに、「Exported UTIs」に、それによって受信するファイルの情報を設定する。
受信であるにもかかわらず「Exported」という名前なのでややこしいが、OSに対して知らせておく=出力しておくという意味なのだろう。
Description | 内容 | 単なる説明文 |
Identifer | 識別子 | DocumentTypeで指定したTypesを記入する |
Confirms To | ファイル形式 |
SmallIcon | 小アイコン | ここ参照 |
LargeIcon | 大アイコン | ここ参照 |
Additional exported UTI properties | 追加属性情報 |
独自の拡張子を持ったファイルをサポートするときは、ここの設定が必要になる。
UTTypeReferenceURL | そのファイルについて説明しているURL | アプリのサポートURLを書いとけば良いと思う |
UTTypeTagSpecification | 拡張子情報辞書
public.filename-extension | 拡張子名群 |
|
|
「Confirms To」には、設定するファイルを含む形式を指定する。指定仕方はTypesと同じ。
拡張子群には、対応させる拡張子を記述する。ここでも大文字小文字は区別されない。
アイコンについては、サイズの他、自動的に掛けられる効果の考慮も必要なので、
基本的には指定せずにOSに任せた方が良さそうである。
他のアイコン画像から自動的に作ってくれるようである。
これで外部アプリケーションからファイルの受信が可能になる。
この方法では同時に1つしかファイルが渡せないが、それについては他の共有方法を使うか、
X-BASIC'(X-BASIC for iOS)の場合はZipファイルを使って渡すことで解決している。
なお、アップルではスクリプトも含め実行形式のファイルのインポートを一切認めない(その機能があると審査で拒絶される)。
ZIPの中に入れてもだめである。
実装時はデータファイルのみインポートするようにしなければならない。