MAC上で動くデスクトップアプリを作ろうと思った。
実は、初めての試みだった。
そして、案の定色々ハマったので、その備忘録をしておく。
今回は、Windowsデスクトップアプリと同じだと思っているとハマる点の備忘録
○アプリケーションの閉じるボタン=アプリの終了ではない
これは、実際に試してみればわかるのだが、デフォのままアプリを実行した場合、閉じるボタンを押してもアプリが画面下部バーに残り続ける。
これを解決するには、AppDelegate.mに下記処理を追加する。
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender { return YES; }
これを書けば、閉じるボタンを押せば画面下部バーからも消えてくれる。
○DS_STOREファイルは、MAC上では可視化できないが、プログラム上でファイル検索すると、リストアップに含まれる
MAC上では、DS_STOREファイルは可視化できず操作もできないらしいので、
DS_STOREファイルを無視するような処理を入れる必要がある。
○外部ファイルアクセスができない?
APP内に含めている(=バンドル化されている)リソースへのアクセスは容易だが、外部データへのアクセスは難しいようだった。
例えば、
// バンドルに含まれている物の読み込み NSString *path = [[NSBundle mainBundle] pathForResource:@"SoundName" ofType:@"mp3"]; NSURL* url = [NSURL fileURLWithPath:path]; [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
これなら読み込めるのだが、
NSString *path = @"/Users/UserName/Desktop/Res/Sound.mp3"; NSFileManager *filemanager = [ NSFileManager defaultManager]; BOOL isDir = NO; //ディレクトリの確認 if([filemanager fileExistsAtPath:path isDirectory:&isDir]){ if( isDir == YES ){ printf("ディレクトリです。n"); }else{ // ファイルの存在確認はできる printf("ファイルです。n"); } } NSURL* url = [NSURL fileURLWithPath:path]; [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
とすると、権限が無い的なエラーが出て読み込みに失敗する。
新しいOSでは、アクセス権限的な物をフォルダに付与する事も可能らしいが、 それを、配布するユーザー毎に毎回お願いするのもおかしいので、外部ファイルへのアクセスという考え方は、やめたほうが良さそうだ。
○じゃぁ、リソースの変更はどうやる?
実は、APPアプリを右クリックして「パッケージの内容を表示」をすると、バンドルに含めたリソースがそのまんま入っている。
そして、うまくいく読み込みのパスは、このリソースまでのパスである。
つまり、この中身を入れ替えてしまえば、対応可能だったりする(実証済み)
○作ったアプリを他人の環境で実行するときは、右クリ→開くをする必要がある
許可が下りていないところからダウンロードされたアプリは、実行に権限を付与する必要があるらしい。
で、それは右クリ→開くで可能になるようだ。
○データをセーブする時
こんな感じで、簡単に実装できるようだ。
ただ、どこに保存されるのかまでは、よく調べていない。
// 保存 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; [ud setInteger:100 forKey:@"Volume1"]; [ud synchronize]; // 読み込み NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; long volume1 = [ud integerForKey:@"Volume1"];
○アプリ終了時のイベントフック
データをセーブするタイミングは、アプリ終了時とかで自動で保存したいデータもあると思う。
そういう場合は、AppDelegate.mにこんな感じで書いておくといい。
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // 終了時に保存するための処理 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; [nc addObserver:self selector:@selector(OnEndCallback) name:NSApplicationWillTerminateNotification object:nil]; } -(void)OnEndCallback{ printf("end"); }