<application-home>----AppName.app | | ----Documents | | | ----・・・ | ----Library | | | ----Preferences | | | ----Caches | ----tmp
また、XcodeプロジェクトのResourcesグループに登録した画像やサウンドファイル(内部利用)は、この各アプリケーションパッケージ内に保存されている。
textFieldShouldReturn のような Cocoa Touchフレームワーク上での、テキストフィールドの処理を委譲するためのプロトコル[UITextFieldDelegate]を利用するには、対象クラスに下記の指定が必要。
@interface TestViewController : UIViewController <UITextFieldDelegate>
そうすることで、InterfaceBuilder上のInspectorのConnectionタグの一番下の項目にReferencing Outletsというエリアに、New Referencing Outlet というリンクできる機能があるので、そこからtextFieldにD&Dすることで、delegateを選択することができ、便利なイベント呼び出しを利用できる。textFieldShouldReturnの場合はtextFieldのFocusが外れた場合など。
UITableViewControllerのviewWillAppear:メソッドでは、まだデータがロードされていない状態の時にのみ、reloadDataが呼び出される。そのため、オーバライドする場合には[super viewWillAppear:animated];はメソッド最後に呼び出すようにする。
Viewを切り替えて使うようなアプリケーションで切り替え時にUIの値を変更したい時はviewWillAppearでやらなければならないが、メモリ不足などでviewDidUnloadなどが行われた場合には、view表示を行った場合、再度viewDidLoadが呼び出される。このことはviewUnloadで正しくメモリ解放が行われない場合、2重でメモリを確保(メモリリーク)することになる。
(注)loadViewでxibがアプリに読み込まれた以降に、UIパーツの値変更が可能
すべてのクラスはUIViewからの継承であるため、frameプロパティが存在する。インスタンスを作成後、必ずこのプロパティを表示しないと画面にview等が表示されないので気をつけること。
XcodeのClassの中にアプリケーション名+AppDelegate.mというファイルがある。その中を以下のように編集してみる。
-(void) applicationDidFinishLaunching:(UIApplication *) application { CGRect rect = [window frame]; // windowサイズの取得 UILabel* label = [[UILabel alloc] initWithFrame:rect]; // 大きさ(rect)を指定してラベルの作成 label.text = @"Hello new World"; // ラベルにテキストを設定 [window addSubview:label]; // ウィンドウにラベルオブジェクトを追加 [label release]; // ラベル変数を解放 [window makeKeyAndVisible]; // }
UIApplicationMain(argc, argv, nil, @"myAppDelegate");一番後ろのmyAppDelegateが、呼び出しを行う最初のクラスになる。
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]
uiview.frame.origin.x // uiview.frame.origin.y uiview.frame.size.width uiview.frame.size.height
注意点としては、frame.sizeとbounds.sizeは基本的に同じサイズになるが、自分自身が親の座標からはみ出ている場合には、このサイズは変更される。(と思われる)
下記のような実装において、autoreleaseでメモリ解放は問題がある。
- (void)viewDidLoad { UIViewController *vc = [UIViewController new] autorelease]; [self.view addSubview:vc.view]; }
具体的には、上記のようなイベント処理内で、サブコントローカーのvcを作成して、子供としてサブコントローラーのviewを登録するような場合、viewは登録されるものの、vcとして作成されたコントローラ部分は、viewDidLoad関数から出た時点で、autorelease設定により作成したインスタンスがメモリから解放されてしまい、touchesコマンドを受け取れない。そのため、UIViewControllerのクラスを親クラスと持つ独自のクラスを作成し利用する場合には、インスタンス作成時にautoreleaseを設定してはならない。クラス変数として確保し、deallocで解放させるようにする。
オブジェクトの生成は、2つに分けられる。1つは、allocしてオブジェクトを生成。もう一つは、クラスメソッドの内部で作成する。
例1)ユーザー管理型 UIView * view = [[UIView alloc] init];
例2)システム管理型 NSString * name = [NSString stringWithString:@"suzuki yamada"];
例2ではallocを行わず、stringWithStringメソッド内で領域を確保しているため、ユーザーがdeallocを行う必要がない([view release]は必要だが、[name release]はいらない)。逆にこの例2のような作成をしているオブジェクトに、releaseを実行すると、その場で落ちる。
オブジェクト定数
NSStringなどで、ソース中に定数として記述している場合
NSString * str = [NSString stringWithString:@"メッセージ"];
この場合、str.retainCountが「2147483647」という数字になる。これはオブジェクト定数(文字列定数)のため、解放不要というのを表す「NSIntegerのMAX値」が設定される規定の為。
NSError* error; NSString* contents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];ここのerrorの初期化を単純に忘れている。
下記のコマンドで自動プールの中を確認できる。
[NSAutoreleasePool showPools];
plistのBundle identifierの設定が間違えている場合に発生しやすいが、Emulatorをリセット後、再起動を行うと直る場合が多い。
残念なことにxcodeはかなりバグが多いIDEである。(3.2.4現在)上記のような場合、内部の設定問題をxcodeは自己解決できず、何をおこなっても2度と動かない。基本的には以下の手順で解決する。
これにより、xcode内部のプロジェクト情報が新規で作成され、上記のエラーから回復することができる。
アプリケーションにバインドされるファイルは、開発時に実機やシミュレーターなどにコピーされて、アプリケーションから利用されるが、このファイルがゴミのようにテスト機の中に残る場合がある。Simulatorであれば、メニューから設定のリセットを利用することで削除できるが、実機の場合はすべて工場出荷時に戻すという選択しかない。
Error launching remote program: failed to get the task for processが表示され、実機上で、アプリが起動せず実機でのデバッグができない場合は、Entitlement.plistが指定されている場合がある。例としては、AD-HOC用にdist.plistなどが指定されている。(厳密には、plitsの中の、get-task-allowのチェックがONになっている状況)
また他にも、ProvisioningFileのセットが、Distribution向けになっている場合も起動しない。そのため、Apple Develper Centerから、Development用のProvisioningFileを利用する。
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
理由は、AppleライブラリがPNGを読み込んで画像化する際に、アルファ値をすでに反映したRGBデータに変更しておくため。詳細はここのページを参照のこと。
これは、PowerVR系のチップが、タイルベースアーキテクチャを採用している唯一の弊害であり、対処するには、glTexSubImageなどのテクスチャーの一部書き換え処理回数を極力減らすように設計することだ。
Xcodeには初期設定として行っておくと便利な機能がある。
xcodeのウィンドウは他のIDEと違い、やたらとWindowsが表示される昔のタイプのUIを持っているが、xcode単体(プロジェクトは開かず)を立ち上げたときに、環境設定の中の全般タグの中のレイアウトを「オールインワン」にすることで多くのウィンドウを1つに纏めることができる。
xcodeにおけるsubversionの連動は一応できる。基本的な手順は以下の通り。
※注意、ファイルの追加やディレクトリの追加には注意が必要
TortoiseSVN的なSubversionクライアントが、ここのSubversionを作っている所から提供されている。残念なことに正式には、SnowLeopardには対応していないが、下記の設定を行うことで利用することが可能。
/Library/Contextual Menu Items/SCFinderPlugin.plugin
Contents/Resources/SCPluginUIDaemon
※注意、ファイル名やフォルダ名に日本語は使えない。フォルダの削除ができない。(snowで利用している場合)の2点が制約事項として存在する。
Warning: The バンドルリソースをコピー build phase contains this target's Info.plist file 'Info.plist'.この場合には、対象のInfo.plistを右クリックし、情報を見るから、ターゲットのタブの中にあるチェックをすべて外す。これによりplistをバンドルしなくなる。
Resources/MyProject_Prefix.pchフォルダの位置は、プロジェクトフォルダからの相対位置となる。
Xcodeでは、多言語対応するためのファイルを追加することで、多言語の対応を行うことができる。xcodeの左側のプロジェクト構造の中で、新規ファイルを選択し、Resourcesタグを選択することで、Strings Fileという種別のファイルをLocalizable.stringsという名前で作成することで対応可能である。
作成されたファイルを右クリックし「情報を見る」を選択すると、この中にファイルを「ローカライズ可能にする」というボタンがあるので、選択をすることで設定画面が表示される。設定後は、複数の言語ごとのテキスト設定ファイルが作成され、それぞれのテキストにラベルを編集できる。
Localizable.strings (Japanese) のファイルの中 "Label" = "ラベル";
このように設定することで、プログラム中では以下のように利用できる。
NSString * str = NSLocalizedString(@"Label",@"");
2つの引数の内、右の @"" はコメント用の文字列であり、設定の必要は特に無い。
※ローカライズを可能にする」ボタンを押すと、プロジェクトファイルの中には、English.lproj と Japanese.lproj という2つのフォルダが作成され、それぞれに先ほどのLocalizable.stringsというファイルが作成される。
Setting bundleの日本語化
システムの設定の所にアプリケーションの設定が行える情報を登録できる、setting bundleだが、en.lproj フォルダは作成されるものの、ja.lproj フォルダがxcodeから作成できない。そこでコマンドラインより、以下のコマンドを実行する。
cd Settings.bundle cp -r en.lproj ja.lproj
アプリ名の多言語化
基本的には、plistの多言語ファイルである「InfoPlist.strings」を作成する必要があるが、手順・ファイル名ともにシビアな為、下記の手順で追加してほしい。
CFBundleDisplayName = "アプリ表示名";
iPhoneとiPadは、同じようでかなり違う。解像度などの問題や外部ディスプレイ、またメモリ容量などいろいろな部分が違うために、両方で起動させるにはそれらをかなり意識して開発する必要がある。
アプリの開発方法には、2つのタイプがあり、1つはアプリをiPhone,iPadの両方で起動できるように内部に両方のリソースをバンドルし、起動時にそれらを切り替えて起動するようにする手法であるUniversalタイプと、ターゲットを2つ作成し別々のアプリとして作成する、Two Device-Specific Applicationの2つがある。
基本的にはiPhoneタイプでプロジェクトを構築し、xcodeの左側に表示されるプロジェクト構成のターゲット登録されている、1つのターゲットを右クリックすると「現在のターゲットをiPad用にアップグレード」という選択が表示される。これを選択することで、ダイヤログが表示され、ビルドタイプを選択できる。Universalタイプを作成したいときは左側のOne Universal Applicationを選択し、Two device-specific Applicationを作成した場合には、右を選択する。
※コンパイルやデバッグのターゲット変更は、xcodeのメニュー -> プロジェクト -> アクティブターゲットの設定、で変更する
その他のプロジェクトファイルの設定について
項目 | 値 | 説明 |
アーキテクチャ | Standard (armv6, armv7) | CPUのアーキテクチャを選択する、CPUにあわせた最適化設定などもある(下記のベースSDKを設定すると変化) |
ベースSDK | iPhone デバイス 4.1 | 稼働する基本SDKの選択、基本は最新のSDKバージョンとする |
項目 | 値 | 説明 |
iOS Deployment Target | iPhone OS 3.1.2 | 最終的にインストールされる機種の最低OSバージョン。基本的にSDK毎の差異で問題がなければ、なるべく低いバージョンにする |
古い環境には含まれていない Framework を利用している場合
実行時のDynamic Linkerがシンボルのロードに失敗してアプリケーションが起動しない。そのため、アプリの中に対象となるライブラリの同梱指示を行う。具体的には、Xcodeの左メニューのターゲットの対象ターゲットにおいて「バイナリをライブラリにリンク」の中にリストされている、古いframeworkの「役割」を、Required から weak に変更する。
IOSでは、アプリが起動するまでの黒画面のところで画像を表示しておくことができる。やることは簡単で、Default.png (ファイル名は固定)を、Resources フォルダに入れておくだけで、自動的にこのファイルをアプリ起動時に表示してくれる。
NSZombieEnabled
プロジェクトファイル内の実行可能ファイルをダブルクリックで、起動時の引数などを選択できる。ここで引数タブの下の段に、NSZombieEnabled YES と設定し、チェックを選択することで、システムからの呼び出しもエラー表記してくれるようになる。
これは特に、アプリが途中で突然落ちるときなどに効果を発揮する。
NSDebugEnabled
MallocStackLogging
MallocStackLoggingNoCompact
原因が分からない落ちバグにはいろいろあるが主な原因には以下のものがある。
基本的に、原因の分からない落ちバグはメモリ関係が多い。この場合にはgdbコマンドを利用してメモリのログを見ることで解決する場合もある。xcodeは基本的にgdbを利用しているため、落ちた後に(gdb)というプロンプトが出ている場合は、このプロンプトの後にコマンドを入力する。
例: (gdb) shell malloc_history 21331 0x9ea1a0
これは、プロセス番号21331番の、メモリ領域0x9ea1a0に関するメモリログを表示する機能となる。これにより、詳細なメモリ管理情報が取得できる。
IOSでは、設定アプリに自分用の設定項目を作ることができる。基本的には以下の手順で設定ファイルを作成し、xcodeに含めることで、設定アプリに自分の設定を増やすことができる。
Cocoaフレームワークにおける最上位に位置するクラス。すべてのオブジェクトの基礎となる。NSObjectのProtocalに関する説明はここ
ファイル管理における専用クラス
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(handleTimer:) userInfo:nil repeats:YES];ここでは、repeatsをYESにしているので、2秒毎にHandleTimerメソッドが呼び出される。呼び出される方のコードは以下の通り。
- (void) handleTimer:(NSTimer *)timer { NSLog(@"@%@ : [%s]", [self class], _cmd); }通常はここで再描画の処理や必要な機能を呼び出す。
タイマー時間を計算するクラス
NSDate *startTime = [NSDate date]; // 処理 NSTimeInterval elapsedTime = [startTime timeIntervalSinceNow];
これで処理の時間を計ることができる。
メモリ確保の方法により生存期間が違う。
NSMutableArray *ma; [[ma alloc]init]; // ローカル外でaddObjectできる。 [ma array]; // ローカル外でaddObjectできない。
これは他項で説明している所有権に関わる問題である。
文字データのフォーマットがUnicodeであることから、NSStringには下記の5種類の改行コードを使用することが認められている。通常はLFを利用。
複数の改行コードに対応しているのはいいが、問題はこれらのコードがひとつのNSStringインスタンスに共存可能だということだ。Windows/DOSならCR-LF、Unix系ならLF、旧MacOSならCRとなっている。
その他
コード | 役割 |
\t | 水平タブ |
\" | 二重引用符 |
\\ | \自身 |
NSString * text = [NSString stringWithFormat:@"文字列:%@, intの数 = %d", @"中身", 10];
NSRange range = [textString rangeOfString:@"COCO"];
NSString * newString = [oldString stringByReplacingOccurrencesOfString:@"OLDTEXT" withString:@"NEWTEXT"];
NSString * newStr = [longText substringFromIndex:5];
NSString * newString = [NSString stringWithUTF8String:oldString];
主にスクリーン情報を取得するための特殊なクラス。下記のような手順で画面の大きさなどを取得する。
frame = [[UIScreen mainScreen] applicationFrame]; // StatusBarを除いたスクリーン領域 bounds = [[UIScreen mainScreen] bounds]; // スクリーンの大きさを取得 scale = [[UIScreen mainScreen] scale]; // 画面の拡大率(iPhone3GやiPhone4などは解像度が違うため)
ほとんど利用されないが、iPad以降では外部スクリーンを管理できるようになったので、以下のような要領でスクリーン状態を確認できる。
NSLog( @"screenCount = %d", [[UIScreen screens] count]);
for( UIScreen * sc in [UIScreen screens] ){ screenFrame = [sc bounds]; }
NSLog( @"width = %d", image.size.width );
image = [UIImage imageNamed:@"playIcon.png"]; // 指定のリソースを読み込む
image = [UIImage imageWithContentsOfFile:@"/User/temp/background_bg.jpg"];
大きな画像を表示させ、スクロールさせたりするための専用view。
Bundleについて、一度ここを読み必要がある。
iPhone Simulatorでは、実機と同じように2本の指によるピンチなどの操作も行うことができる。
iPhoneの操作名 | PCでのマウス操作手順 |
タップ | 左クリック |
タッチホールド | 左クリックし押したまま |
ダブルタップ | 左ダブルクリック |
スワイプ | 1.マウスを指定の位置に移動し左クリック |
2.左クリックは押したまま | |
3.マウスを好きな方向に移動してから左クリックを離す | |
フリック | 1.マウスを指定の位置に移動し左クリック |
2.左クリックは押したまま | |
3.マウスを好きな方向に、素早く移動し、途中で左クリックを離す | |
ドラッグ | スワイプと操作は同じ。アイコンを選んでいるかどうかの違い |
ピンチ | 1.Optionキーを押したままにする |
2.希望位置に左クリックを行い円を表示させ | |
3.マウスを移動させピンチ幅を調整してから左クリックを離す |
利用のための初期設定
iPhoneの着信音は *.caf という変わった拡張子を利用した、*.aiff (osxのサウンド形式)ファイルであり、拡張子をリネームしたものである。通常は aiff 形式にファイルを拡張子cafに変更するだけで利用可能。
着信音は、40秒以内のAACデータで構成される。m4rは、m4aファイルの拡張子を変更したものであり、作成は容易である。
# afconvert -hf
#import <QuartzCore/QuartzCore.h> [[view layer] setBorderColor:[[UIColor blueColor] CGColor]]; [[view layer] setBorderWidth:2.0];
[[view layer] setCornerRadius:15.0]; [view setClipsToBounds:YES];
改行の削除 NSString *repWord = [[text componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:@""];
※IBの場合は必要がない可能性あり。
UIImage *pushImage = button.imageView.image; UIImage *stretchImage2 = [pushImage stretchableImageWithLeftCapWidth:12 topCapHeight:12]; [button setBackgroundImage:stretchImage2 forState:UIControlStateHighlighted];
UITextField *textField; textField.keyboardAppearance = UIKeyboardAppearanceAlert; (黒の半透明のキーボード) textField.keyboardAppearance = UIKeyboardAppearanceDefault; (通常)
[textView resignFirstResponder]; (フォーカス消す。他にtextViewなければ、キーボード消える) [textView becomeFirstResponder]; (キーボード出現)
iPadやiPhoneでは、アイコンの種類が何種類か準備し、アプリにバンドルする必要がある。
機種 | 解像度 | ファイル名 |
iPad | 72 * 72px | Icon-72.png |
50 * 50px | Icon-Small-50.png | |
768 * 1004px | Default-Portrait.png | |
1024 * 748px | Default-Landscape.png | |
iPad(Retina) | 144 * 144px | Icon-72@2x.png |
100 * 100px | Icon-Small-50@2x.png | |
1536 * 2008px | Default-Portrait@2x.png | |
2048 * 1496px | Default-Landscape@2x.png | |
パソコン用 | 512 * 512px(png, jpg共にOK) | iTunesArtwrok |
ここではコーディングやデバッグに便利な記述やテクニックを紹介する。
通常、NSLogなどを利用してプログラムのトレースなどを行い場合、以下の行をコピーし、メソッドの先頭に入れておくことで、クラス名・メソッド名を表示できる。
NSLog(@"@%@ : [%s]", [self class], _cmd);
NSArrayなどのオブジェクト型の配列には、通常、プリミティブ型のデータを入れることができない、これはオブジェクト型はすべてNSObjectからの派生で作られているため、オブジェクト管理メソッドおよびプロパティを、プリミティブ型は持たないためである。そこで以下の形でNSValueやNSNumberというオブジェクト型に変換して利用する。
領域などの構造体系
NSValue * val = [NSValue valueWithCGPoint:(CGPoint)point]; NSValue * val = [NSValue valueWithCGSize:(CGSize)size]; NSValue * val = [NSValue valueWithCGRect:(CGRect)rect]; NSValue * val = [NSValue valueWithCGAffineTransform:(CGAffineTransform)transform];
数字など
NSNumber * num = [NSNumber numberWithInt:(int)value]; NSNumber * num = [NSNumber numberWithUnsignedInt:(unsigned int)value]; NSNumber * num = [NSNumber numberWithLong:(long)value]; NSNumber * num = [NSNumber numberWithFloat:(float)value]; NSNumber * num = [NSNumber numberWithDouble:(double)value]; NSNumber * num = [NSNumber numberWithBool:(BOOL)value];
iPhoneによるマルチスレッドは、メソッドの呼び出し時にそのフロントスレッドではなく、バックスレッド処理を行う設定ができる。
[self performSelectorInBackground:@selector(backGroundProcess:) withObject:arg];
たとえばこれは自分のクラス内のbackGroundProcessというメソットを、バックスレッドで処理させるように指示を出す。簡単で便利ではあるが2つの大きな注意事項がある。
[self performSelectorOnMainThread:@selector(uiDraw:) withObject:arg waitUntilDone:NO];
// 自動メモリ管理登録 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// 自動メモリ管理解放 [pool release];
アイコンのサイズ
iOS7 | size | iOS | size |
Icon.png | 60px | Icon.png | 57px |
Icon@2x.png | 120px | Icon@2x.png | 114px |
Icon-40.png | 40px | - | - |
Icon-40@2x.png | 80px | - | - |
Icon-72.png | 〃 | Icon-72.png | 72px |
Icon-72@2x.png | 〃 | Icon-72@2x.png | 144px |
Icon-76.png | 76px | - | - |
Icon-76@2x.png | 152px | - | - |
Icon-Small.png | 〃 | Icon-Small.png | 29px |
Icon-Small@2x.png | 〃 | Icon-Small@2x.png | 58px |
- | - | Icon-Small-50.png | 50px |
- | - | Icon-Small-50@2x.png | 100px |
iTunesArtwork.png | 〃 | iTunesArtwork.png | 512px |
iTunesArtwork@2x.png | 〃 | iTunesArtwork@2x.png | 1024px |
atomicにするとロック機構が働くためnonatomicより10倍程度遅くなる。マルチスレッドでアクセスするならatomicにする。nonatomicなプロパティにメインスレッド以外からアクセスすることもできるがデータが破壊される可能性があるため、無理矢理使うなら@synchronizedなど、他のアクセス制御の仕組みが必要。
http://www.atmarkit.co.jp/fwcr/design/tool/iphonesdk03/02.html
http://allseeing-i.com/ASIHTTPRequest/How-to-use
sudo port -v selfupdate // 自分自身の更新 sudo port install git-core gnupg // git のインストール curl http://android.git.kernel.org/repo > repo // repoコマンドの取得「.bash_profile」に追加
export PATH=/opt/local/bin:/opt/local/sbin/:$PATH export MANPATH=/opt/local/man:$MANPATH
iPhoneやiPadではアプリケーションのアイコン登録が必須であり、app.plistの中に、CFBundleIconFiles というフォルダを作成し、機種毎に最適化した複数のアイコンを登録する必要がある。詳しくはリンクを参照。注意:アイコンファイルの最初の文字は必ず大文字にする
※また、iTunes用の512x512の巨大なアイコンは、plistに登録するのではなく、プロジェクト直下(ResourcesやClassなどと同じレベル)に、.png の拡張子を消した「iTunesArtwork」というファイル名で登録する。