UIAlertController に入力フィールドをつける、textField.delegate = self で警告・・・

UIAlertController に入力フィールドをつける方法がわからなくて調べたところ、わかりました。UIAlertController のインスタンスを生成し、

    [alertController addTextFieldWithConfigurationHandler:^(UITextField* textField)

のような感じでした。簡単ですね。

次に、入力された値を取り出すのはどうするのかよくわからなかったんだけれども、textField を作成した時に、delegate を設定してやればよいと。

textField.delegate = self;

のような形です。これで特に問題ないのですが、Xcode のエディタに黄色の三角が出て、Assigning どーのこーのと、ちょっと嫌な感じ。textField 使うといつも出るんだよな・・・と思いつつ、警告はない方がいいのでよい方法はないかと調べたところ、Stack overflow を中心に、ヘッダファイルにプロトコルを追加すればいいんだよ、<UITextFieldDelegate> だよ、みたいな回答がありました。

ほぅほぅ、簡単ですな、とやってみましたが改善しません。なぜでしょう・・・

正しいやり方わかりません。やむを得ず魔法を使うことにしました。

textField.delegate = (id)self;

これで警告は出ません。

mapView に pin を刺して、タップしたら情報出すのって難しいね。

mapView に単に pin を打つのはそう難しいことではない。ネットで検索するとわかりやすい記事が出てくるので、詳細はそちらで。

また、pin にカレットを表示することや、カレットに info ボタンを表示することも同じくすぐ出来るでしょう。

問題はその先で、カレットに表示した info ボタンをタップした時に、カレットに detail を表示する方法がさっぱりわかりません。色々試しましたが未だにわかりません。view を segue で切り替えるような動きなら出来るけれども、カレット内の表示を切り替えようとすると途端にわからなくなる。

今回はよく考えてみたら、初期表示では pin のみ、pin をタップしたら詳細を表示、info ボタンをさらに押すのは操作が面倒になることを懸念しやめることにしたので、ま、いいか。この動きを実現するには、以下の記事が参考になりました。

stackoverflow.com

 

 

CLLocation から MKCoordinateRegion にするには・・・

CLLocation のデータを、MKCoordinateRegion データにするにはどうするのでしょう。

色々調べたところ、

CLLocationCoordinate2DMake(0.0, 0.0);

みたいな関数があり、え、CCLocation から x, y みたいな感じでプロパティ取り出すの?

え?分かんね・・・と思ったところ、そんなことはなくて、もっと簡単にできることがわかりました。というか、いつもそうなんですが、初めからわかるようにして置いてくださいというのが正直なところなんですが、当方の学習不足という懸念もありそうで、その点は言及しないことにします。

さて、余談が多くなってしまいましたが、結局のところ、CCLocation を MKCoordinateRgion とするには、次のようにすればオケです:

 

    MKCoordinateRegion cr =  [self.centerLocation coordinate];

 

つまり、CCLocation には、coordinate というメソッドが用意されており、それを呼び出せばオケということです。ちなみに、coordinate の意味は調整とかそういうことみたいですね。

今日の格言:めんどくさい方法を改善する方法は大抵用意されている。

5,000 円のクーポン券が当たった。

某店の 5,000 円クーポン券が当たってしまった。

よく考えると、店はよく見るのだけれど、最近は買うものがないなぁと思っていたところ。以前は、Lee の国内生産ジーンズが置いてあったんだけど、最近はアメリカで流通しているものばかりで、ちょっといらない感じ。ジーンズ購入する気になれず、どうしたものかと。

ネットでよく品定めして、キャンバーの白 T にしようかなと思ったんだけど、会社に着ていけそうにもないしなぁ。悩んだ末、Saintt James の薄手 T シャツにしました。これ、まともに買うと 6 千円以上するので、クーボンなかったら絶対買わないなと。

来週も抽選があるようなので、また応募しました。当たったらどうしよ。

 

segue で画面遷移するときに値を渡せない・・・

Xcode で画面を作り、segue で接続してやると特にプログラムしなくても画面遷移ができてとても便利なんですが、画面遷移する折に遷移先に値を渡してやりたい時があります。

そんな時どうするのかよくわからなかったんですが、いろいろ調べてみた結果、以下のようにするとすんなりだと。

1. 遷移先のクラスに、値受け取り用に property を作っておく

2. 遷移元では、prepareForSegue メソッドを実装。segue が複数ある時のために、メソッド内では identifier で名前を取得して判別すべし。

3. prepareForSegue メソッド内では [segue distinationViewController] とすれば、遷移先のクラスが取得できる。このクラスのプロパティに必要な値をセットしよう。

文字で書くとまさにこのようなことなんです。決して間違いではありませんが、すんなり値を渡せずかなりはまりました。理由は、遷移先の ViewController を設定した際、m ファイルと h ファイルは作ってあったのですが、class 名が null で設定していなかったので、遷移してエラーになっていました。

わかってしまえば簡単なことですが、分かるまでが大変な苦労で、おや?配列は渡すことができないのか?いやそんなことはない、ネット検索したら渡している例がある、など、ホント、理由がわかるまでに苦労しました。

今日の教訓:ViewController で画面を新しく作ったら、class 名を設定することを忘れてはいけない。

block の中で使う変数を変更する方法

Objective-C でいつの間にか block 構文を使えるようになって便利というか、method に勝手に組み込まれているので覚えざるを得ない状況です。

block って便利なんですが、文が長くなりすぎてしまいわかりにくいのが難点かと。

その他、block 内で変数を変更しようとしても上手くいかない。これには理由があって、変数のキャプチャ機能があるので block 内部では実際の変数ではなくコピーが使われていて、block の外の変数は変更されない言語仕様になっているようです。

ただ、それでは困ることもあるわけで、そんな時のために、__block 修飾子が用意されていて、ブロックの外で次のように宣言すれば、block の中で使えて値を共有できるようになります。

    CKReference* __block record_ref;

知らなかったので、class のプロパティ経由で値をやり取りできないか?とか色々試してしまいましたが、できなくて困ったなぁと思ったところだったので、すごい助かりました。

ありがとう、黒本。

同期処理に semaphore を使う

CloudKit のプログラムを書いていると、サーバに対する Query 処理などでは非同期処理となる。通常はこれで特に問題がないのですが、フィールドの値に Reference 型を指定してある場合、マスターのレコードを query してサーバ側のレコード番号を取得しておく必要が出てくる。

その後、自分のレコードを保存することになりますが、マスターのレコードを query してくるところが間に合わなくて、値を保存し損ねてしまうことがあります、ってか、通信が高速になったとは言え、普通間に合わないです。

こんな時どうすればいのかわからなかったのですが、semaphore を使って同期処理にしてしまえば良いようです。具体的には以下のような形で・・・

        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

     ... some programs ...

    dispatch_semaphore_signal(semaphore);
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

  とりあえずやり方わかってよかったです。