読者です 読者をやめる 読者になる 読者になる

第5回 飯能アルプス~奥武蔵丸山トレイルラン、完走するも体ボロボロ・・・

距離がちょっと長いけど、参加したことがないレースなので、準備万端(のつもり)で臨むも、ゴールまで 9 時間近くかかるというなんとも情けない結果に・・・

距離が長いことはあらかじめわかっていたので、秋葉原までランニング 3 回、その他、20Km 以上の距離数えきれず、締めはつくばまでランニングと、足はしっかりできていたつもり。

レースを終えて痛いところは、太ももの前面と歯を食いしばったからか、顎の筋肉が痛い。太ももの前面は、特に階段を降りるときにかなりきつい。冷や汗が出るほど。顎の筋肉も相当やばい。お腹が空いているのに昨日は噛めなくて食べたくなくなるほど。

このコース、登り坂がきつすぎる。そして長い。見上げても見上げてもピークは遥か彼方、まるで見えない。しかも、途中で息継ぎしないと昇れないほどの急坂なので、全くスピードが出ない。登りがきついということは、下りも同じくらい急な坂ということ。ある程度の斜面なら、サーっと降りることができるが、そんな斜面ではなく、おっかなびっくり下りる感じで、下りもスピードが出ない。

あと、縦走区間がほとんどない。正丸峠を超えたあたりから、多少走れそうな区間があったけど、そこにたどり着くまでに足を使い果たしていて、スピードが乗らないし走る気力も失せてくる。

初めの 5Km 表示で長いと感じたが、10Km, 15Km が異様に長く感じる。15Km 地点で確か、4 時間は超えていたと思う。15Km 走って、まだ半分来ていないわけで、落胆の色は濃くなる。お金を払って出たレースなので、今まで考えたこともなかったけれども、リタイアしたいと何度か思った。ただ、リタイアしたところで、最寄り駅まで運搬し、以降はゴールまで電車で行って荷物を取ってくることになっているようで、それはそれで面倒すぎる。

25Km を超えたあたりからか、半分は超えた、残り半分、後半は確か下り一本調子だったはずと自分に言い聞かせて、淡々と進む。登って降りるとエイドがあるのが嬉しい。でも、エイドの後はまず間違いなく坂がきついということに気づき始め、エイドを離れたくなくなってくる。目論見通り、最後のピーク、丸山を超えたら下り一本調子になるも、もう、完全に足が残っていない。下りの方が足へのダメージがかかる。疲労が蓄積される感がすごい。

ようやくゴールするも、17 時過ぎていて帰りの電車に間に合わないかもしれないと思い、ゴール地点が温泉なのに風呂に入らず駅へ急ぐ。帰宅したのは 20 時を過ぎていた・・・

9 時間も運動をし続けたのは、人生初ではないだろうか。正直、もう、このコースは走りたくない(何日かするとまた、走りたくなるものだけど)。

日付の比較は compare ですか。

Objective-C で日付の比較をしようとしたところ、どうも、うまくいかない。

if ( now > item.date )

こういうのはだめ。

なんで?と調べて見たところ、compare 使えと。

[now compare:item.date]  --> 1 ............ now の方が最近

[now compare:item.date]  --> -1 ........... now の方が古い

isEqual といい、入念に用意してあるね。

 

設定、app、通知 が許可になっているのか調べるには・・・

時刻を設定すると、その時刻になるとアラームを出すアプリを作成中。こういった処理は、UNNotification を使って作成するのが iOS 10 からの流れのようで、UINotification の時代から大して慣れていない中、やっとこさっとこ意味のある機能を作ることができました。

端末が通知を許可しているか、許可していないかを調べる方法がわからなくて、色々試行錯誤してようやくわかりました。そもそもなんで許可しているかどうかを知りたかったかと言えば、タイマーをセットしようとして、時間が来たらアラートを出すのですが、端末が許可されていないと、fire しても発火しない(アラートが出ない)からです。

具体的な方法は、AppDelegate.m に以下のメソッドを定義します。

- (void) isNotificationsAuthorization:(void (^)(BOOL isActive)) handler

{

    [[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings* _Nonnull settings)

    {

        //settings.alertStyle == UNAlertStyleNone;

        NSLog(@"settngs: %ld", settings.authorizationStatus);

        if ( settings.authorizationStatus == UNAuthorizationStatusAuthorized )

        {

            // NSLog(@"Authorized");

            handler(YES);

        }

        else

        {

            // NSLog(@"Denied");

            handler(NO);

        }

    }];

}

このメソッドを呼び出すと、YES が返って来れば、端末は通知を許可していることになります。一方、NO が返って来れば、許可していないということです。このメソッドを呼び出すのは次のようにします。

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

        [appdelegate isNotificationsAuthorization:^(BOOL isActive)

         {

             if ( isActive )

             {

                 NSLog(@"notification setting: YES");

             }

             else

             {

                 NSLog(@"notification setting: NO");

             }

         }];

isActive の状況に応じて分岐できrので、例えば設定されていないことが分かれば、そこで「設定してください」のアラートを出すことができます。

というわけで、こんな感じでできることがわかって、良かった・よかったなんですが、余談もひとつ。

最近ネット上に Objective-C の記述が少なくて、そろそろ情報が増えて来た Swifit にしようかなと思い始めたところです。でも、Swift のコードを見ると、クロージャとかの記述は Objective-C とあんまり変わらず見にくい(醜い)ので、そうであれば、Objective-C の方がまだわかりやすくていいなぁと思いました。

SKLabelNode で画面中央に時計を表示すると、何秒かおきに横にずれてしまうのを解消。

SKLabelNode で画面中央に時計を表示した時のこと。時計は、シンプルに次のような形で HH:MM:SS。これ、何秒かおきに微妙右にずれ、左にずれを繰り返します。理由は、画面左右の中央に時計を表示しますが、時計の数字フォントの幅が、数によって微妙に異なるため。例えば、1 の横幅と 0 の横幅は違うということ。

これ、TeX の時も謎だったんだよなぁ。TeX で表組みする時、表に数字データが入っていると、数字によって幅が異なるので、縦に並べようとするとガタガタになっちゃう。回避策は、数字を表示したいときは数式モードにしてやると、0-9 まで全部の width が揃う(というか、kernning されなくなる)ので、表組みしてもガタガタしない。

SKLabelNode の場合、kernning を解除する指定は無いようなので、さてどうしたものかと試行錯誤した結果、horizonalAlignmentMode というプロパティがあり、縦方向に揃えようとする時、どこで揃えるかを指定できることが判明。今回の場合、SKLabelHorizonalAlignmentModeLeft を指定して、label の左端を揃える位置として指定してやることで、ずれなくなりました。デフォルトは center になっているので、数字の組み合わせによって時計全体の幅が変わるのでガタガタしていた、という訳だ。

細かく指定できていいけど、ちょっとめんどくさいね。

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

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