文字っぽいの。

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

上町から桜新町まで散歩しながら、OGAWA COFFEE LABORATORYに行ってきた。

東急電鉄世田谷線の上町駅から桜新町まで、寄り道をしながら散歩をしてOGAWA COFFEE LABORATORYに行ってきました。

YOUR DAILY/COFFEE

f:id:FromAtom:20210418154003p:plain

上町駅から徒歩5分弱でいけるYOUR DAILY/COFFEE。ドリップコーヒーは浅煎りが3種類、中煎りが1種類選べるようになっていた。

f:id:FromAtom:20210417130547j:plainf:id:FromAtom:20210417130527j:plain
キューバサンドとフレンチトースト

初めてORIGAMI ドリッパーを使ってるお店に出会った気がする。コーヒーによって、ドリッパーを使い分けていそう。ORIGAMIドリッパーは店頭でも販売していた。お店のグッズも売っていたけど、ロゴがかわいくてよかった。

f:id:FromAtom:20210417130329j:plain

近所にあったら毎日通いたい感じの、居心地が良いお店だった。

Raven's table

f:id:FromAtom:20210417134503j:plain

店内には1人か2人までしか入れない、小さなパン屋さん。

f:id:FromAtom:20210417135521j:plain

ホットドッグにはザワークラウトが入っていて珍しい感じ。店内に食べるスペースはないので、持ち帰って家で食べた。

散歩の道中にはパイプを利用した水遊びスペースとかあった。

f:id:FromAtom:20210417140440j:plain

こんなパイプがいくつか立っていて水が出てる。馬事公苑が近いらしい。

OGAWA COFFEE LABORATORY

f:id:FromAtom:20210417152208j:plain
こういうグラス。流行ってるよね。

小雨が降り始めたので、早足になりつつOGAWA COFFEE LABORATORYへ。

14時位についたけど、結構並んでいて1時間ぐらいで入れた。ギリギリランチメニューにありつけたので、お昼ごはんをいただく。

f:id:FromAtom:20210417153738j:plainf:id:FromAtom:20210417153938j:plain
ビーフカレーと鶏グリルのチムチュムソース

美味しくてよかった。量も丁度いい感じ。鶏のグリルはゴルゴンゾーラソースも選べた。チムチュムソースは、タイ料理のチムチュムに入っている香草をソースにしたもの。雑に書くとガーリックバジルソースな味。

「カフェランチってかもうディナーでは」という美味しさでとても満足した。ディナーメニューにはがっつりとステーキがあったり、コースもあるらしいので機会があったら来てみたい。

OGAWA COFFEE LABORATORYにはその名の通り、面白いコーヒーメニューがたくさんある。せっかくなので、食後のコーヒーはその中から選んだ。ランチのセットドリンクもあるけど、差額を払うだけで他のドリンクにも変更できるのが嬉しいところ。

これは"KO-CHA"。

f:id:FromAtom:20210417160730j:plain

グラスには煎茶を凍らせた氷が入っており、それに少し甘い暖かいコーヒーを入れて飲むもの。飲もうとグラスを口に近づけるとまずは煎茶の香りがする。飲むとほんのり甘いコーヒーに少しだけ煎茶の渋みが混ざって不思議な味わい。

あんこがバケットにのって出てくるけど、これはあんこというより、小豆をほんのり甘く煮たものと言う感じ。豆感が残っていてあっさりしていて、煎茶+コーヒーを邪魔せず美味しい。

こっちは "Bright Sense"

f:id:FromAtom:20210417160957j:plain

浅煎りのコーヒーに、塩気のあるフォームミルクをのせたもの。店員さん曰く、「グレープフルーツの様な浅煎りコーヒーに、塩気のあるフォームミルクをのせることで、ソルティドッグのような味わいを楽しめます。」とのこと。

コーヒーではない別の飲み物かのように仕上がっていて、浅煎りコーヒーの酸味が苦手な人でも飲める味わい。

店内は薄暗くて落ち着いてコーヒーを楽しめる雰囲気。大きな窓がずっと開放されていて換気もできているし、席間も十分に空いていてコロナ対策的にも良かった。

リモートワークで目減りする「褒め」と「感謝」

みなさん、最近「褒め」られたり「感謝」されたりしましたか? また、最近誰かを「褒め」たり「感謝」を伝えたりしましたか?

コロナ禍によってリモートワーク・テレワークを導入する企業が増える前から、褒めたり感謝を伝えることは大切だと言われており、多くの人が意識してそういった行動をとっていたことと思います。しかし、対面での会話を控えるようになった昨今では、「褒め」や「感謝」を伝える機会が減っている気がします。

以前であれば、社のイベント、飲み会、廊下ですれ違った時、コンビニやランチに出かける時、水や飲み物を取りに行った時、MTG開始前や終了後など、様々な「いい感じにラフなタイミング」で「この前のアレありがとうね!」とか「前に出してたアレめっちゃええやん!」と声をかけることができました。しかし、今ではこういったタイミングのほとんどが失われてしまいました。

わたしたちは、以前よりも意識して「褒め」と「感謝」を伝えるタイミングを作る必要がでてきました。それはスタンドアップミーティングの時かもしれませんし、(OKRの文脈での)ウィンセッションの場かもしれませんし、Slackなどのテキストチャットかもしれません。

なんにせよ、単純接触効果が全く役に立たないこの状況下です。「こんなことわざわざ言わなくても良いか」と思うささいな「褒め」や「感謝」でも、そういった個々の小さな言葉の積み重ねが、陰鬱としたこの状況下で誰かを少しだけ楽にできるのだと思います。

山崎実業のお風呂の壁につけられる収納でお風呂場を整理した。

お風呂の壁、多くの場合はマグネットがくっつくようになっていて、最近では「磁石でくっつく洗面器!」とかも売り出されている。 「磁石くっつくのかー。」と思って自分の家でも適当な磁石で試してみたら無事にくっついたので、山崎実業のお風呂収納をいくつか購入した。

山崎実業(Yamazaki) 浴室用ラック ホワイト 約W28XD9.5XH8cm MIST 4237

山崎実業(Yamazaki) 浴室用ラック ホワイト 約W28XD9.5XH8cm MIST 4237

  • 発売日: 2019/03/27
  • メディア: ホーム&キッチン

これには妻が利用するシャンプー・コンディショナー・ボディーソープのボトルや、メイク落としとか諸々のチューブ類が乗っけてある。

男の自分は少ないもので、これで事足りる。立ってシャワーをすることが多いので、高めの位置にくっつけられるのが良い。

ひげそりを置くやつも買った。上の多機能ラックに全部載せられるので、要らなかったかもしれない。

シェーバー類がうまく収納できなくて困っていたが、これを使うといい感じに収納できてよかった。


特に買ってよかったのがこれ。

おもちゃラックだけど、お掃除用具を入れるのに使っている。

f:id:FromAtom:20210116223413j:plain
ごちゃごちゃお掃除セット

お掃除用具はどうしても濡れてしまうのでお風呂外での収納が難しく、かといってお風呂の中では置いておく場所がない。前までは雑なプラカゴに入れていたけど、置いてある場所が汚れやすいし見た目もダサかった。 これなら風呂場の角にくっつけておけるし、浮いてるので水はけも良い。もし邪魔なら外して別の角に貼り付ければ良くて最高。

これらの製品を導入によって、床に物がなくなってのがとても良い。風呂の床にラックなどを置いてあるとどうしても底に水が溜まって汚れるのが早いし、こまめに掃除するのも億劫になる。 また、スクレイパーで水を払うのも物があるとやりにくい。とにかくすべてを空中に固定することで、風呂床の掃除が行いやすくなって便利。

ちなみに「磁石だとシャンプーとかのポンプ押したら落ちないの?」と思っていたけど、よほど力強く押す必要があるほどポンプが固くなければ大丈夫だろう。普段遣いでは全く問題ない。

洗濯機を買い替えた。

大学生の頃からずっと使い続けていた洗濯機をようやく買い替えた。この洗濯機は父親から譲り受けたもので、2008か2009年製の無印良品のものだった。かれこれ12年以上使われているのに、なぜか壊れないので買い換えるタイミングを失っていた。

f:id:FromAtom:20210116150341j:plain
なぜか壊れなかった洗濯機

しかし、さすがに容量も単身者用で小さいし、汚れも気になるようになったので買い替えた。

"時代はドラム式洗濯機"ということで、採寸してみたところ最小サイズでもサイズがピッタリ過ぎたので諦めた。ピッタリなら良いと思うけど、我が家にはこういったランドリーシェルフがあるので、左右に隙間が無いと困ってしまう。

どうしてもドラム式洗濯機が欲しいというわけではなく、容量が増えてあわよくば洗剤の自動投入あると嬉しいという温度感だったので、その条件で洗濯機を探していた。どうやらパナソニック製では縦型でも乾燥機能がついている洗濯機でないと自動投入はないらしい。

というわけで、パナソニックのNA-FW100K8を購入した。

f:id:FromAtom:20210116172413j:plain

panasonic.jp

何度か使ってみた感想を書く。

自動投入はやっぱり便利で、今まで人間がお猪口でオットットしていたのがアホらしくなる。アタックゼロにしたことでかなり楽になったが、それでも作業が有るのと無いのでは大違い。漂白剤だけ手動だけど、これぐらいならギリギリ許容できる。こう考えると食洗機も自動投入になってほしい。

乾燥機能はちゃんと乾くし、タオルもフカフカになる。ただ、冬場はエアコンの前に干しておいたほうが加湿になるしなぁと使うことは少なそう。梅雨シーズンには助かりそう。あとはシーツや布団カバーなど、干すのが面倒かつ乾くまで時間がかかる大物を洗濯乾燥すると。晴れた日に洗濯をガッと回したいのに、こういう大物は物干し竿を専有するので、どうしても優先度が落ちがちなので助かる。

駆動音については、10年以上前の洗濯機と比べるまでもないが、非常に静かだ。さすがに乾燥時にはうるさいが、洗濯時は脱水でも非常に静か。最初は「これ洗ってるのかな?スタートボタン押し忘れたのか?」と思うほどだった。これなら在宅勤務中に洗濯機を回しても大丈夫そう。

デメリットとしては運転中には蓋がロックされるタイプなので、洗っている様子を眺めることができない。脱水時に爆音がしないので「もうすぐ終わるな」と把握することができない。値段が高い。

kakaku.com

自分は家電量販店で値引き交渉してWeb最安値から2万ほど引いてもらって、古い洗濯機の回収もつけてもらえたけど、Webでポチッと買いたい場合には「ドラム式洗濯機でよくね?」という値段だと思う。縦型なので壊れにくく、その点で費用が回収できるといいなと思っている。

Swiftで大量のメンバ変数があるclassやstructのinitを自動生成する。

環境

課題

開発をしていると、こんな感じでメンバ変数がたっぷりあるclassができます。この例ではclassですが、structも同様ですね。

class SampleClass: Codable {
    public let id: Int
    public let title: String
    public let body: String
    public let thumbnailUrl: URL
    public let tags: [String]
    public let categories: [String]
    public let createdAt: Date
    public let updatedAt: Date
    public let comment: [String]
    public let isFavorited: Bool
    public let isBookmarked: Bool
    public let url: URL
}

Swiftのstructではinitが自動生成されますが、Embedded Frameworkを活用してModelをアプリ外に出しているとその恩恵を受けることができません。Modelを外に出している場合は、Codableに準拠しておくだけで済むことが多いのですが、たまにinitが必要になります。

さて、このメンバ変数に対応したinitを書くと、

init(id: Int, title: String, body: String, thumbnailUrl: URL, tags: [String], categories: [String], createdAt: Date, updatedAt: Date, comment: [String], isFavorited: Bool, isBookmarked: Bool, url: URL) {
    self.id = id
    self.title = title
    self.body = body
    self.thumbnailUrl = thumbnailUrl
    self.tags = tags
    self.categories = categories
    self.createdAt = createdAt
    self.updatedAt = updatedAt
    self.comment = comment
    self.isFavorited = isFavorited
    self.isBookmarked = isBookmarked
    self.url = url
}

と、結構な量を書く必要があり面倒です。実際のプロダクトコードでは、もっと多くのメンバ変数を持つ場合もあります。

解決法

XcodeのRefactor機能を使って自動生成します。

  1. class名 or struct名を右クリックする
  2. "Refactor"メニューを選ぶ
  3. "Generate Memberwise Initializer"をクリック

f:id:FromAtom:20210106000215g:plain

これで簡単にinitが生成できます。めでたしめでたし。

Xcode12時代のライブラリ管理ツール選定

背景

iOSDC 2020でMint及びiOSアプリ開発時のライブラリ管理について執筆し、同様の内容をZennでも本として販売した。

zenn.dev

しかし、Xcode12の正式版がリリース後に、執筆時からライブラリ管理を取り巻く状況が大きく変わってきたため、ここに筆を執った次第である。

はじめに

この記事はXcode12を利用してiOSアプリ開発を行う前提で執筆されている。また、情報は2020年12月25日現在のものとなる。

iOSアプリ開発を行う場合、ライブラリ管理には

  • CocoaPods
  • Carthage
  • Swift Package Manager(以下 SwiftPM)
  • Manual

が選択肢として挙げられる。Manualは管理といえるのか怪しいため今回は省略する。なお筆者は、

  • 本業:Carthage, CocoaPods, Mint 1
  • 副業:SwiftPM, Mint
  • 個人開発1:SwiftPM, Mint
  • 個人開発2:CocoaPods, cocoapods-binary

という構成で開発を行っている。

以下、CocoaPods、Carthage、SwiftPMのそれぞれでライブラリ管理をする場合のメリットとデメリットを述べる。

CocoaPods

■メリット

CocoaPodsは2011年に作られたツールで、すでに9年以上の歴史がある。Objective-CからSwiftへの移行も乗り越えた歴戦の戦士であり、十分に長い年月利用されているため、とてもよく枯れている。

また、CocoaPodsにはPluginの仕組みがあり、便利なサブコマンドを追加することができる。有名なところではcocoapods-keyscocoapods-binaryがある。これらPluginもGemとして提供されているので、Gemfile に追記して bundle install して Podfile に追記するだけで利用することができる。

■デメリット

Ruby Gemなので、Rubyが必要になる。Rubyは別に嫌いではないし、個人OSSでも利用している。ただ、こちらとしてはiOSアプリ開発をしたいのであって、Rubyでコードを書くわけではない。SwiftでiOSアプリを書きたいだけなのに、どうしてrbenvでRubyを入れ、Bundlerを入れ、Gemfileを書いてCocoaPodsを入れてバージョン管理をしなければならないのだろうか。Fastlaneも同様にGemなので許容範囲とも考えられるが、正直管理するものが多くて面倒である。

[追記 2020/12/25 15:45]

今ではSystemのRubyを利用することも可能なようです。

[追記ここまで]

よく知られたデメリットとして、Clean Buildするとライブラリも再ビルドが必要になるためビルド時間が長くなる点がある。これはCocoaPodsの仕組み上なくなることは無いが、最近ではそこまで気にしなくても良いだろう。Swift2や3系の頃のSwiftコンパイラはかなり安全側に倒してあり、差分ビルドよりフルビルドが選ばれがちであった。そのため、1行変更しただけでフルビルドが走り、その度にCocosPodsで導入したライブラリ群もビルドされるため、長時間のビルドを待つ事態が頻発していた。Swift5系の今では、こういった挙動は皆無ではないにせよかなり減った。

SwiftUIで開発していると稀に「Derived Dataを消してXcodeを再起動すると直るエラー」に出会う。これが何を起因として発生しているのか不明なのでなんとも言えず、Xcodeのアップデートによって発生しなくなるかもしれないが、もし頻発するようであればフルビルドによって開発速度が低下することは記しておく。

Carthage

■メリット

導入には.pkg, Homebrew, Mintなどが使える。別のプログラミング言語を準備すること無く導入が可能である。

Carthageで導入されたライブラリは事前にビルドされており、Xcode上からはビルド済みのライブラリを利用するため、Clean Buildをしてもライブラリ群の再ビルドが走らない。これによって、CocoaPodsに比べてビルド時間を短縮することができる。ちなみに、cocoapods-binaryでも同様の状況にはできる。

■デメリット

Mintを利用せず .pkg やHomebrewで導入した場合、Carthage自体のバージョン管理を行うことができない。そのため、複数人で開発をしている場合に、チームメンバーそれぞれの手元で異なるバージョンのCarthageが動くことになる。これはMintを導入することで解決可能なため、些末な問題だとも言える。

ライブラリ群が事前にビルドされることはデメリットにもなり得る。開発環境を整える際に大量のライブラリ群のビルドを待たなければならないし、 git switchした際にライブラリのバージョンが異なっている場合にも、ビルドし直さなければならない。これは、Carthage/Build ディレクトリをGitの管理下に含めることで対処可能ではある。しかし、Carthage/Build のサイズが大きいためGitリポジトリの肥大化が加速してしまい、別の問題に直面することになる。

さて、ここまで色々と書いてきたが最も大きなデメリットは、Xcode12からCarthageがまともに使えなくなってしまったことだ。この問題は公式から案内されているWorkaroundを利用することで対応が可能ではある。

しかし、2020年9月16日にXcode12 GMが提供されてから3ヶ月が経った今でもこの問題は解決されていないため、対応を待ち続けるのは良策ではないだろう。

このWorkaround問題に関係しているが、未だにCarthageはXCFrameworksに対応できていない点もデメリットの一つである。XCFrameworksはWWDC2019で発表された仕組みであり、当時は「これをCarthageがサポートしたら copy-frameworksが不要になる!」と言われていた。優秀なOSSコミッター各位が揃っている中で未だに対応していないということは、非常に大きく困難な壁があることは想像に難くない。なお、CocoaPodsとSwiftPMはXCFrameworksに対応している。

SwiftPM

■メリット

Xcodeをインストールすればすぐに使える。サードパーティツールを導入する必要が無く、Xcodeを起動して待っているだけでコードを書き始められる点が最大のメリットだろう。CLIツールを利用しなければ、セットアップスクリプトも不要になる。

iOSアプリを開発をしたいのにRubyやHomebrewを利用してサードパーティツールを入れ、そのツールをセットアップするために、setup.shMakefileに細々と設定を書く必要がなくなるのは非常に心地が良い。README.md# SETUP 項には

$ xed .

とだけ書けば良い。

■デメリット

SwiftPMではXcodeでProjectが開かれると、管理しているライブラリ群の更新を確認する。これはAndroidのGradleに似た挙動ではあるが、地味に時間がかかるため若干不便である。もちろん利用するライブラリが増えると、この待ち時間は長くなっていく。

もっとも不便さを感じるのは、SwiftPMではライブラリをStatic Frameworkとして扱う点である。このため、例えばライブラリAがアプリ本体とWidgetKitの両方で使われていると、エラーになってビルドができない。この問題を解決するためには、1度自作のFrameworkに包んでDynamic Frameworkの様に振る舞わせる必要がある。

この問題は、Embedded Frameworkでも発生する。なお、筆者は試していないがEmbedded Frameworkをprojectとして管理し、それぞれのproject毎にSwiftPMの設定をすることで回避することが可能かもしれない。

Firebase iOS SDKやRxSwiftを利用した際にも問題がある。Firebase iOS SDKのSwiftPM対応はまだbetaであるため、Workaroundを利用しないとAppStore Connectへのバイナリアップロードができない。

If you're using FirebaseAnalytics, Xcode 12.0, and have an issue with device installation or archive uploading, see the workaround at https://github.com/firebase/firebase-ios-sdk/issues/6472#issuecomment-694449182.

RxSwiftの場合はRxTestを利用している場合にリンクエラーになるバグがある。

[SR-12303] Swift Package Manager package stopped working after Xcode 11.3, Xcode 12, etc. - Swift

これからアプリを書き始めるならCombineを使う手もあるが、すでにRxSwiftとRxTestが導入されているプロジェクトで、Combine移行するコストは無視できない大きさである。

結論

2020年12月25日現在では、CocoaPodsを選択するのがベターだと言える。

しかし、今後CarthageのXCFrameworksサポートや、Firebase iOS SDKのSwiftPM/Carthageサポート完了によって最適解は都度変化するだろう。もし記事公開から数カ月後にこの記事を読んでいる読者がいたら、最新の状況を調べてから判断して欲しい。

CLIツールの管理

話が脇道にそれるが、Swift製のCLIツールのバージョン管理についても書く。CLIツールとしてよく使われるものには、

  • realm/SwiftLint
  • nicklockwood/SwiftFormat
  • mono0926/LicensePlist
  • mac-cain13/R.swift
  • SwiftGen/SwiftGen
  • yonaskolb/XcodeGen

などがある。

まず、Homebrewによるバージョン管理は困難2なため除外する。そのため選択肢としては、SwiftPM, Mint, CocoaPods,cocoapods-binaryがある。

SwiftPMの場合、すでにアプリ側でSwiftPMを利用している場合にダミーファイルを用意する必要があるため若干煩雑である。よって現時点では、Mint, CocoaPods, cocoapods-binaryのいずれかを用いるのがよいだろう。もし、アプリ側のライブラリ管理をCocoaPodsに一元化するのであれば、cocoapods-binaryを利用するのがベターだと考える。

実際にこれらツールを用いてCLIツールを管理する方法については、上述したZennの本でも記載している。ただし、わざわざ購入しなくても検索したほうが無料で最新の情報が得られるだろう。

zenn.dev

感想

私個人としてはCarthage+Mintによって「最初にビルドをしておけば、後は高速にコードを書き続けられる」という状況が得られると考えていたが、昨今の状況を鑑みると難しそうである。


  1. CocoaPodsを引き剥がそうと思いながら作業をしていたら、Xcode12リリース後に状況が一変してしまって厳しい。

  2. HomebrewでもFormula提供者が特別な対応をすることでバージョンを指定した(かのような)インストールが可能だが、全ての過去バージョンがインストールできるかはFormula提供者が対応するかどうかに依存する。

Xcodeのデバッグコンソール画面が勝手に閉じて不便なやつ対策

環境

起こること

ビルドしてシミュレータが起動するたびに、デバッグコンソール画面が閉じてしまう。

f:id:FromAtom:20201217192005p:plain
デバッグコンソールはここのこと

ログを見たいのに、ここが閉じてしまうと見れなくてとても不便だった。

対策

XcodeのPreferencesのBehaviorsタブを開き、Running -> Completesから下記の項目を変更する。

f:id:FromAtom:20201217192207p:plain

変更内容はチェックを外すでも良いし、下記画像のように変更しても良い。

f:id:FromAtom:20201217192900p:plain

もしくはこうすると、毎回勝手にデバッグコンソールが開いてくれる。

f:id:FromAtom:20201222132238p:plain

謝辞

この対応方法は@k_katsumiさんに教えていただきました。ありがとうございました。