textView は曲者だ。

textView は曲者だ。以前もハマった記憶がある。

事象は、textView に文字を設定しようとしても設定できない状況。textView.text = @"hoge"; で設定できるはずなのに、全く反応なし。かなり調べて、例えば、.editable は頭に指定しないで、text の変更をしてから指定する・・・だめだ、うまくいかない。textView.text = @""; としてから、textView.text = @"hoge"; とする・・・、だめだ、うまくいかない。

結局、storyboard に設定した textView を一度削除して、もっかいオブジェクトを配置し、ヘッダーファイルにアウトレット登録したらうまくいきました。

なんかよくわからない。バグですか?

つくば駅まで 35 Km

5 月にトレイルのレースがあり、距離は 37Km。レース前に同じぐらいの距離を走っておきたく、今日は休日だったので朝から走ることに。

自宅からつくば駅まで 35 Km あり、朝 7:30 分に走り始めて、つくば駅に着いたのが 11:40 頃。実に 4 時間以上かかったわけですが、30 Km 過ぎてからペースが上がらず、歩き歩きになってしまいました。レースに向けてこれまで練習した中で、最長は 27 Km。今日は 30 Km 以上の距離になり、未知の世界感満載。途中、自販機とコンビニで2 回程給水。気温が割とあるのと、日陰があまりなかったので、結構喉が乾きました。

つま先走りに変えてから、35 Km も保つのか不安でしたが、特に問題なかったのが良かったです。これぐらい長距離を走ると、いつもは太ももの前面が痛くて痛くてたまらなくなるのですが、つま先走りにしてからは、太ももの前面が全然痛くなりません。代わりに、足の裏、母子球付近が痛くなってしまいますが、ま、これは仕方ないでしょうね。明日、どこが筋肉痛になるか注意して、レース本番までに補強をしたいと思います。

ゴールした後、コンビニで 100 円ドリップコーヒーと、アイスクリーム買って食べました。すごくうまかったです。昼も食べて帰ろうかと思っていたのですが、疲れ過ぎて食べるのが辛そうなのでやめました。回数券の自販機で割安の切符を買ったら、¥200 近く安くてびっくり。

レース本番では今日よりも距離があるのと、アップダウンもあるわけですが、硬いアスファルトではなく土なので、足の裏のダメージは少なくて済みそう。

それにしても、何時間でゴールできるのか・・・

 

Xcode 8 では CoreData 用のファイルは automatic になったんだって (2)

CoreData が automatic になったことは既報の通りです。実際使用するにあたり、どういう違いが出てくるのか、実際プログラムして試してみました。

結論から言うと、automatic の方が便利です。理由は、開発の段では database の schema は変動的なので、フィールドの追加、フィールド名の変更などが頻繁に発生するもので、その度にファイルを作り直す必要がないので(コンパイル時に自動的に作ってくれるので)そこが便利。

あと、従来の方法で、フィールドの変更などが起こると、アプリ起動時にアプリが落ちてしまうことが大半で、お?何のエラー?意味わかんね?と言うことがしばしばでしたが、automatic なら、落ちることも少なくなり精神衛生上好ましいと思います。それではフィールド名の変更やフィールドの追加があったとするとどうなるのかと言うと、変更前のレコードはそのまま取り残され、次にデータを保存したタイミングでは新しいスキーマに基づいたレコードが保存されることになります。落ちなくなったものの、すでに保存してしまったデータを活かすなら従来通り migration は必要なので、そこは、注意が必要でしょうか。

それでは、新しい CoreData はどうやって使うかについて言及しましょう。まずヘッダーファイルで以下の指定をします。

#import <CoreData/CoreData.h>

#import "your_entity_name+CoreDataProperties.h"

データの追加は次のような形です。

AppDelegate* appdelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];

NSManagedObjectContext* context = appdelegate.persistentContainer.viewContext;

 

これで、context ができたので、データを保存するなら、こんな感じです。

NSManagedObject* entityNameObj = [NSEntityDescriptioninsertNewObjectForEntityForName:@"your_entity_name" 

                             inManagedObjectContext:context];

[entityNameObj setValue:mesg forKey:@"your_fieldname"];

[((AppDelegate*)[[UIApplication sharedApplication] delegate]) saveContext];

 

 

と言うわけで、

appdelegate.persistentContainer.viewContext

って何ですか?と言うのはありますが、これは覚えるしかないのでしょうね。

 

 

TLSv1.2 って何ですか・・・

事の発端はアプリから SSL 通信で CGI にアクセスし、JSON データを受領しようとした事。

NSURLRequest を使って、簡単・簡単、と思ったら、推奨していないので、NSURLSession を使えと叱られる。うわーめんどくセーと思いながら渋々書き換えたところ、error 発生。どういうわけか、ここだけ日本語でエラー表示。

Error Domain=NSURLErrorDomain Code=-1200 "SSLエラーが起きたため、サーバへのセキュリティ保護された接続を確立できません。

何かいつもと様子が違うので、ググってみたら、iOS 9 から TSL v1.2 となっていて、Web サーバ側での対応がとれてていないのでエラーになっている感じ。Web サーバは当方管轄外なので、回避策はないのかさらに調べたところ、まず、console で通信しようとしている Web サーバの対応状況を調べ、次に、info.plist に例外記載すればよいらしい。

console で調査:

/usr/bin/nscurl --ats-diagnostics https://some_domain

 

TLSv1.2 with PFS disabled and insecure HTTP allowed

Result : FAIL

---

 

---

TLSv1.1 with PFS disabled and insecure HTTP allowed

Result : FAIL

---

 

---

TLSv1.0 with PFS disabled and insecure HTTP allowed

Result : PASS

 

はいはい、v1.0 じゃないとダメなのね、ということで、今度は info.plist に以下の記載を追加。

App Transport Security Settings, dictionary

  Exception Domains, dictionary

    domain_name, dictionary

      NSIncludesSubdomains, Boolean, YES

      NSThirdPartyExceptionRequiresForwardSecrecy, Boolean, NO

      NSThirdPartyExceptionMinimumTLSVersion, string, TLSv1.0

どこに追加するのかよくわからなかったので、Information Property List のすぐ下に追加しましたが、ちゃんと設定されたようで、うまく通信できました。

これ、普通わかんないよね。

ふうぅぅぅ。

 

 

LM5102 と LM0102 の比較

先日、LM5102 と LM4102 の違いについて言及しました。

その後、LM0102 を購入(厳密には、Twill black)を購入したので、重ねてみてスタイルの違いを比較しました。

はじめに、LM5102 の説明を読んだ印象と、実際に履いてみての思っていたのは、結局、原点回帰なら LM0102 と変わらないのでは?と思っていました。今回、両方を重ねて比較した結果、スタイルはほとんど一緒だということがわかりました。

ただ、購入したのが Twill black なので、履いてみての姿は随分違います。Twill の方がシワが目立たないので、陰影も薄く、履いた姿はブーツカット感もない感じに見えます。

細かく見ると、仕立ての部分で detail が随分違います。LM5102 の方が総じて作り込まれている感じがします。ジッパー、レザーバック(LM0102 は革ではない)、サイドの耳が開いている(履き込むといいアタリが出る)、ベルトの穴が 7 本などです。こういった細かい違いが価格差になっているようです。ただ、この違いは履いた時の見た目にはあまり違いが出ません。生地もオーガニックだったりトレーサビリティだったりするので上質ですが、履き心地も見た目も違いになって現れないでしょう。残りの良さとして、染めの違いがありそうで、同じブルージーンズなら、LM5102 の方がカッコよく色落ちする期待感があります。

今回、Twill の黒を購入しましたが、LM5102 (アメリカンライダーズ)でも Twill 黒あります。Twill の場合、前述の通り、見た目にはさほど違いが出にくいので、価格差を考え、LM0102 でもいいかなぁと思いました。

私としては、ローライズ感満点で、履いた時の見た目のかっこよさが抜群の LM4102 のスタイルがとても良かったので、復活希望です。

addObserver に UserDefaults を登録できる

プログラムを作るときに KVO って便利なんだけど、監視対象にするオブジェクトとして、UserDefaults を指定できることを知らなかった・・・

随分遠回りな実装になってしまったところでできることに気がついて、その後、余分なコードを消し消ししてそっちの方が大変だった。

実装は次のような感じ。

    defaults = [NSUserDefaults standardUserDefaults];    

    [defaults addObserver:self forKeyPath:@"fireTime"

                  options:( NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld )

                  context:nil];

便利、便利。

UserNotifications について

時計とアラームをアプリに組み込んでいて、時間が来たら Alerm を出すわけですが、以前は、Notification とか使っていたんですけど、いつの間にか、UNNotificationCenter なる Framework が追加になっていた。

Swift ベースの記述が多くて難儀しましたが、いろいろ調べたところ、今までよりも格段に使いやすくなっていることが分かりました。後学のため、組み込み方をメモします。

以下のような記述が必要ですが、ひとまずは Appdelegage.m の applicationDidFinishLaunchingWithOptions に記載。

    //set NotificationCenter instance

    UNUserNotificationCenter* notificationCenter = [UNUserNotificationCenter currentNotificationCenter];

    

    // set delegate

    notificationCenter.delegate = self;

    

    //setting type of notification

    // use Sound and Alert

    [notificationCenter requestAuthorizationWithOptions:UNAuthorizationOptionSound|UNAuthorizationOptionAlert

                                      completionHandler:^( BOOL granted, NSError * _Nullable error )

     {

         // none

     }];

 

 

フォアグラウンドで通知を受けた場合の処理は delegate method が呼ばれる。

該当するクラスに、delegate を設定し、.delegate = self; を忘れずに、以下のメソッドを記入。

 

 

- (void) userNotificationCenter:(UNUserNotificationCenter *)center

        willPresentNotification:(UNNotification *)notification

          withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler

{

 

    // アプリがフォアグランドにいた場合の通知動作を指定する。

    completionHandler(UNNotificationPresentationOptionBadge |

                      UNNotificationPresentationOptionSound |

                      UNNotificationPresentationOptionAlert);

}

 

はまってしまったのは、AppDelegate.m に記載しなければならないのかと思ったのですが、普通に delegate method だったので、delegate の宣言をして、呼んで欲しいクラスに書けば OK。