InterfaceBuilderでUILabelのtextを複数行に


コードで書くときはUILabelのnumberOfLinesを増やしてテキストに\nを書いてやれば複数行にできたのですが、InterfaceBuilderのtext項目には\nを入れても、そのまま表示されるだけで改行してくれなかった。

やり方がこちらに載っていたのでメモ。
チーズくんの備忘録 [iOS]InterfaceBuilderを使って、UILabelを複数行にする方法

Linesを0にするというのはやってみたのだけど、option+returnで改行されるとは知りませんでした。
shift+returnとかは試してみたんだけど、、、。
macでは結構optionボタンを使うのね。

そういえば \n のバックスラッシュを入力するときも option+¥ だしね。

UIbutton上の画像を右寄せ

UIButtonにイメージを貼り付け、横サイズ280に固定したかったのですが、
イメージが中寄せになるので困っていました。

いろいろ試してみるとこれで右寄せすることができました。


UIButton * button = [[UIButton alloc] init];
[button setImage:img forState:UIControlStateNormal];
button.frame = CGRectMake(10,10,280,img.size.height);
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;

performselectorで実行を遅らせる

iOSアプリ開発の話です。

テスト用のアプリで基本的な動きを学びながら、分かったところで本命アプリに組み込むなんて方法で開発しているのですが、ちょっと複雑にするとすぐ問題が出てきます。
今日発生した問題は画面遷移中に落ちてしまうという問題。

A.「ボタンをタップすると0.3秒のアニメーションがあって、アニメーション後に画面を書き換える」という処理と、
B.「0.1秒毎にtimerを動かしていて、指定した時間が過ぎると時間切れで画面遷移する」という処理があったのですが、
時間切れギリギリにボタンをタップすると、画面遷移のためにviewWillDisappearで変数をnil化した後にAの画面書き換え処理が動いてしまって、nil化した変数にアクセスしてしまい例外が発生していました。

これ、どうしようかと思いましてまずは画面書き換え処理の前にフラグを立てて、処理終了後にフラグを下ろす。フラグが上がっている間は画面遷移せずに待つ。
という方法にしてみました。

一定時間実行を遅らせるために使ったのはこれ。

[NSThread sleepForTimeInterval:0.5];

これで0.5秒待つ。フラグが下りてなかったら再度待つ。5秒待ってもフラグが下りなければ画面遷移強行。ってやってみたのですが、確かにスリープはしていますが、それでもタイミングによっては落ちます。

このsleepForTimeIntervalってのは画面遷移の時間を遅らせると同時に、画面書き換えの処理も止めちゃってますよね?
これじゃ意味ない。

ってわけで次は performselector ってのを使ってみます。

[self performSelector:@selector(OpenNext) withObject:nil afterDelay:0.5];

これで OpenNext という関数を0.5秒後に実行してくれます。
スリープしているわけではないのでその間に画面書き換えの処理は動いて完了してる(っぽい)。

これでどうにか落ちることはなくなりました。

file was built for unsupported file format which is not the architecture being linked (i386)

iADというiPhone/iPad向けの広告を試しに入れてみようと試行錯誤しているのですが、表題のエラーが出ました。

iAD関連のライブラリが不適切なんだろうと思ったのですが、よくわからない。
調べてみると、同じような症状の人がいました。

objective c – Sending email in an iPhone application – Stack Overflow

どうやらiAd.frameworkの追加の仕方が悪かった模様です。
左側にある[project navigator]の中に、Finderから直接iAd.frameworkのフォルダをドラッグアンドドロップしていたのですが、これが間違いらしい。

正しいフレームワークの追加方法は、[project navigator]の一番上のプロジェクト名のところをクリック。
[TARGETS]を選択し、一番上の[Build Phase]を選択。
[Link Binary With Libraries]を選択し、そこの[+]マークからお目当てのフレームワークを追加する。

正しい方法で追加すると正常にビルドできました。
以前AVFoundation.frameworkとか追加したことがあったんだけど、偶然正しい方法で追加していたっぽいなぁ。

Macのgimpが使いにくい


アプリ作ってるとどうしても画像編集する必要がでてきます。
Photoshopとかillustratorとか使っている人が多いんでしょうが、あれって8万とか9万とかするみたいだし。
趣味への投資額としてはちょっと、、、考え込んでしまうくらいの価格です。

windowsでは簡単な画像の加工にはペイントを使って、年賀状用の画像とかちょっと面倒な加工をするときにはgimpを使っていました。
そんなわけでMacにもgimpを入れるには入れたのですが、これが使いにくい。

どこがどうなって使いにくいのかよく分からず、なんだか使いにくいなぁという印象だったのですが、さすがに肩が凝ってきましてgoogle先生に解決策を聞いてみました。
すると、多くの人が不満に思っている点は、ツールボックスのウィンドウと画像ウィンドウをわざわざクリックしてやらないとフォーカスが当たらない点。

言われてみると確かにそうなんです。
画像に色をつけて、その後ツールボックスの「矩形選択ボタン」を押したつもりが1回目のクリックではツールボックスウィンドウにフォーカスが移動しただけ。もう一度クリックしてやっと「矩形選択ボタン」が押されたことになります。
その後、画像ウィンドウで矩形選択しようとしますが、1回目のクリックは画像ウィンドウにフォーカスを移動させるだけ。2回目のクリックでようやく矩形選択ができるようになります。

これだったのか何か使いづらいと思っていたのは。
指摘されるまで気づかないとは。

で、解決策ですが、検索した結果、ターミナルを開いて

defaults write com.apple.x11 wm_ffm -bool true

と打ってX11を再起動すれば解決できるそうなんですが、なぜかウチでは上手くいかず。

なんか方法があるだろうと思ったら、gimpを起動したときの最上部のX11のツールバーに「X11」→「環境設定」という項目が!
この「X11の環境設定」の中の「ウィンドウ」の中に「フォーカスをマウスと一緒に移動」という項目があります。
ここにチェックを入れてX11を再起動すると、めでたく期待通りの動作をするようになりました。

これで少しは使いやすくなるはず。

あとはテキストに日本語を入れるときに、テキストエディタなどからわざわざコピペしてやらないといけないってのが解決できればなぁ。

NSTimerでアニメーション


一週間以上アニメーションのことで悩んでいました。

UIImageViewを画面を表示している間ずっと点滅させたい、やりたかったのはただこれだけなのですが。

ちょっと調べて最初に書いたコードはこんな感じ。

[UIView animateWithDuration:1.0
  delay:0.0
  options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat
  animations:^{ flashIV.alpha = 0.0; }
  completion:nil
];

flashIVの透明度を1秒かけて1→0へ。その後UIViewAnimationOptionAutoreverseの効果で透明度は再び1秒かけて0→1へ戻る。
UIViewAnimationOptionRepeatを指定しているので、これが延々と繰り返すというもの。

これはこれでちゃんと動いていたのですが、ちょっと問題が。
続きを読む

iOSアプリ 効果音の再生


効果音の再生方法です。

あちこちで調べてAppleのドキュメントなんかも眺めて難しそうだなぁと思っていたのですが、実際にコードを書いてみると、、、難しいことをやろうとしなければ意外とやることは単純かな。

こちらのサイト様を主に参考にさせていただきました。

iOS で効果音を鳴らしたい | どうも。わたすがダニーです。
効果音を鳴らす « iPhoneアプリ練習帳

それでなんとか効果音を鳴らすことまではできたのですが、、、
問題があって、ボタンを連打して前の音が鳴り終わっていないときに次の音を鳴らそうとすると鳴らない。

再生用のメソッド作ってその中で

// (playerは AVAudioPlayer *ということで)
if([player isPlaying]){
  [player stop];
}
[player play];

とかやってみたのですが、どうも効果がない。

音ファイルの再生時間をできるだけ短くしたりしてなんとか我慢していたのですが、今日こちらのサイトを見つけて解決しました。

C開発者によるiPhoneプログラミング: サウンドの連続再生

stopを使わずに、強制的にcurrentTimeを0に巻き戻してあげてからもう一度再生すればいいのか〜。
こんな感じに。

[player setCurrentTime:0];
[player play];

参考になりました。
感謝。

safari ボタン一つでリンクタグを作成


こうしてブログを書いていると、他のサイトさんへのリンクを作成する機会って非常に多いんですが、リンク先のURLをコピーして、ページのタイトルやサイトのタイトルを調べてって作業が地味にめんどくさい。

で、他の調べものをしているときに便利なブックマークレットを公開して下さっている方がいたので紹介。

SS | 今Safariで見ているページのリンクタグを作るブックマークレット

今までコピーペースト、コピーペーストってやっていた作業がボタン一つでできるようになりました。

感謝。

ところで、このとき調べていたメインの課題というのが、safariのタブ表示が非常に使いづらくなんとか解決したいというもの。
今safariを全画面表示するとタブが13個までは横並びに表示されていて、それ移行は >> こんなボタンを押して選ばないといけない。
なにか便利な方法はないものかと思ったのです。

なんかいろいろツールを入れればタブを左側に表示したりできるそうなのですが、そんなにがんばるほどには困ってないかも。

これを書いているうちに、13個もタブが開ければ十分な気もしてきましたし。
「お、これ便利そう」とか「ちょっと気になるから後で読もう」とか「ブックマークするほどではないけど一応使うかも」というようなページなんかを開いていたらあっという間に13個を超えてしまうので、リーディングリストをもっと有効活用しようかな。

iOS Developer Library 日本語訳


こんな便利なドキュメントが用意されていたとは・・・。
無知とは恐ろしいものです。

iOS Developer Library
https://developer.apple.com/jp/devcenter/ios/library/japanese.html

UIImageの連結


UIImageを横に連結して新しいUIImageを作るメソッドを作りました。
といってもほとんどこちらのサイト様のコピペです。
UIImageの合成 – Horigoodの日記 – iPhoneアプリ開発グループ

コピペで動かなかった部分は書き換えています。


+ (UIImage *)concatImages:(UIImage *)imgA :(UIImage *)imgB
{
	int widthA = CGImageGetWidth(imgA.CGImage);
	int widthB = CGImageGetWidth(imgB.CGImage);
	int height = CGImageGetHeight(imgA.CGImage);

	int widthC = widthA + widthB;
	unsigned char *bitmap = calloc(widthC * height * 4, sizeof(unsigned char));
	CGContextRef bitmapContext = CGBitmapContextCreate(bitmap,
						   	widthC,
						   	height,
						   	8,
						   	widthC * 4,
						   	CGColorSpaceCreateDeviceRGB(),
						   	kCGImageAlphaPremultipliedFirst);

	//imgAをbitmapContextに描画
	CGContextDrawImage(bitmapContext, CGRectMake(0, 0, widthA, height), imgA.CGImage);

	//imgBをimgAの隣に描画
	CGContextDrawImage(bitmapContext, CGRectMake(widthA, 0, widthB, height), imgB.CGImage);

	//CGContextからCGImageを作成
	CGImageRef imgRef = CGBitmapContextCreateImage (bitmapContext);

	//CGImageからUIImageを作成
	UIImage *imgC = [UIImage imageWithCGImage:imgRef];

	//bitmapを解放
	free(bitmap);
	
	return imgC;
}

大部分がコピペなのできちんと理解できているか不安です。
間違いとかに気づかれた方いらっしゃいましたらコメントお願いします。