文字っぽいの。

文字を書いています。写真も混ざります。

2023年の買ってよかったもの。

毎年12月になって慌てて書いているので、今のうちに書いておこう。

山崎実業 バスルーム多機能ラック

マグネットでお風呂場の壁にくっつけられるラック。 シャンプー、ボディーソープ、シェービングクリーム、体洗うタオルなどの一式をこれにセットすることができて便利。マグネットはかなり強力なので、このラックの上でシャンプーなどのポンプを押してもびくともしない。

Anker PowerLine Ⅲ

PD(高速)充電にも対応しているケーブル。やわらかくてコシがあってサラサラしている。とにかく絡まない。バッグの中に入れて持ち運ぶ用途で非常に便利に使っている。

エレコム クリーナー ブラシ

帯電防止のクリーナーブラシ、ディスプレイのホコリを取るのに使っている。これを買うまではキムワイプなどで頑張っていたけど、これを買ったらこれで良くなった。洗えるのも助かる。

HHKB Professional HYBRID Type-S 英語配列/雪

HHKB Pro2の墨を使い続けてきたけど、無線にしたくなったので購入。詳しくはこちら。

fromatom.hatenablog.com

銭別銀行とりだし君

小銭を入れると勝手に仕分けしてくれて便利な貯金箱。財布に入っている小銭をとりあえず入れればOKになったのでとても便利。10円がたまりがち。

Mcdodo 多機能 デジタル収納ケース

  • Type-C to Type-Cケーブル(PD充電対応)
  • Type-C to Micro USB変換アダプタ
  • Type-C to Lightning変換アダプタ
  • Type-C to USB-A変換アダプタ
  • SIMカード取り出しピン

が全部入っているのに非常に小さい。とりあえずカバンに入れておけば応急処置で充電したり、通信したりが可能になる。

FUNDAY モイストシェーブ&ウォッシュ

シェービングしつつ洗顔もできるやつ。朝にこれで顔を洗いながら髭を剃っている。パッケージがオレンジで可愛いのも気に入ってる。メンズ用の化粧品って全部青・白・黒・緑なのなんとかならんのか?

Elgato Key Light Mini

顔を明るくするライト。部屋のシーリングライトを背負った位置に机があってどうにも顔が暗くなりがちで、MTGはまだしも面接や外部の方との打合せで印象がよろしくないので購入した。爆裂に眩しい。PCやスマホから電源のON/OFFや光量変更、色温度変更もできてすごい便利。眩しい。

Anker Eufy Security SmartTrack Card

財布に入れられるトラッカー。AppleのAirTagは地味に大きく厚みもあるため、小さい財布を使っていると使えないけど、これなら入る。クレカ2枚分の厚さなので財布に入れるカードを整理して入れた。財布を落としたことは無いけど、もし落としたら大変すぎるので転ばぬ先の杖。

Belkin MagSafe対応 磁気ワイヤレス充電スタンド

くっつければ充電できるスタンド。どうにも「AppleWatchも充電できる!」みたいなのが多くて困っていたけど、これはiPhoneだけ充電できるし、安いし、デザインもへんてこじゃない。一方で重みはないので工夫をしないとiPhoneを取り外すのがちょっと難しい。

Anker 633 Magnetic Wireless Charger

最強のMagSafe充電器。なんと充電器がモバイルバッテリーも兼ねているので、出かける直前で「全然充電ないやん」ってときでも、このバッテリーをつけっぱなしで出かければ良い。しかもスタンドを使うためにはバッテリーをセットしないとなので「バッテリーの充電を忘れていた」という事故も防げる。デメリットは価格。高い。

Maker hart Just Mixer S

Mac, Windows, PS4, Switchなど複数の音源があり、それを1箇所に集めたい時に便利なミキサー。小型かつ安価なので非常に良かった。

Cubilux マルチ イヤホン スプリッター

Maker hart Just Mixer Sで集めた音源を、複数の出力に分割するために購入。スピーカー、イヤホン、ブルートゥーストランスミッターに音を流している。

オーム電機 キッチンライト

キッチンのコンロまわりがどうにも暗くて購入。換気扇についてる申し訳程度のライトでは全然ダメだったけど、これをつけたらバリバリに明るくなった。

サンスター 水まわり用輝き洗剤キーラ

これをスポンジに付けてシンクを磨くだけでピカピカになって最高。水垢がひどい場合は塗ったあとでしばらくおいておくと良い。2週間に1回程度使ってシンクをきれいにしてニッコリしている。

リーベックス(Revex) ワイヤレス チャイム

インターホンが隣の部屋にあるかつ、音がちょっと低めなためにドアを貫通してくれない。なおかつ仕事中はイヤホンやヘッドホンをして音楽を流しているので更に気づけなくなる。iPhoneの機能もあるけど、なかなかそれも使いにくくて困ってた。これなら遠隔で音がなるだけでなく、光ってくれるのでめっちゃ気付ける。

デメリットとしてはドアの近くにインターホンがあって、勢いよくドアを閉めるとその音で反応してしまうこと。

Xbox ワイヤレス コントローラー

PCゲーをやるために購入。ずっとPS4DUALSHOCKを使っていたけど、スティックが加水分解されてきてしまったので買ってみた。めちゃくちゃ良い。背面にドット加工がされていることによってちょうどよい滑り止めになっていて、手にすごい馴染む。十字キー部分はクリック感があってカチカチを音がなりながら押せるもの。これが存外に良くて、メニュー操作をするときなどあまりにも快適。乾電池式なのも良くて、たまに充電池を入れ替えれば良いだけなのが良い。Aボタンが下にあるのが人によってはデメリットだけど、SteamもPS5も下にあるボタンが決定になってるから、こちらに慣れていくのが良いんだとおもう。

FPSなどをガチでやる人ならホールエフェクトとか背面ボタンとか欲しいので物足りないと思うけど、そうじゃないならこれが最適解だと思う。

コンドー お薬手帳&カードケース

カバンの中に「財布に入れる1軍ではないが、持ち歩いておくと何かと便利」なカードとお薬手帳を入れているのだけど、それらをまとめるのに便利。

Xiaomi Smart Band 7

最強スマートバンド。自分がスマートバンドに求めているものは、時間が分かるのと通知が来ること、そして充電を頻繁にしなくて良いこと。あとはたまーに、タイマーやストップウォッチが使えればそれで良い。

XiaomiのSmart Bandシリーズは2週間バッテリーが持つのに有機ELで、なおかつセール時なら4000〜5000円くらいで買える。なんかおかしい。文字盤もカスタマイズできるので、テンプレートをカスタマイズしたり、自分で作ったりして楽しめる。通知も「このアプリの通知のみ送る」という設定ができるのが非常に便利。

タオル研究所 ミニバスタオル

タオルはタオル研究所が最強。ふわふわだし、毛羽落ちも少ない。自分は髪が短いのででっかいバスタオルより、こういうミニバスタオルの方が、洗濯や乾燥が楽になって良い。

GUARIRE 肘置きクッション

どうにも肘置きに肘を立てている事が多いらしく、肘の骨が痛くなってきたので購入した。「ちゃんと固定できるんかな?」と不安だったけど、ガッチリと固定されてずれることもないし、肘の骨も痛くならなくなったので最高。おまけでリストレストがついてくるけど、これはいらない。

マーナ 極しゃもじ

全くくっつかないしゃもじ。しかも薄いから米を切るように混ぜるのがとても容易にできる。注意点としては食洗機に入れてはいけないこと。食洗機で洗うとすぐにくっつくようになってしまう。手洗いなら大丈夫。

3coins バスタオルハンガー

https://www.palcloset.jp/display/item/2006-20H2149-00/

画像だと複数枚干しているけど、これに1枚のバスタオルを干している。そうするとバスタオル同士がくっつかずに隙間があくので乾きやすいし臭くなりにくい。非常に便利だけど、3coinsなので耐久性はちょっと弱い。一回割れてしまったので買い直した。

象印 加湿器 EE-DD50

自分が買ったのはEE-DC50という1つ前のモデル。最強の加湿器。お湯を沸かすのでどうしても電気代はかかるが、喉を痛めたり皮膚乾燥のかゆみで掻き壊して病院に行くよりは良いと思う。

Swift OpenAPI GeneratorでISO8601拡張形式のDateが処理できないことがある

問題

Apple公式のOpenAPI Generatorを使うと、Responseをパーズできなくて下記のエラーが出ることがある。

Client error - cause description: 'Unknown', underlying error: DecodingError: dataCorrupted - at : Expected date string to be ISO8601-formatted.

原因

正確にはSwift OpenAPI Generatorではなくswift-openapi-runtimeがデフォルトで利用するISO8601DateTranscoderの実装に起因している。

public struct ISO8601DateTranscoder: DateTranscoder {

    /// Creates and returns an ISO 8601 formatted string representation of the specified date.
    public func encode(_ date: Date) throws -> String { ISO8601DateFormatter().string(from: date) }

    /// Creates and returns a date object from the specified ISO 8601 formatted string representation.
    public func decode(_ dateString: String) throws -> Date {
        guard let date = ISO8601DateFormatter().date(from: dateString) else {
            throw DecodingError.dataCorrupted(
                .init(codingPath: [], debugDescription: "Expected date string to be ISO8601-formatted.")
            )
        }
        return date
    }
}

https://github.com/apple/swift-openapi-runtime/blob/d50b48957ccb388fb89db98a56c2337276298e79/Sources/OpenAPIRuntime/Conversion/Configuration.swift#L28-L42

SwiftのISO8601DateFormatterを利用しているので良いように見えるが、ISO8601には拡張形式がありこのコードはそれに対応していない。

例えば、 2023-11-23T10:29:15.53+09:00 のように、ミリ秒まで含まれるISO8601拡張形式を処理したい場合は

let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withFractionalSeconds]

のように .withFractionalSeconds オプションを追加で指定する必要がある。他にも拡張形式は様々あるため、拡張形式でDateが表記されているレスポンスの場合、ISO8601DateTranscoderではうまく処理できないことがある。

対策

DateTranscoder はprotocolとして公開されているので、自分で DateTranscoder を作ってしまえば良い。

struct CustomISO8601DateTranscoder: DateTranscoder {
    public func encode(_ date: Date) throws -> String { ISO8601DateFormatter().string(from: date) }

    public func decode(_ dateString: String) throws -> Date {
        let iso8601DateFormatter = ISO8601DateFormatter()
        iso8601DateFormatter.formatOptions = [.withFractionalSeconds]

        guard let date = iso8601DateFormatter.date(from: dateString) else {
            throw DecodingError.dataCorrupted(
                .init(codingPath: [], debugDescription: "Expected date string to be ISO8601-formatted.")
            )
        }
        return date
    }
}

実装した CustomISO8601DateTranscoder はConfiguration経由でClientに渡せば良い。

let transport = AsyncHTTPClientTransport(configuration: .init())
let client = Client(
    serverURL: serverURL,
    configuration: Configuration(dateTranscoder: CustomISO8601DateTranscoder()),
    transport: transport
)

iso8601DateFormatter.formatOptions にどのOptionを指定すればよいかはAPIのレスポンス形式による。使えるOptionはこちらを参照すること。

developer.apple.com

参考ページ

#iOSDC Japan 2023のレギュラートークで『君だけのGFMエディタを作ろう!』というタイトルで登壇してきました。

今年もオフライン・オンラインのハイブリッド開催!

今年のiOSDCも去年に引き続きオフライン・オンライン両方のハイブリッド開催でした。今年はブース出展の担当をしており、会場に行ける時間も少なかったので配信で見られるのはとても助かりました。

レギュラートーク登壇

めでたいことに今年も採択していただいたので、20分のレギュラートークをしてきました。なんとこれで6年連続登壇です!

Apple公式がcmark-gfmを利用したMarkdownパーザであるapple/swift-markdownを公開しています。今回の発表ではこのswift-markdownを利用して、

  • Markdownの入力補助をする便利バーの作り方
  • シンタックスハイライトを自分で実装する方法
  • プレビューはどうすればよいか?

について話しました。

世の中にはたくさんのMarkdownエディタアプリがありますが、どうしても「ここがもっとこうなればい良いのに」という要望が出てくるものです。例えばEmacs, Vim, VSCodeなどであれば自分でカスタマイズしてしまえばよいのですが、iOS, iPadOSアプリではそれが難しいです。しかし我々はエンジニアなので、なければ作ってしまうことが可能です。

しかし、いざ作ろうと思ってもMarkdownをどの処理すると良いのか取っ掛かりがないものです。 そこで今回の発表ではiOS, iPadOS, macOSMarkdownエディタを実装してみたい人の参考となるように資料をまとめてみました。

とにかくSourceLocation, SouceRangeを変換するのが大変で、文字コードに悩まされるのですが、おいでよ文字コード地獄の沼へ……という気持ちです。

今年のラーメン

今年のiOSDCではランチにキッチンカーがやってきており、そこでご飯を買うことができました。そのためお昼は会場で済ますことができて大変助かりました。しかし、せっかくラーメン激戦区である高田馬場まで行くのであれば、いくつか回りたい店舗があるのも事実。そこで、夕飯にラーメンを食べることにしました。

どちらの店舗も美味しかったので、高田馬場に訪れた際や来年のiOSDCでぜひ。

渡なべ

tabelog.com

博多ラーメン でぶちゃん 高田馬場本店

tabelog.com

まとめ

今年も無事に登壇することができて嬉しかったです。またブースや懇親会で、よくインターネットで見かける方や、すごい久しぶりに会う方や、登壇を拝聴させて頂いたスピーカーの方とじっくりとお話できて非常に楽しかったです。やはり対面でじっくり話せると、色々と深い話が聞けてとても楽しいですね。こればっかりはオンラインでは得られない効能だと感じます。

さらに今年は無限コーヒーが復活していてすごく嬉しかったです。お盆も過ぎて9月だというのに汗をかくほど暑い3日間。そんな中でのアイスコーヒーが非常に美味しかったです。ペットボトルの水もいっぱいあって助かった。

自分個人としては、6年連続登壇が嬉しかったのでここらで一段落したい気持ちもありつつ、来年も登壇できたらいいなぁという気持ちもあります。って毎年書いてるんだよなぁ。

それでは皆様、また来年お会いしましょう。

iOSDC Japan 2023で『君だけのGFMエディタを作ろう!』というお話をします。

今年もiOSDC Japanの季節がやってきましたね!ありがたいことに今年はレギュラートーク(20分)を採択してもらえました。 これで6年連続登壇となり、うれしみに舞い踊っております。

fortee.jp

プロポーザル内容は、

NSAttributedStringとSwiftUIのMarkdown対応により、 誰もが1度は「僕の考えた最強のMarkdownエディタ」を作る夢を見たでしょう。

エディタには、見出し・太字・リストなどの記法を簡単に入力できるボタンが欲しくなります。 その時に「正規表現で実現できそう」と考える人がいるかもしれません。 そう、過去の私です。 しかし、正規表現を用いた実装は失敗に終わります。

このセッションではその失敗をもとに、

  • 正規表現で入力補助機能の実装が困難な理由
  • apple/swift-markdownとcmark-gfm
  • SourceLocation をUITextViewで扱う方法
  • Syntax Highlightの自作方法 について話します。

このセッションを聞くことで、みなさんもオリジナルのMarkdownエディタが作れるようになります!

となっています。入力補助をする便利バーやシンタックスハイライトもついたMarkdownエディタを作るために、必要なノウハウをお話します。

9月2日(土)の16:50からTrack Cで話しますので、GitHub Flavored Markdownエディタを自作してみたい人や、 Markdownエディタ作りの難しさを知りたい人はぜひぜひお越しください。

また、今年のiOSDC Japanも去年と同様にオフライン+オンラインのハイブリッド開催となっています。 自分は現地で発表する予定なので、Ask the speakerや懇親会などで話しかけてもらえると嬉しいです。

ではみなさん、会場やインターネットでお会いしましょう!

南粤美食でお粥の会を開催した。

元町・中華街には、それはそれは豪華なお粥を楽しめる南粤美食というお店がある。TVドラマ版の孤独のグルメにも登場したお店なので、そちらで知っている人も多いだろう。

tabelog.com

さて、主題のお粥コースだが、このお粥コースは非常に難易度が高い。まず値段が高く1人15000円からになる。そして次に16人以上のグループ予約しか受け付けていない。つまり、このお粥コースを楽しみたい場合、1回の食事(お粥)に15000円出せる人間を16人集め、さらにその人数の予定を調整し、お店の予約が取れる日をおさえる必要がある。

そんなわけで非常に高難度なため、あまり期待せずに社内で募集をかけたらところ、21人集まった。変な会社である。

お粥コースの内容

まず前菜として、丸鶏の塩蒸し焼きが出てくる。これがいい感じに塩が効いていて旨い。

今日がお粥コースでなかったら、これだけで瓶ビールを何本も空けられる。 しかしこれはあくまでも前菜なため、心を落ち着かせてお粥の開始を待つ。

会場には最初からお粥が用意されている。人数が多いので鍋も2つあった。お粥というより重湯に近い。

そこに車海老がやってくる。生きているので、蓋をしないと全部飛び出していく。

そして、その海老をこうして、

こうじゃ。

そう、このお粥コースとは「大量の高級食材をお粥で茹でて食べていき、お粥にその出汁を染み込ませ、最後に出汁を吸収しまくったお粥を楽しむ」という、非常に贅沢なコースなのだ。

というわけで、お粥の出汁になるために茹でられた食材の様子たちをどうぞ。

アワビ、まずいわけがない。

ホタテは生で食べられるものをレアに茹でていただく。

イカとセンマイ。このイカが非常に美味しかった。センマイも下処理が丁寧にされていて一切の臭みがない。

名古屋コーチンは生姜が効いていて旨い。

しいたけは異常なサイズをしている。こんなん旨い。出汁も出まくる。

和牛は「ふるさと納税の宣材写真じゃん!」という声が出るほどにきれいなもの。当然旨い。

肉団子と真鱈のすり身団子、どちらも下味がちゃんとついていて、素材の味けいの今までとは路線が変わって良い。

山芋とかぼちゃ。山芋は外はホクホク、中はシャキシャキになって最高。

大粒なアサリ。熊本県産と聞いてちょっとしたザワツキが発生した。でも、こんなん旨いよな。

大根は今までの出汁を全部吸っていて、ジュワジュワに旨い。

最後は揚げパンと干し貝柱を入れて、お粥を完成させていく。

そして、完成したお粥がこちら。

このお粥に至るまでに非常に大量の食材を食べてきたため、腹はパンパンである。少なそうに見えるが、ちょうどいい。なにぶん味が強い。今までの食材がどこかにいる。味がする。つまるところ、これは味である。

感想

開催までの難易度が高くて躊躇していたが、やってみたら最高の体験を得ることができた。 なかなか難しいとは思うが、ぜひ一度行ってみてほしい。

ちなみに、南粤美食はお粥コースだけのお店ではなく、少人数でも(行列はすごいが)普通に飲食をしたり、予約してコース料理を楽しめるお店である。

ケーブルレスでWebカメラとライトを運用できるようにした。

こういったセットアップをした。

一番上にはこのライトがついている。

バッテリー内臓なので、充電ケーブルを繋ぎっぱなしにしなくても良い。

その下にはiPhoneをMagSafeで固定している。これもカメラを使う時だけくっつければ良いので、充電ケーブルはつけていない。

iPhoneMacを使っていれば連携カメラ機能で、iPhoneのカメラをMacWebカメラとして利用することが可能。

support.apple.com

これが非常に便利で、MaciPhoneを有線接続しなくても使えるという優れもの。

両方ともケーブルレスで使えるので、Macとはなにも繋げずにWebカメラとライトが運用できるようになった。

使ったもの

これらを順番に繋げてあげれば良い。

最後のクランプは設置場所によっては使えないので、ミニ三脚にしたり、ポールにすると良い。

感想

かなりコンパクトに便利な仕組みができた。ただ、MTGの時間が長い人は流石に充電ケーブルをつけないと1日は持たないと思うので、注意して欲しい。

プロポーザルが不採択になった時に。

社内で話した内容を公開できる状態にしました。 そのため、文意がブレていたり、補足が足りないかもしれません。


プロポーザルが不採択になると、どうしても悲しい気持ちになります。

試験で不合格になったような、なにか大きな失敗をしてしまったような。プロポーザルが不採択になったことが、自分のやってきたことの否定や自分自身が否定されてしまったように感じる人もいるでしょう。

"Don't take it personally." という言葉があります。コードや論文をレビューをされる時に気をつけるべきポイントとして話されることが多いです。レビューなどで受けた指摘は、あくまでも制作物の内容、表現に関するものであり、「あなた自身」に対するものではないので冷静に受け止めましょうというものです。

しかし、人間はそう簡単に気持ちを切り替えられないものです。そのため、不採択のストレスを忌避するように、

  • カンファレンスやコミュニティを下げる
    • 運営は何も分かってない、センスがないと批判する
    • 採択されてるプロポーザルが面白くないと他人を攻撃する
  • 自分の出したプロポーザルを卑下する
    • 元々面白くないと思っていたと言う
    • 本気じゃなかったと言う
    • 自分はセンス・能力が低いからと言う

といった行動をとることで自分を守ろうとします。これは人間の心の防御反応として仕方がないことなのですが、公に発言する事は、ぐっとこらえたほうが良いでしょう。

このネガティブをコミュニティに撒き散らしても、特に良い効果は生まれません。なんならコミュニティから「面倒な人」だと疎まれてしまうかもしれません。

「次こそは!」という気持ちで、日々の活動の中から発表のネタを探していけると良いですね。