RxSwiftわからん

メモ書き

ObserverとObserable

世界観として、観察者と観察対象がある。ObserableからObserverに対して複数回状態を送信する。UILabelとかUITableViewはObserberとなり、Obserableの値を観察を行って変更があった場合にそれに合わせて表示を変更を行う。ObserableはDBの値やサーバーで取ってくる値、UITextFieldやUIButtonなどがある。

Hot/Cool

obserableは基本的にHotなobservableでないと複数から観察できない。 * Subject * multicast, publish/replay/replayAll, share

少し古いが、このスライドがわかりやすかった。shareが便利

今日こそ理解するHot / Cold @社内RxSwift勉強会

Sink

内部的に使われているもの。ObserverでありObservableでもある。FilterとかMapで返ってくる

46pあたりから説明がありわかりやすかった。 RxSwift コードリーディングの勘所@社内RxSwift勉強会

deferred/Deferred

まだよくわからない

amb/Amb

buffer/BufferTimeCount, debounce

入力される最後の通知からtimeinterval の時間の後にcount分だけ通知を一気に流す。 検索をするコストがそこそこある場合に、入力されるたびではなくUISearchBarからの最後の入力から0.5秒後に検索を行いたい時に用いるのが良い。 debounceはcountを1にしたもの

throttle

連続して大量に繰り返される処理を一定間隔で間引くものです。 よく使われるのはscrollイベントです。スクロールイベントをすべてハンドリングすると処理回数が多くなり、場合によってはスクロールがもっさりしてしまいますよね。それを防ぎます。

throttleとdebounce

materialize, dematerialize

Eventに変換と元に戻す

【RxSwift】materialize, dematealizeを使ってみた

concat/Concat , combineLatest/ CombineLatestN

複数のObservableをまとめて、一つのObservableとして扱うもの

distinctUntilChanged/DistinctUntilChanged

通知の内容が前回と変更があった場合に通知を次に流す

concat , merge

複数のストリームを混ぜ合わせられる

【RxSwift】concatとmergeの違いをサンプルを元に整理してみる – su- tech blog

ObservableType

RxSwiftのObertvableな物についている

Obserable

最もシンプルなObservableType。ObservableType に実装されているところ以外はほとんど能力はない

SharedSequence

ConnectableObservableType

subscribeを完了させた後にconnect()を行って、接続を完了させる。

iOSで実装されているカレンダーの解説

この記事を読んでいる人は、日本語で書いているので概ね西暦か和暦を使っていると思います。しかし、世界には西暦では過ごしていない国や地域が数多くある。もしグローバル展開する機会があればそれぞれの国で正しく計算されたり表示される助けになればと思います。

カレンダーの隣の日付はグレゴリアン暦2020年3月14日をそれぞれのカレンダーで表示したもの。

太陽暦

太陽暦とは

太陽の変化によって一年を決める方法。太陽を地球が一周するのに365.25日程度かかるため、1年を365日と4年に1回の閏年で調整を行う暦。月と季節は同期する。

グレゴリオ暦

グレゴリオ暦と同じ日付を採用する暦をグレゴリオ暦系とした。 太陽年は365.25日ではなく誤差があり、400年間に(100回ではなく)97回の閏年置いて調整を行っている。

グレゴリオ暦

iso8601 Saturday, March 14, 2020 gregorian Saturday, March 14, 2020 iso8601 にも定義されているように国際標準の暦として採用されている。世界的にも多く採用されている。 キリスト紀元として、キリストが誕生した年を1年とした。多くの暦は紀元1年の前年は紀元前1年であり、0年は存在しない。

タイ仏暦

buddhist Saturday, March 14, 2563 BE 釈迦が入滅した翌年を元年とする紀年法である。キリスト紀元に543を加えた値が仏滅紀元となる。

中華民国暦

republicOfChina Saturday, March 14, 109 Minguo

中華民国が成立した1912年を元年とする紀年法である。

和暦

japanese ここで紹介する全ての暦の中で最も変わった紀元をもつ。改元を行う暦である。多くの暦は紀元を基準にするか紀元前と紀元後しか存在しない。一方、和暦は237個の元号が存在し、30年程度で改元が行われる。改元される理由は近年では天皇陛下が御即位されることによって改元され、直近にならないといつ改元されるかは予測不可能である。平成31年4月30日の翌日は、令和1年5月1日である。つまり、時代(era)が一つ増え、年が1に戻り、月以下は通常通りである。平成31年と令和1年はeraとyearが異なっているが同じ年として扱われる。

海外では改元されることを想定していないOSSが多く存在するため注意が必要である。

イラン暦

persian Saturday, Esfand 24, 1398 AP

紀元を預言者ムハンマドヒジュラの年(西暦622年)を紀元としておく。 グレゴリオ暦と日付が異なるが年が多少ずれるものの、グレゴリオ暦と完全同期している。 イラン暦 - Wikipedia

コプト暦系

1年は13ヶ月あり、初めの12ヶ月は各30日から成り、13月に追加日5日(閏年は6日)を足した365日(366日)である。 太陽年との誤差を修正していない365.25日を1年の長さとしている。通常は1年を365日として4年ごとに閏年をせってしている。ユリウス暦と同期しており、グレゴリアン暦に比べて400年で3日進むため、徐々にズレが生じる。

コプト

coptic Saturday, Baramhat 5, 1736 ERA1 ディオクレティアヌス紀元を紀元とている。ディオクレティアヌス紀元は、ディオクレティアヌスが即位した年の年初(ユリウス暦284年8月29日)を紀元とする

エチオピア

ethiopicAmeteMihret Saturday, Megabit 5, 2012 ERA1

キリストの生誕を基準にしている。

ethiopicAmeteAlem Saturday, Megabit 5, 7512 ERA0

神はキリストの生誕の5500年前に世界を創造したとして、世界創造暦を基準としている。

太陰太陽暦

1月を29.5日、12ヶ月を1年として、季節の連れを修正するために、3年に1回程度1ヶ月追加される。追加される月のことを「閏月」と呼ぶ。

インド国定暦

indian Saturday, Phalguna 24, 1941 Saka

サカ紀元の紀元に当たる西暦78年を「インド国定暦0年」として数える。

中国暦

chinese Saturday, Second Month 21, 2020(geng-zi)

ユダヤ暦

hebrew Saturday, 18 Adar 5780 at 12:55:29 AM Japan Standard Time

太陰暦

1ヶ月を29.5日、12ヶ月で1年としたもの。

イスラム暦

islamic Saturday, Rajab 20, 1441 AH islamicCivil Saturday, Rajab 19, 1441 AH islamicTabular Saturday, Rajab 20, 1441 AH islamicUmmAlQura Saturday, Rajab 19, 1441 AH

イスラム暦の少しづつ違うようだが細かくは調べきれていない。分かる人コメントください。

参照

The Ethiopic Calendar | An Ethiopian Journal

iOSでユーザーが文字を入力する方法

UITextFieldなどに文字を入力する方法が、キーボードだけではないのでまとめておこうと思います。

ソフトウェアキーボード

もっとも一般的な入力方法。 日本語の変換があるので確定していない文字が存在する。確定した時点で、複数の文字が入れ替わったりすることもある。

外部キーボード

Bluetoothなどでつながったキーボードを使って、文字を入力することができる。ほとんどは、ローマ字入力だが、バーコードリーダーなどの特殊な入力をするようなキーボードも存在する

カットやペースト

 大量の文字を一度に削除したり、入力することになる。必ず一文字ずつ入力していると考えているとバグの原因になる。 数字をペーストをする際は前後にスペースが入ったりする。

元に戻すとやり直す

シェイクしたりアラートを表示したり、iPadではキーボードにボタンをタップするなど、元に戻すを行うことができます。もちろんやり直すこともできる。 ユーザーの入力を変更していたりすると、クラッシュする場合がある。 https://qiita.com/akuraru/items/15e629bfe472f83f45f6

他のテキストからドラッグする

選択している状態で、ドラッグすると文字がそのまま別のテキストに貼り付けることができます。結果としてペーストと同じような挙動になります。

f:id:akuraru:20200326223617p:plain

他にも入力方法を知っていたらコメントください。

あなたの文字制限をしているUITextFieldはクラッシュしているかもしれない

UITextFieldで入力した文字に対して何らかの制限を加えたい時はよくあると思います。文字数を制限したり、数字のみを入力させたい場合などです。

サンプルコードを用意しました。 https://github.com/akuraru/CrashTextField

数字のみを入力制限させたい場合の雑なサンプルは以下のようなものになると思います。このコードはクラッシュします。

extension ViewController: UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let b = string.isEmpty || string == String(Int(string) ?? 0)
        return b
    }
}

クラッシュの再現方法

  1. UITextFieldに制限される文字列をペーストする
  2. 端末をシェイクして取り消しアラートを表示する(シミュレータだと⌘+⌃+Z)
  3. 取り消す
  4. クラッシュ

対策1

入力を受け付けない場合、UndoManagaerをリセットします。これで、取り消しができなくなります。

extension ViewController: UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let b = string.isEmpty || string == String(Int(string) ?? 0)
        
        if !b {
            textField.undoManager?.removeAllActions()
        }
        
        return b
    }
}

対策2

シェイクで編集する機能を無効にします。この方法はアプリ全体で無効になってしまうのでできればやらないようにしたほうがいいでしょう。

application.applicationSupportsShakeToEdit = false

クラッシュの内容(おまけ)

アプリケーションのどこで起こったクラッシュなのか全くわからないクラッシュログが発生する

2018-05-21 22:20:05.268665+0900 CrashTextField[47789:859156] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSBigMutableString substringWithRange:]: Range {0, 38} out of bounds; string length 0'
*** First throw call stack:
(
    0   CoreFoundation                      0x00000001127fd1e6 __exceptionPreprocess + 294
    1   libobjc.A.dylib                     0x000000010ec76031 objc_exception_throw + 48
    2   CoreFoundation                      0x0000000112872975 +[NSException raise:format:] + 197
    3   Foundation                          0x000000010e663e72 -[NSString substringWithRange:] + 131
    4   UIKit                               0x0000000110360b1e -[NSTextStorage(UIKitUndoExtensions) _undoRedoAttributedSubstringFromRange:] + 136
    5   UIKit                               0x0000000110360f7d -[_UITextUndoOperationReplace undoRedo] + 319
    6   Foundation                          0x000000010e711695 -[_NSUndoStack popAndInvoke] + 280
    7   Foundation                          0x000000010e711424 -[NSUndoManager undoNestedGroup] + 433
    8   UIKit                               0x000000010f5225aa __58-[UIApplication _showEditAlertViewWithUndoManager:window:]_block_invoke.2495 + 31
    9   UIKit                               0x000000010f8db425 -[UIAlertController _invokeHandlersForAction:] + 105
    10  UIKit                               0x000000010f8dbe2a __103-[UIAlertController _dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:dismissCompletion:]_block_invoke.461 + 16
    11  UIKit                               0x000000010f683d02 -[UIPresentationController transitionDidFinish:] + 1346
    12  UIKit                               0x000000010f687b72 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke.436 + 183
    13  UIKit                               0x000000011026b274 -[_UIViewControllerTransitionContext completeTransition:] + 102
    14  UIKit                               0x000000010f5d410d -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 859
    15  UIKit                               0x000000010f5a6f09 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 343
    16  UIKit                               0x000000010f5a754c -[UIViewAnimationState animationDidStop:finished:] + 293
    17  UIKit                               0x000000010f5a7600 -[UIViewAnimationState animationDidStop:finished:] + 473
    18  QuartzCore                          0x00000001160117a9 _ZN2CA5Layer23run_animation_callbacksEPv + 323
    19  libdispatch.dylib                   0x000000011395d848 _dispatch_client_callout + 8
    20  libdispatch.dylib                   0x000000011396892b _dispatch_main_queue_callback_4CF + 628
    21  CoreFoundation                      0x00000001127bfc99 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    22  CoreFoundation                      0x0000000112783ea6 __CFRunLoopRun + 2342
    23  CoreFoundation                      0x000000011278330b CFRunLoopRunSpecific + 635
    24  GraphicsServices                    0x0000000115189a73 GSEventRunModal + 62
    25  UIKit                               0x000000010f5120b7 UIApplicationMain + 159
    26  CrashTextField                      0x000000010e36db77 main + 55
    27  libdyld.dylib                       0x00000001139da955 start + 1
)

参考

https://www.jianshu.com/p/b302a7c66741

XCUITestでアプリの初期状態を変更する

起動時にパラメータを渡すことができ、アプリケーション内でいつでもそれを確認することができます。 XCUITestでは外部からの操作がほとんどできません。この起動時のパラメータによって初期状態を変更することができそうです。

let app = XCUIApplication()
app.launchArguments.append("UITEST")
app.launch()
ProcessInfo.processInfo.arguments.contains("UITEST")

リモートワークは銭湯ですべき

前職での話です

リモートワーク制度で諸事情によって会社にこれないための制度です。 諸事情の解釈は通常家にいないといけない理由がある的なものかもしれませんが、会社の環境(主にネットワークあたりとか狭いとか)よくないということを理由により良い環境で働くためにリモートワークすることにしました。 より良い環境が必ずしも自宅とは限らない。 適当にググって良さそうだったのでなごみの湯にリモートワークしにいくことにしました。

https://www.google.co.jp/amp/s/multiness.net/tripandwork/nomad-super-sento/amp/

なごみの湯とは

https://www.nagomino-yu.com/ 都内の日帰り温泉のこと。 新宿から10分程度の荻窪にあり、駅からすぐ近くにあり割と簡単に行ける。

良い点

  • 会社のWifiより若干早い
  • 広い。すごく広い。誰も働いていないので3席分くらい占有できる。
  • 15分で温泉に浸かって休憩できる
    • タバコ休憩並なので、共用されていいはず
  • コンビニにおやつ買ってくる短くて健康的
  • 詰まったら温泉入りに行ける
  • サウナとかもある
  • リクライニングソファとかがある
  • 隣が秋吉

悪い点

  • 2000円くらいかかる
  • そんなにはお高くはない
  • 電源があるところの椅子は硬い
  • 一度入ったら出れない
  • 食べてから行くか、中で食べるか迷う
  • もちろんディスプレイとかはない
  • 個人的な理由
    • 会社より遠い
    • おそらく中央線ユーザ以外は大抵の人が会社より遠くなりがち

勤怠的な話

勤怠は現状のシステムとしては、出社して退社した後に再び出社して退社した場合はその間が休憩時間としてあるかわれます。よってTeamSpiritで論理出社と退社ボタンを使って休憩時間を記録することができます。食事などをしている時間をし始めるタイミングで退社を行い、終わったら出社することで正確な勤怠管理が可能です。

その他

  • 漫画がある
    • 読んでいないものがあれば漫画喫茶より安く済むかも
  • 縦に長い施設
  • 女子の方が休憩施設に近い
  • 女子風呂が2階で休憩施設が地下1階、男子は4階
  • 働いている人は2,3人見かけた

転職と原宿のおすすめの店10選

1月15日に退職して、16日にクレディセゾンに入社しました。給料と環境は向上した。エンジニア募集しているそうです。

ということでおすすめの原宿の10選です。

がらり

焼酎と味噌のお店。お昼は3種類の味噌汁が無限に飲める。何食べても旨い。そして常に混んでいる。

夜は味噌舐めながら、焼酎を煽る末期な飲み方がしていた。

https://www.google.co.jp/amp/s/s.tabelog.com/tokyo/A1309/A130901/13005444/top_amp/

タップルーム

クラフトビールのお店。昼はやっていない(はず)。常に10種類以上のクラフトビールがある。

今のところ飲み屋しかないが、1杯で潰れるので飲み屋は出てこない。

https://bairdbeer.com/ja/taprooms/

龍の子

麻婆豆腐のお店。会社からは竹下通りを通り抜けていくがそれだけの価値はある。麻婆豆腐以外もあるが、麻婆豆腐しか食べた事はない。

http://ryunoko.tokyo

Hutte

グリルバル。ステーキが食べれる店。ステーキを食べようと思ったらかなり長距離を移動しないとないので、会社から2番目に近い飲食店というのもあり得点が高い。

https://www.google.co.jp/amp/s/amp.retty.me/r/100001311117/

スパゴ

パスタ専門店。パスタの種類がかなりある。食べた限りでは全部美味しかった。たらこがおすすめ。

https://www.google.co.jp/amp/s/amp.retty.me/r/100000019992/

asatte

日替わり定食のみのお店。入るとご飯の量しか聞かれないので初見殺し感がある。毎日変わるので毎日行ける店。

https://www.instagram.com/asatte._.menu/?hl=ja

東京バーガー

東京感はない。なんなら常連はバーガーも食べない。ライスシリーズのタコライスロコモコを食べている。

https://g.co/kgs/FqQzPH

うさぎ

広島のお好み焼き屋。

https://g.co/kgs/XL2mqp

手打ち釜揚げうどん 禅

カレーうどんがおすすめ

https://g.co/kgs/FfvWEc

五○二

定食とうどんのお店

https://g.co/kgs/geR5f1

まとめ

原宿でも勧めれる10個もあったことに驚いている。一番のおすすめは同僚と食べにいく店です。