タグ「その他技術」の 記事 19 件中 1 ~ 19 件を表示しています。

ただの適材適所のような気がする

最近 jQuery でググると jQuery はレガシーで Vue や React, Angular はモダンというものばかり出てくる。 私も仕事やこの Blog において Vue で SPA を作成しており確かに便利だと思うのだが、本当に jQuery や Vanilla JS は終わった技術なのか、というのは気になるところだ。 その話をするところで jQuery は至るところでデータを持ち回してスパゲッティになりやすい (が Vue などはそうでない) といったような言い回しがされているのだが、私は全くそうは思わなかった。 むしろ Vue (Vuex) の方がどこに何があるかが分かりにくいし、PhpStorm でも Vue のコンポーネント開発があまり楽に書けない (JS のコード補完があまり頼りにならない)。 正直なところ技術がどうというより実装者のスキルに依存するほうが大きい。 他人が書いた Vue (Vuex) のコードなど読めたものではない。

jQuery はまだまだ Bootstrap 4 にも同梱されているし、あまり考えずに使っていけるのがよい。 レガシーなのだから、と毛嫌いして使わないのはもったいないような気がする。 jQuery 使うくらいなら Vanilla JS のほうがいい、という意見もあるかもしれないが、実際のところ jQuery で書いたほうがはるかにコードが短くなる。 それに jQuery を使わなくても Bootstrap で必要だったりして結局 jQuery のロードはされるケースが多い。 さすがに SPA は Vue 一択だと思うが、普通の Blog やマスタ管理のようなページ切り替えをメインとする Web アプリならば jQuery の方が実装しやすい気がする。 要は適材適所。

それにしても PHP はどんどん進化して書きやすくなっていっているが、JavaScript は Laravel Mix (Babel) を通して ES6 で書いてもイマイチ書きにくいと感じる。 ということで、なるべく楽をするために PHP 側で書ける処理はなるべく PHP 側で書くというふうにしている。

最近 PhpStorm をアップデートしたら JetBrains Mono というフォントに自動的に変更された。 このフォントが特に低解像度ディスプレイで異常に見やすくて気に入って使っている。 どういう仕組みになっているのか分からないが、デフォルトだと PhpStorm のような JetBrains 製の IDE 以外で使えないので改めてフォントをダウンロードする必要があった。 JetBrains Mono 公式サイトでダウンロードできる。 そしてこのフォントは Web フォントが同梱されており自分の Web サイトやアプリで自由に使用して良いと明記されているのが素晴らしい。 早速この Blog にも Web フォント (.woff2.woff) を埋め込んでみた。 プログラミングコードが出現した際に使用される。

ちなみに JetBrains Mono を Web フォントとして使うには以下のような CSS を書けば良い:

// @font-face として JetBrains Mono を定義する
@font-face {
    font-family: 'JetBrains Mono';
    src: local('JetBrains Mono'),
        url('fonts/JetBrainsMono-Regular.woff2') format('woff2'),
        url('fonts/JetBrainsMono-Regular.woff') format('woff');
}

// 使用したいところで普通に指定すればよい
div.post-content code {
    font-family: "JetBrains Mono", monospace;
}

src の指定の意味は local (ローカル PC) に JetBrains Mono が入っていたらそれを使い、無かったら woff2, woff フォーマットの順でダウンロードして使用するという意味である。 woff2 の方が新しいフォーマットで圧縮率が高いので先に指定している。

私は今の今まで Windows の日本語フォントは UD デジタル教科書が最も良いが書体が教科書然として万人向けとは言い難いと思っていた。 しかし今日何の気なしに Windows 日本語フォント で検索して衝撃を受けた。 あのモリサワから Windows 10 向けに BIZ UD ゴシックというフォントが提供されている! しかも 1 年も前からという。 何故今の今まで気づかなかったのか、本当に悔やまれる。 プロポーショナルの BIZ UD P ゴシックと等幅の BIZ UD ゴシック、そして明朝体の BIZ UD (P) 明朝と用意されている。 早速 Google Chrome の環境設定でフォントをこれらで設定してみると、とても読みやすい。 一番気に入ったのは游ゴシック体などだと線が細くて小さい文字が見にくかったのがこのフォントだととても見やすいということだ。 今まで視認性の関係上仕方なくメイリオを使っていた場面でもこのフォントで代用できそうだ。

Web サイトに適用する為の CSS 表記が気になったのだが、Webページのテキストのフォントに BIZ UDゴシック BIZ UD明朝 を利用する (CSS Tips)によると以下のように書くようだ:

/** BIZ UD ゴシック */
font-family:"BIZ UDGothic";

/** BIZ UD P ゴシック */
font-family:"BIZ UDPGothic";

/** BIZ UD 明朝 */
font-family: "BIZ UDMincho";

/** BIZ UD P 明朝 */
font-family: "BIZ UDPMincho";

これで Windows だとフォントがイマイチという悩みがほぼなくなった。 一点、Web サイトによっては font-family: Meiryo が適用されており Chrome で BIZ UD ゴシックを指定していてもメイリオで表示されてしまう場合がある。 macOS だとそもそもメイリオが無いのでそういうサイトでも綺麗なヒラギノフォントで表示されるという利点はある。

Android Studio や PhpStorm を使っていて、昔は英語表記のまま使っていたので Pleiades で日本語化できると分かった後でもそのまま使っていた。 しかし一旦 Pleiades で日本語化して使ってしまうとそれはそれで慣れてしまって今度は Pleiades なしだと気になるようになってしまった。 今日も PhpStorm の更新があったのだが、マイナーアップデートがあった場合に設定項目がクリアされるのかその都度 Pleiades を適用し直す必要がある。 といっても以前 Mac や Ubuntu でやっていたような設定ファイルの手動書き換えでなく、インストーラで適用先のバイナリを選択するだけなので楽で助かっている。

1 台の Mac に Boot Camp などで macOS と Windows のデュアルブートにしているものとする。

US キーボードはシンプルだが日本語入力は設定が必要

各種ショートカットで macOS は Command キー、Windows は Ctrl キーを使用するため「同じキーバインドを設定する」だと少し語弊があるかもしれない。 要するに以下の要件を満たしたい:

  • IME の状態を左 Command 押下で直接入力、右 Command 押下で日本語入力に変更
  • Caps Lock を Ctrl に変更

前者は macOS で日本語キーボードを使用する時になっている設定と同じにしたいという意図だ。 今どちらの状態になっているかを意識せず単打で IME の状態を切り替えられるのでとても便利だ。 後者は US キーボードの Mac の Ctrl の位置がとても押しにくいので、Happy Hacking Keyboard などと同様の押しやすい位置に変更したい。

IME の状態を左 Command 押下で直接入力、右 Command 押下で日本語入力に変更

macOS

これは有名な Karabiner を使う方法で可能だ。 これに関しては Mac用 Apple英字配列(US)キーボードにおける日本語入力切替のおすすめ:Commandキーのみで実現がとてもよくまとまっているので、この通りやれば実現できる。

Windows

私が月配列を使っていた時に使用していた DvorakJ というキーリマップ用のソフトで実現可能だ。 Mac のキーボードの Command キーは Windows だと Windows キーとして認識されるので、DvorakJ の設定の「キーボード」->「単一キー」->「Win」で「左 Win」を「直接入力にする」、「右 Win」を「日本語入力にする」にすればよい。

Caps Lock を Ctrl に変更

macOS

macOS の場合標準機能のみでできる。 システム環境設定の「キーボード」から「修飾キー」ボタンを押下すると Caps Lock や Ctrl キーなどを差し替える画面が表示されるので、そこで Caps Lock に Ctrl を割り当てれば良い。

Windows

DvorakJ でできるのかと思っていたが、DvorakJ のレファレンスマニュアルにも書いてある通り DvorakJ (というより AutoHotKey) では仕組み上実現できない。 これに関してはレファレンスマニュアルに書いてある通り Ctrl2cap というソフトを使用することで解決できた。

Mac で Boot Camp を使う場合当然 Windows 10 が必要だ。 ちょっと試すだけならば Windows 10 の評価版を使用すればよいのだが、在宅勤務で使用するというのもあってそれで済ますのも憚られるところだ。 ちゃんとした Windows 10 Pro が欲しいのだが普通に Amazon などでパッケージ版を検索するととても高い。 何とか安く済ませる方法はないものか、と検索して探していたらこちらのブログの記事を見つけた。 普通に手に入れるよりかなり安い。 しかも日本語のサイト (Yahoo! ショッピング) で買えるので問い合わせの時も安心できる。 パット見怪しいサイトに見えるので大丈夫かな、と思ってしまうが Yahoo! ショッピングならばクレジットカード番号が店舗に直接渡るようなこともないだろう。

実際その店で購入してから 1, 2 時間もしたらライセンスキーが書かれたメールが送られてきた。 Windows 10 Pro でそのライセンスキーを入力したらちゃんと認証された。 これは便利だ。

自宅では 4K ディスプレイを使用していて、そちらで UD デジタル教科書体や Consolas を表示すると Mac には敵わないがそれなりに綺麗に表示される。 しかし低解像度環境での Windows フォントはとにかくプログラミングを行う気力が失せるほど見づらく汚い。 以前は同様に Consolas を使用していたが Consolas は欧文フォントなので IDE にもよるが日本語の部分はメイリオで表示されたりする (IntelliJ の場合はフォールバックフォントとして日本語フォントを使用できるので Consolas + UD デジタル教科書体ということができる)。

いい加減この見づらいのが何とかならないか、と探していて見つけたのが Myrica というフォントで ASCII 文字部分は Inconsolata を使用しているらしい。 Eclipse で表示してみたが、すごく綺麗ではないが Consolas よりは見やすい気がする。 ただ 4K ディスプレイでも使用してみたら個人的には Consolas の方が綺麗な気がした。 このあたりは個人の好みかもしれない。

というわけで、仕事でやむなく低解像度ディスプレイ Windows で作業する時は Myrica を愛用しようと思った。

仕事でバッチ処理を 24 時間実行する必要があってそうしていたが、Windows のスリープを無効にしていても何故かいつの間にかスリープになってしまって困っていた問題の対処。

MSeeeeN 様の Windows の電源設定で無効にしても勝手にスリープになる現象を回避するにはという記事を参考にした。 Windows にはスリープの設定以外にシステム無人スリープ タイムアウトという設定があって、電源ボタンを押さずにスリープ解除した時に指定時間でスリープに戻るという罠があるらしい。 私は確かに電源ボタンでなくキーボード押下でのスリープ解除を行っていたのでこれの可能性が高い。 参考サイトの通りレジストリを弄り設定を変更。

FF5 のクラウドセーブがフォルダ一覧に出てこない

私は Android 端末でドラクエ 5 や FF5 などのゲームで遊んで、その結果をクラウドセーブしている。 スクウェア・エニックスが提供するアプリのクラウドセーブは Google Drive を利用しているものが大半と思われる。 例えばドラクエ 5 でクラウドセーブを実施した場合は Google Drive のルートフォルダの下に DQ5 というフォルダが作成されそこにセーブデータが格納される。だが FF5 でクラウドセーブを実施してもルートフォルダの下には何も作成されない。一体 FF5 のセーブデータはどこに行ったのだろうか。

Google Drive の保存領域は普通にアクセスして見えるフォルダツリー (ルートフォルダ) と個々のアプリケーションからしか見えない AppFolder の 2 種類が存在していることを Google Drive API の仕様書を眺めていて知った。

AppFolder の確認方法

Web 上の Google Drive から確認できる。 画面右上の歯車マーク (設定) を押下し「アプリの管理」を選択する。 そうすると Google Drive へのアクセス権を保持しているアプリの一覧が表示されるが、例えば今回の FF5 の場合は非表示のアプリデータ: 254 KB などと表示されている。 セーブデータの表示はできないが「非表示のアプリデータを削除する」を選択すればデータを削除することはできる。

この AppFolder は結局 Google Drive の容量 (現時点で無料枠 15 GB) を使用してしまうが、一般のフォルダツリーに表示されないので間違って削除してしまうようなことが起きないし、余計なバックアップ格納用フォルダがルートフォルダ直下に乱立しないということでノイズが増えないという利点がある。

コジごみカレンダーの調整をしていて、今はサーバを立てなくてもこのように Google Drive に気軽にクラウドセーブを行うことができるのでそういう機能を実装するのもアリだと思った。 しかも一度実装してしまえば他にも簡単に使い回せそうだ。

数日間 Markdown を快適に書ける環境をいろいろ探していたが、結局 MarkdownエディタはTyporaとJotterPadで決まりだ! を見て同様に Typora と JotterPad を使用することにした。 Boostnote も良かったのだが Android 版の出来が悪いのが致命的だった。 現状 Dropbox としか連携できないし Dropbox 側の決まったディレクトリから移動することができない。 また保存フォーマットが Markdown テキストでなく JSON ライクな形式になっているのも微妙なところで、いくら Markdown 形式でエクスポートできるといっても気軽に見ようとした時に JotterPad が入っていないと見ることができない。 素の Markdown テキストならばどんな環境でも見ることができるので個人的にはそちらの方が嬉しいところだ。 また Boostnote はフォルダ分けに加えてタグ付けもできるが、個人的には管理が面倒なのでタグは不要だ。

Typora だとフォルダ分けしてそのアウトライン (エクスプローラのような階層化されたフォルダの状態) を左サイドバーで見ることができるし Markdown を書くとその場で整形されて表示される為プレビュー画面が分かれていないのが新しいと思った。 Redmine のように Textile で書かなければならない時に Textile 形式のエクスポートがとても便利だ。

歳のせいか分からないが、「あれ、これなんだっけ」といった事が増えてきたように感じる。 忘れそうなことは逐次 Markdown でメモ書きを残す癖をつけたいところだ。 この Blog も自分の備忘にとても役に立っている。

プログラマに特化した Markdown 記法のメモアプリ

昨日の記事で主に他人に対して Markdown でドキュメントを起こす手段は MkDocs がいいだろうという事になったわけだが、自分用のメモアプリでも Markdown を使いたいという欲求が出てきた。 Markdown でメモを残しておけば、もしアプリを乗り換えたい場合でも乗り換え先が Markdown 記法をサポートしていれば比較的簡単にデータを移すことが可能だ。

ちなみに今までは Google Keep を使用していた。 Evernote を使用していた時期もあったがゴチャゴチャしていて好みではなくすぐに止めた。 Google Keep はとてもシンプルなメモアプリで簡単に PC / Android 間でクラウド同期できるし、チェックボックスを使用して TODO リストを作ることも容易なので残作業の管理にとても役立っていた。 ただ、以下の点で少しだけ不満に感じていたのは事実だ:

  • 記法がプレーンテキストの為若干物足りない
  • フォルダ分けの機能がない (タグを使用して近い事はできるが)

MkDocs の情報を探すついでにクライアントアプリで代わりになるようなものを探していたら Boostnote がヒットした。

凄くいいなと思ったところ

  • Markdown 記法をサポートしているが表組とチェックリストに対応していること
  • Boostnote で生成される結果がただのファイルなので簡単に Dropbox などのクラウドストレージと連携できること
  • フォルダ分けに対応していること (タグにも対応している)
  • Vim キーバインドが使えること
  • Windows / Mac / Linux アプリだけでなく Android / iOS アプリが用意されていること

尚 Boostnote がサポートしている Markdown 記法に関しては公式の Blog 記事「仕事効率、学習効率を加速させるMarkdown記法の紹介」に詳しく書かれている。 テーブル記法もチェックリストも Qiita の Markdown 記法と同じとなっているのがありがたい (MkDocs も同じだが)。

このアプリを見ると真っ先に思い出すのは Qiita と連携できる同じく Markdown 記法のメモアプリ Kobito だが、今日見たら既に公開終了していた……。

現在 Android 版の出来がかなりイマイチ

Android 版も Google Play から落として使ってみたのだが、機能が全然足りていないし挙動が不安定でよく落ちる状態で正直イマイチだと思ってしまった。 記事を参照しようとすると編集画面になってしまってプレビューを表示したい場合は一旦保存しなければならない UI など全く練り込まれていない感じがする。 また Dropbox 連携ができる (Google Drive 非対応) 為試しに連携して使おうとしたところ記事を追加しようとすると 100 % クラッシュするという不具合に見舞われた。 にっちもさっちもいかないので Dropbox に作成された boostnote-mobile フォルダを Windows 側のアプリで Add Storage Location した。 そうしたら 1 つもフォルダが無い状態だったので 1 つ追加した上で Android アプリ側で記事を追加しようとしたら今度はうまくいった。

正直今のところ Android 側でちょっと見たいくらいの要件にしか使えない。 今後の更新に期待したいところだ。

Fall Creators Update で入ったフォント

Windows 10 の大型アップデートである Fall Creators Update が 10 月にあったわけだが、新しい日本語フォントである UD デジタル教科書体が入っていたのを忘れていた。 このフォントに関しては窓の杜に以下のように説明があった:

「UDデジタル教科書体」は、教育現場の要望に応えるため、ヒアリングや検証をもとに改良を重ねながら10年にわたり開発されてきた書体。筆運びの向きや点、ハライ、画数、筆順などは学習指導要領に準拠しつつも、太さの強弱を抑えてロービジョン(弱視)、ディスレクシア(読み書き障害)などにも配慮しているのが特徴。電子黒板やタブレット端末といったICT教育の現場で効果を発揮する可読性・視認性に優れるユニバーサルデザイン対応の書体となっている。

試そうと思っていたのを今日思い出したので早速 Full HD と 4K の液晶両方で見てみた。 Full HD でもまずまず綺麗に見えるのだが 4K 液晶で見ると確かにかなり綺麗だ。 ただ「教科書体」という名前からイメージする通り、いかにも教育用といった字体で macOS のポップなヒラギノ角ゴと比べるとちょっと好みが分かれるような気がした。 どちらかというと堅い文章を書く人に合っているかもしれない。 ということは私向きだろうか。

N, NP, NK の違い

  • UD デジタル教科書体 N-R
  • UD デジタル教科書体 NP-R
  • UD デジタル教科書体 NK-R

末尾の R はレギュラーということであり標準の太さという意味で分かるのだが N, NP, NK の違いが最初よく分からなかった。 調べてみるとどうも N は等幅フォント (但し半角英数は半幅) で NP は英数字がプロポーショナルになっており、NK は更にかなもプロポーショナルになっているフォントのようだ。 ということで普段指定する際は NK-R でいいだろう。

Blog をフォントに合わせてデザイン変更

気に入ったので、早速この Blog で指定しているフォントのプライマリをこの UD デジタル教科書体にしてみた。 合わせてフォントサイズも適切に変更してみた。 とても見やすくて満足だ。

今までは以下のように ASCII フォントを先頭に出して「英数字は Arial だが漢字とかなは sans-serif (多くは游ゴシック体やメイリオ)」という技法を使用していた:

body { font-family: Arial, sans-serif; }

今回も最初これでやってみたのだが、どうも UD デジタル教科書体のデザインと一般的な ASCII フォント (例えば Arial) の字体の雰囲気が合わない。 そこで今回思い切って全て UD デジタル教科書体に任せることにした。 UD デジタル教科書体の CSS の指定は以下のようにそのままの名前で指定するようだ (半角・全角に注意):

body { font-family: "UD デジタル 教科書体 NK-R", "Roboto", "Lucida Grande", Verdana, Arial, sans-serif; }

どうも半角英数字と全角英数字の見分けが付きにくいフォントのように思えるが、慣れかもしれない。 ともかく Windows でこれだけ綺麗なフォントで記述・閲覧できるのであれば、もうヒラギノ角ゴ目的で Mac を選ぶようなこともなくなるだろう。 勿論 Mac を選ぶ理由はフォントだけではない (技術者としては主に OS 自体が正当な UNIX であることに起因する) のだが、それは別の話である。

見やすさは yyyy 年 M 月 d 日形式が最高だが

今までコジオニルク (この Blog) では日付を示す形式として 2016 年 10 月 3 日10 月 3 日 などと書いていた。 日本人なら誰でも分かるし、何より読みやすい。 しかし最近 Nexus 5X で自分のページを見ていて気づいたことがあった。 日付の部分が妙に改行されてタイトル一覧が見辛い。

画面サイズが小さいスマホも視野に入れると

スマホと PC の両方でこのページを見ている皆さんならお気づきと思うが、コジオニルクは画面の広さ (というより横方向の有効ピクセル数) に従い自動的にレイアウトを最適化して表示するようになっている。 例えばギャラリーだと横方向のピクセル数によって画像を横方向に幾つ並べるかを変更するなどしている。 こういった画面サイズに応じて最適化する技術を Web の世界ではレスポンシブ Web デザインなどと呼んだりする。 Bootstrap ライブラリに標準でレスポンシブ対応する為の機能が付いているのでそれを活用している。

なので当初はこれで良いと思っており、自分自身はスマホで見ることが殆ど無かったので気付かなかった。 「2016 年 10 月 3 日」だとやたらと長いし好きな位置での改行を許してしまう。 とすると「2016/10/3」や「2016-10-3」が思いつくがどちらが良いのだろうか。

2016-10-03 は改行を許してしまう

日付表記に関して Wikipedia には以下のように書かれていた:

日付で、算用数字で表した月日または年月日を分ける。ただし、順序は国によって異なる。
2004/1/31 (1/31) - 日本、中国、韓国など
2004-01-31 (-01-31) - ISO 8601(参考)

スラッシュ区切りは広く知られている方法でありハイフン区切りは ISO 8601 で定義されている。 つまりどちらでもその時に合ったものを使えばいいように見える。

両方タイトル一覧の表示で試してみた。 2016/10/3 は改行されず、2016-10-03 はハイフンの後に改行されてしまった。 私はこの場合改行して欲しく無かったので 2016/10/3 の方を採用した。

但し Wikipedia に

算用数字で表した月日または年月日を分ける

と記載されているので年月のみ分ける場合はどうなのだろうと疑問を持った。 2016/3 などという記法だが公式にあるのかが分からない。

そこで年月日は 2016 年 3 月などと書いて月日または年月日は 3/15, 2016/3/15 などと書くように統一してみた。 日記のタイトルで「10 月 3 日」などと書いていたのが長くてタイトルが 2 行になっていたものが 1 行になるようになり多少見やすくなった。

今の時代 PC で閲覧する事のみを想定できない

最近の若者はスマホのみを使って PC を全く触らないので逆に私達の世代より PC の操作が覚束なかったりするらしい。 現にコジオニルクもスマホから参照されることが多いので、少しずつスマホに寄せていくように微調整していきたいところだ。

コーディング規約

Swiftコーディング規約@Wantedly が参考になったのでこれをそのまま使用している。 ちょっと驚いたのが定数が Upper Snake Case でなく接頭辞 k を付けた camelCase であることだ。 例えば let DEBUG_KEY = "hoge" でなく let kDebugKey = "hoge" となるということ。

先頭 k が最初奇妙に思えたが、しばらく Swift に触っていたら公式のライブラリなどもこの規則に従っているようなので正しく思えてきた。 よく考えたら Android も public でないフィールドには接頭辞 m を付けるという奇妙なルールを使用していたので、それと同じに思える。

JavaDoc 的なもの

Swift には JavaDoc 的なものが無いのかと思っていたのでコメントを適当に書いていたのだが、どうもあるようなのでそれに従うことにした。 Swift 2 のドキュメントコメントが参考になった。

三本スラッシュ /// で始めるとドキュメントコメントになるというのが結構便利に思った。 あとは markdown で書けばそのままドキュメントになるところとか、実にモダンだ。

CHAPTER 07 演算子

Swift に用意されている演算子とその優先順序、そして最近の言語にはよくある演算子を自分で定義できるという話。 実装方法はどうせまたその時に調べると思うので要点だけ書く。

  • 二項演算子は infix operator で定義する
  • 前置演算子は prefix operator で定義する
  • 後置演算子は postfix operator で定義する
  • それぞれ演算子の優先度を precedence で定義する
  • それぞれ演算子の結合規則を associativity で定義する

パターンマッチ演算子

Swift にはパターンマッチ演算子 ~= が用意されておりこれをオーバーライドすることで switch 文のパターンマッチの挙動を上書くことができる。 しかしこれはグローバルに定義されてしまうので対象を特定の列挙型に限定するなどの工夫が必要となる。

短絡評価をする演算子の定義

例えば三項演算子 a ? b : c みたいなものを自分で定義したい時に普通に書くと a を満たさなくても c が評価されてしまうのがまずい場合がある。 処理に時間が掛かる場合やログ出力を行う場合などだ。 こういう時は @autoclosure を使う:

// cond を満たさない時のみ処理を行う
func skip(cond: Bool, @autoclosure _ arg: () -> Int) {
    if !cond {
        print("value=\(arg())")
    }
}

CHAPTER 08 クラスと継承

クラスの概要

Java のクラスの知識がそのまま使えそうな雰囲気。構造体と違って mutating 修飾子は必要ない。

動的結合とキャスト

インスタンスの型が対象のものかをチェックする演算子は is でキャスト演算子は as, as!, as? である。 これは Kotlin と同様。

クラスメソッドとクラスプロパティ

なんか Python みたいだがタイプメソッドとタイププロパティ (static で記述するもの) の他にクラスメソッドとクラスプロパティ (class で記述するもの) がある。 class の方はサブクラスでオーバーライドできるが static のほうはできない。

指定イニシャライザと簡易イニシャライザ

Swift ではイニシャライザ (コンストラクタ) は init で定義するが init の中から他の init を呼ぶようなのを簡易イニシャライザ (他のイニシャライザの助けを借りるイニシャライザ) と良い convenience init で定義する。

必須イニシャライザ

required init で記述すると必須イニシャライザとなり継承先のクラスでも同一のイニシャライザを必ず実装しなければならなくなる。

遅延格納型プロパティ

Kotlin と一緒で lazy で指定すると遅延格納型となる。

CHAPTER 09 メモリ管理

この辺りは難しい話なので、読み物として読んでおくだけでいいのではと思う。

弱い参照

Java でいうところの WeakReference (弱参照) を実現するのに weak キーワードを使用する。

CHAPTER 10 プロトコル

要するに Java のインターフェース。

オプション項目のあるプロトコルを宣言する

必ずしも実装する必要のないメソッドやプロパティを宣言することができる。optional を先頭につければよい。

ネスト型とプロトコル

Java でいうところのジェネリクス (型パラメータ) は typealias キーワードで定義する。

CHAPTER 11 拡張

Kotlin と同様にすでにあるクラスに対し機能を追加することができる。 これをエクステンションと呼ぶ。

CHAPTER 04 オプショナル

今時の言語にはすべて搭載されている、ヌルポ対策機能。

オプショナル型と nil

Swift では null でなく nil で Objective-C には nilNull も両方あるらしい。 null 許容型 IntInt? とかく。これは Kotlin 等と同様。

オプショナル型の値を開示する

Int? 型を Int 型に変換するのに ! を使用する。確実に nil が入っていないと予想できるときに使用する:

let year: Int? = Int("2020")
var remain: Int = year! - 2016  // ! が無いとコンパイルエラー
year! -= 2016  // このように代入も可能

if-let 文

オプショナル型の値が nil ではなかった場合に処理をする、といった構文が if-let 文となる:

let year: Int? = Int("2020")
if let y = year {
    print("あと \(y - 2014) 年")  // y: Int として使える
} else {
    print("エラー")
}

// 複数のオプショナルがともに nil でない場合は以下のように書く
if let sapporo = Int("1972"), nagano = Int("1998") {
    print("\(nagano - sapporo) years.")
}

// where 句で更に条件を絞ることができる
if let sapporo = Int("1972"), nagano = Int("1998") where nagano > 1990 {
    print("\(nagano - sapporo) years.")
}

guard 文

if-let の逆、即ち条件を満たさない時に else 句の処理を行うことができる:

let stock = ["01", "2", "4", "05", "8", "q", "X"]
for str in stock {
    guard let v = Int(str) else {
        print(str + "??")
        break
    }
    print(v, terminator:" ")
}
// 1 2 4 5 8 q??

nil 合体演算子

オプショナル型に対し ?? で値を取り出すことで nil の場合にデフォルト値を使用するといったことができる:

opv ?? S  // opv が nil なら S が使われる. opv != nil ? opv! : S と同様

有値オプショナル型

プログラムの前後関係から確実に nil でない値が入っていると予想できる場合は Int? でなく Int! とすると使用する際に ! の開示が不要となる:

let year: Int! = Int("2020")
print("あと \(year - 2016) 年")  // ! が不要

失敗のあるイニシャライザの定義

init ではなく init? を使用する。例えば init への引数が防いで有効な構造体を生成できない時に nil を返すようにするなど。

CHAPTER 05 基本的なデータ型

部分配列

配列のスライスはどうやるのかと思ったら範囲指定がそのまま使用できるようだ:

let stock = ["01", "2", "4", "05", "8", "q", "X"]
print(stock[1...4])  // ["2", "4", "05", "8"]

但し上記でスライスした配列は Array<String> ではなく ArraySlice<String> になり、添字が元のままの 1, 2, 3, 4 になる。 これを普通の 0 から始まる配列として使用したい場合は Array<String> のイニシャライザで wrap する:

let subarray = [String](stock[1...4])
print(subarray[0])  // "2"

可変長引数

可変長引数指定は Java と一緒で Int... のようにする。 但し Java と異なり引数の途中でも可変長引数にできる。

辞書の型宣言と初期値

辞書の型は [String: Int] のように記述する。

var d: [String: Int] = [:]  // 空の辞書代入

辞書へのアクセス

「辞書のキーが存在したらなにか処理をする」のようなものは if-let 文が使える:

var d = ["Swift": 2014, "Objective-C": 1983]
if let v = d["Swift"] { print(v) }  // 2014
if let v = d["Ruby"] { print(v) }  // 何も出力されない

集合の型宣言と初期値

配列リテラルが使用できるが型を明示的に指定しないといけない:

var s: Set<String> = ["フランダース", "フランドル", "フランシスカ"]

CHAPTER 06 パターン

キーワード付きのタプル

タプルにキーワードが付けられるというのは知らなかった:

let photo = (file: "tiger.jpg", width: 640, height: 800)
print(photo.0)  // tiger.jpg
print(photo.file)  // tiger.jpg

タプルを switch 文で使う

結構柔軟なことができるようだ:

switch day {
case (1, 1...5):  // 範囲指定ができる
    print("正月休み")
case (4, 29), (5, 2...6):  // 更に条件を並べることができる
    print("連休")
case (8, let d) where d > 10:  // タプルの一部を使用することができるし where で条件を絞れる
    print("8/\(d)は夏休みです")
default:
    break
}

オプショナル型を switch 文で使う

オプショナル型を含むタプルに対し nil でないことを条件とするには ? を付けるようだ:

case let (name, age?) where age >= 18:  // 開示した数値を代入
case let (name, (15...18)?):  // 開示して区間指定

シンプルな列挙型

Java と似ているが case 接頭辞を付けるようだ:

enum Direction {
    case Up, Down, Right, Left
}

値型の列挙型

列挙型に実体型 (raw value) を割り当てることができるらしい:

enum Direction: Int {
    case Up = 0, Down, Right, Left  // こう書くと 0, 1, 2, 3 となる
}
print(Direction.Right.rawValue)  // 2
print(Direction(rawValue: 3)!)  // Left

共用型の列挙型

イマイチ使い所がよく分からないが、それぞれの要素の型 (タプル) が異なる列挙型も定義できる:

enum WebColor {
    case Name(String)
    case Code(String)
    case White, Black, Red
}

let background = WebColor.Name("indigo")
let tuiquoise = WebColor.Code("#04E0D0")
let textColor = WebColor.Black

if-case 文

switch 文だとパターンマッチングが使用できるが default 句を書かなければならず 1 つのパターンマッチングを行うだけだと冗長なので if-case 文という構文が用意されているようだ:

if case .card(let y, _) = t where y > 1200 { ...

for-in 文で case パターンを使う

for-in でも case が同様に使用できる。やはり switch だと冗長なので代わりに使用できるようだ。

再帰的な列挙型

……こんな構文使うのか?と思うので、メモだけ。自分自身の型を再帰的に使用する場合は case の前に indirect を指定し特別扱いする。

プログラミング言語 Swift の解説書として名著である詳解 Swift 改訂版の一人読書会を開始する。 ここには私が「なるほど」と思った Swift の特筆すべき文法を備忘録代わりに記録するものとする。

私は Android アプリの開発経験は 5 年以上だが iOS アプリの開発経験は無く Swift 経験も過去に公式ドキュメントを流し読みして Hello World した程度となっている。 なので Java などのプログラミング経験は豊富だが Swift 経験は無いという方がこの文章に一番マッチする対象読者となる。

CHAPTER 01 Swift でプログラミング

文字列

Swift の文字列埋め込みの記法は \(式) のようにする:

let n = 8
let str = "\(n) の 2 乗は \(n * n) です。"  // "8 の 2 乗は 64 です。"

print 関数

print 関数は Python のようにセパレータを指定することができる:

print(6, 2014, "林檎", separator:"; ")  // "6; 2014; 林檎"

Swift 1.2 までは println があったが Swift 2.0 からは print がデフォルトで改行するようになった。 もし改行したくない場合はキーワード terminator に空文字列を渡す:

print("ほげ", terminator:"")

配列

若干記法が独特だ:

// Int 型の配列は [Int] とかく
let a: [Int] = [2, 5, 8, 11, 7]

// 空の配列生成 (イニシャライザ呼び出し)
let s = [String]()
let s: [String] = []

Java と違って配列も値型のデータらしい。なので普通に他の変数に代入するとディープコピーされるようだ。

型に別名を付ける

ちょっとイマイチ使いどころが分からないが、型に別名を付けることができる:

typealias SInteger = Int32

repeat-while 文

Java や C の do-while にあたるものは repeat-while となっている。Swift だと do が他の文法で使用されている為だろう。

for-in 文

for-in (foreach) が使えるのは大体想像がつくが where でループ対象を絞り込むことができる:

for i in 1..<64 where i % 3 != 0 && i % 8 != 0 {
    print(i, terminator:" ")
}
print("")
// 1 2 4 5 7 10 11 13 14 17 19 20 22 23 25 26 28 29 31 34 35 37 38 41 43 44 46 47 49 50 52 53 55 58 59 61 62

switch 文

switchbreak で抜ける必要が無くなった。 break 必須というのはバグの元なので当然だろう。 もし Java や C でいうところのあえて break を書かずに続けて実行させるという場合は fallthrough キーワードを使用する。

do 文

変数のスコープを絞るのに Java や C だと {} で囲えばできるが Swift はできない。代わりに do 文を使う:

if a >= 0 {
    b += a
    do {
        // t はこのブロック内でのみ有効
        let t = a
        a = c
        c = t
    }
}

CHAPTER 02 関数

外部引数名

Swift では関数の第 1 引数のみキーワードを省略できるが第 2 引数以降はキーワードが必須という文法になっており、これは Objective-C を踏襲したものになっている:

func add(x: Int, y: Int) -> Int {
    return x + y
}
add(1, y:2)  // 本当は add(1, 2) と書きたいが許されない

第 1 引数もキーワード必須にしたり第 2 引数以降もキーワード不要にする文法もあり以下のようにする:

// 引数に別名を付けると第 1 引数でも必須となる
func add2(a x: Int, b y: Int) -> Int {
    return x + y
}

// 引数に _ を別名として付けると第 2 引数以降でもキーワード不要
func add3(x: Int, _ y: Int) -> Int {
    return x + y
}
add2(a:1, b:2)  // 両方キーワード引数
add3(1, 2)  // 両方キーワードなし

下線の特殊な用法

基本的に _ はワイルドカードとして無視するのに使える:

_ = myGreatProcess(10, 20)  // 結果を捨てることを明示
func compare(a: Int, _ b: Int, _: Bool) -> Bool { return a > b }  // 第 3 引数は使わない
func compare(a: Int, _ b: Int, option _: Bool) -> Bool { return a > b }  // 第 3 引数は外部引数としては要るが内部で使わない

inout 引数

Swift の関数の引数は値渡しだが inout を付けるといわゆる参照渡しになる。 ちょっと今の時点で使いどころがよくわからない。 PHP などでもよくある話だが参照渡しは分かりにくくなる元だ。

引数の値を処理中に変更できるようにする

Swift の関数の引数は定数だが var を付けると処理中に変更可能になる。 これも分かりにくくなるのであまり使わない気がする。

返り値を必ず使うための指定

@warn_unused_result という属性 (Java のアノテーションもしくは Python のデコレータみたいなもの) を使うと関数を呼び出した箇所で戻り値を使っていないと警告を表示するようになる。

CHAPTER 03 構造体

Swift は構造体があるしクラスもあるが、どう違うのかがよくわからなかったので調べてみたらこの Qiita の記事がうまくまとまっていた。 要するに構造体は値渡しになりクラスは参照渡しになるらしいので、比較的小さいデータ型を定義するのに構造体を使用するようだ。

構造体を定数に代入した場合

この辺りの話がちょっと Java の感覚と違ったので注意が必要だった。 構造体が値型なのでプロパティも let 扱いとなるようだ。 構造体で var で定義してあるプロパティであっても構造体を定数に代入すると var のプロパティが変更不可となる:

struct Date {
    var year = 2010
    var month = 7
    var day = 28
}
var d = Date()  // 2010-07-28
d.day = 29  // これは OK
var camp = Date(year:1998, month:8, day:8)  // 1998-08-08 変更可
let event = Date(year:2000, month:9, day:13)  // 2000-09-13 変更不可
event.day = 30  // これは許されない!

イニシャライザの定義

構造体のイニシャライザ (コンストラクタのようなもの) は init で書く:

struct Date {
    var year, month, day: Int
    init() {
         year = 2095
         month = 10
         day = 31
     }
 }

もちろん init を複数定義したり (コンストラクタのオーバーロード) もできる。

構造体の内容を変更するメソッド

構造体の内容を変更するメソッドを定義する場合は mutatingfunc の前に付ける。 そもそも内容を変更するのは推奨されないのであまり使うことはないだろう。

計算型プロパティ

計算型プロパティ (変更可能なプロパティ) にはゲッタとセッタを定義することができるが、以下の様な記法となる:

struct Ounce {
    var mL: Double = 0.0
    static let ounceUS = 29.5735
    init(ounce: Double) {
        self.ounce = ounce
    }
    var ounce: Double {
        get {
            // get 節のみの場合 get と {} を省略可能
            return mL / Ounce.ounceUS
        }
        set {
            // 仮引数を省略した場合 newValue という名前の引数として使用できる
            mL = newValue * Ounce.ounceUS
        }
    }
}
  • セッタが不要の場合 get{} が省略可能
  • セッタの仮引数は省略可能
  • セッタの仮引数を省略した場合 newValue という名前で引数を使用できる

計算型プロパティに対する特殊な設定

get でプロパティを変更するような場合は mutating を付加し set でプロパティを変更しない場合は nonmutating を付ける。 あまり使わない気がする。

プロパティオブザーバ

格納型プロパティの値が更新されるときにメソッドを起動するのをプロパティオブザーバと呼ぶ。 willSetzdidSet (要するに pre と post) で定義できる。 ログ出力とかで使えるかもしれない。

ちなみに willSet では newValue で参照でき didSet では oldValue で参照できる。

添字付け

要するに構造体を使って配列のような仕組みを自前で定義できるというもの。 subscript を使う。

struct A {
    let items = ["ほげ", "ふが", "はげ"]
    subscript(i: Int) -> String {
        return items[i]
    }
}
print(A()[1])  // ふが

昨日今日と妻が子供たちとママ友の所にお泊まりに行っているので、若干風邪気味なのも相まって自宅に引き篭もってプログラミングを行っていた。 いずれ必要になるので Blog にコメント機能を付加していた。

コメント機能を追加するにはスパム対策が必須

自前の Blog にコメント機能を追加する場合に考慮しなければならない最重要の問題はスパム対策だ。 何も対策をしない場合、手塩にかけて作った Blog が奇妙な URL やメールアドレス、英語などに汚染されたコメントで荒らされてしまう。

日本人のみ投稿できればいいのであれば、投稿する際に日本人しか回答不能な質問を付加して答えさせるのが有効だ。 例えば「十三たす四=」などといった感じだ。この場合 17 が飛んでくればコメントの投稿を許すこととなる。 まぁこれでもいいのだが、折角 Google が提供している画像認証用のライブラリを見つけたのでそれを使ってみた。 reCAPTCHA という。

reCAPTCHA で認証後に Ajax で送る場合

この記事の右下に「コメント投稿」というボタンがあると思うのでそれを押してみてほしい (ただボタンを押しただけではコメントは投稿されないので安心して欲しい)。 そうするとダイアログが開くが、画面左下に「私はロボットではありません」などというチェックボックスが表示される。 これをチェックすると時にはそのままで「人間であることの証明」が終わり、時には追加の証明手段として画像認証が表示される。 どういうロジックになっているのか分からないがすごい。

これの実装の仕方はこの解説サイトがものすごく分かり易かったので興味があればそちらを参照して頂きたい。 あと reCAPTCHA 公式を見るのもいい。

要するに JavaScript のライブラリを読み込んで指定された HTML タグを書くとそこに認証用のビューが表示される。 そこで認証を行うとフォームに g-recaptcha-response という ID, クラスの HTML 要素に認証済を示すトークンが埋め込まれるので、それをそのまま POST するなり Ajax で送るなりすれば良い。そんなに難しくはなかった。つまり jQuery だと以下で認証済トークンが取れる:

var gRecaptchaResponse = $('#g-recaptcha-response').val();

注意点として、この認証済トークンを POST (Ajax) した先でこのトークンが有効なものかの検査 (https://www.google.com/recaptcha/api/siteverify?secret={Secret key}&response={認証コード} に対し GET リクエストを送り戻りの JSON を見る) を行うが、 この g-recaptcha-response は使い捨てなので 1 回チェックを行ってしまうと次からは不正を示す {success: false} が返却されてしまう。 なのでこの検査はバリデーションチェック等がすべて終わりこれさえ通れば正常終了という箇所で行うのが良い。

CsrfViewMiddleware

Django 1.9 の場合最初に manage.py startproject した際に既に settings.py に以下のように CSRF 対策用のミドルウェアが組み込まれた状態となる:

MIDDLEWARE_CLASSES = [
    ....
    'django.middleware.csrf.CsrfViewMiddleware',
    ....
]

これを使う場合は以下のように form タグの中に CSRF 対策用トークンを埋め込む記述を行う:

<form action="." method="post">{% csrf_token %}

正しい CSRF トークンを付与していなかった場合 403 Forbidden が返却される。

jQuery で CSRF トークンを付与したい

最近よくあるのが POST する際に Ajax 通信にして JSON で結果を受け取りエラーだったらそのまま画面にエラーを表示し成功だったら画面遷移を行うといったものだ。 これを Django で使用しようとすると上記 CSRF トークンが邪魔になる。

不要な場合は CSRF ミドルウェアを除去する

他のライブラリを使用したトークンチェック等行っている場合は組み込みの CSRF チェックは必要ないので settings.py の 'django.middleware.csrf.CsrfViewMiddleware', の記述を削除する。

XMLHTTPRequest のヘッダに CSRF トークンを付与する

幸いこのあたりは Django 公式ドキュメントに書いてある。

// using jQuery
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie('csrftoken');

のように CSRF トークンが取得できるので以下のように Ajax 時に付与する:

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});