emahiro/b.log

Drastically Repeat Yourself !!!!

エンジニアのキャリアとして思うこと

エンジニアとしてのキャリアを今後どうしていくか、どうあるべきかの現時点を記録していこうと思います。

自分なりのエンジニアキャリアの考え方

一般的なエンジニアのキャリアの考え方は3種類あると思っています。
それは

  1. 技術突き詰める
  2. 技術をわかった上でビジネスする
  3. そのハイブリッド

の3つ。

では自分なりにどういうキャリアを歩んで行きたいのかって考えると、ずっと2だと思っていたんですが、最近は3も面白ろそうと感じるようになってきました。

なぜそう感じるようになったのかというと、単純に物作り、サービス作りって楽しいな、もっと大きくした時に、更に大きなフェーズで自分なりにモノづくりを楽しみたいなという思いができてきているからだと考えています。
エンジニアのスキルを持って、ビジネスをするのももちろん楽しそうですが、僕はまだ実感としては、コードを書く現場から離れずにサービスもグロースさせていきたいという思いが強いです。

なにより一つできるより複数のことをできた方が楽しいかなと。

今どうしていきたいか

技術もビジネスもできるハイブリットなキャリアを考える上で、「今」自分がどうしたいのかを考えてみると、今は「技術」に寄っている実感があります。

ビジネスをグロースさせる。
まだ見ぬ勝ちパターンを追求して、サービスが圧倒的に伸び始めている機会を体験したいという欲求はありつつも、伸びた先で待っているであろう課題解決をするためのスキルを今はとにかく身につけたいです。

使える言語やフレームワークへのこだわりはありませんが、少なくとも新しいシステムに触れることで、自分のキャリアの幅は広がり、解決できる課題も増えていくので、今はその課題の解決手段のパイを増やす作業をしていきたいです。

キャリアに課題を感じたときの指針

エンジニアとしてのキャリアを考えるに当たって、何か壁にぶつかったり、想定外の事態が起きて、自分の方向性に迷いが生じることがあります。

そういった時に、自分が提供しているサービス、プログラムが現実の生々しい課題に対して、どう切り込んでいるのかという感覚は捨てずにいきたいと考えています。

理由は、サービスはユーザーがいてこそ成り立つもので、ユーザーの趣味嗜好はこの時代、常に変化していきます。
そうした時に、ふとユーザーの方向や世の中のサービスの方向が変わった瞬間に顕在化するニーズを如何にはやくキャッチアップして、課題を解決するのか、その感覚を忘れずに行きたいなと思います。

サービスは生物であり、それを動かしているコードも生物です。
ニーズが変わればコードはそれに合わせて変わります。

エンジニアリングは課題解決が主たる業務なので、日々刻々と変化する市場とそれに対応するサービス、それを作っているコードが現実の課題に向き合っているのかどうか、そういう指針を持っていきたいと考えています。

今後どうしていきたいか

やはりサービス作りの現場にいたい気持ちがまだまだ強いです。
一方でソフトウェアだけの世界には限界があるように感じてもいます。

これからはオンラインだけでなく、オフラインでもサービスを起点として、ユーザーが繋がって、新しい行動を起こす、新しい価値観が生まれる、そういった世界観を作っていく仕事をエンジニアリングの領域をメインとしつつも関わっていきたい。。

エンジニアリングはどんな課題解決にも適用できると考えていて、サービスを作るだけでなく、そのサービスを支える全てのボトルネックの解消に適用できると考えています。
新しいツール導入したり、単純作業を自動化して、組織のパフォーマンスをあげたり等…

エンジニアリングはあくまで手段で、目標に向かっていく上で、その手段を用いて解決できること全てにエンジニアリングという武器として取り組んでいきたいと思っています。

スキルスタックにとらわれない、もっとメタな枠組みでのエンジニアリングの適用とでも言うのでしょうか。
そういった領域にすごく興味がありますし、良いサービスを作る上ではやっていきたいなと考えています。

iOS開発の学習に際して意識したこと

年明けから業務でiOS開発を担当することになったので、ここ一ヶ月半で何をして何をしなかったのかを書きます。

目標

一ヶ月でiOS開発に必要な知識のベースをつける

キャッチアップしないと行けなかったこと

  • Swift
  • Xcode
  • Cocoaプログラミング
  • Rx (含むリアクティブプログラミング)
  • 1通りObjectice-Cが読める

やったこと (最初の一週間)

ここで課題が発生します。
眠くなります。

ただ、トリセツ読んでるだけでは集中できずにすぐ眠たくなることがわかりました。
そこで手を動かそうと思います。

やったこと(次の一週間)

Appleの公式チュートリアル「Jump Right In」

これがすごく良かったです。
Xcodeの使い方からViewControllerとViewの関係、TableViewControllerまでの実装を学習できるのと、TableViewControllerがわかるとおおよそのアプリがどう作られているのかがわかるようになりました。
あくまで主観ですが。

これを一周完了した後にRxの学習をしました。
そしてつまづきました。

その段階で気づいたこと

  1. swiftを100%理解していない
  2. xcodeの操作で迷うときがある
  3. RxSwiftを理解するにはFRPをなんとなく理解する必要がある
  4. Cocoaプログラミングおろか、まだxcodeの使い方すらおぼつかない。

つまりまずやるべきは

  1. 開発にすぐ入れるレベルでのswiftの理解
  2. xcodeの使い方で迷わない

でした。

僕に限らず初学者にありがちなのが、開発環境構築や開発に必要なツールの理解が甘くて、挫折すること。
僕もその一人ではありますが、業務で行うにあたって挫折は許されないので、まずは開発環境の理解とswiftの理解に重きを置くことにしました。

んでそのタイミングでやることを絞り、

  1. xcodeとswiftの理解をすること

を最重要項目として

  1. Jump Right Inを何も見ずに作りきれるレベルで暗記する
  2. Swift 実践入門を読む
  3. CocoaプログラミングでJump Right Inに出てくるものは暗記する

でした。
優先順位としては

Swift > Cocoa >それ以外

って感じで進めることになります。

やったこと(残りの期間)

残りの期間はとにかく「Jump Right In」をひたすら写経。
わからないAPIAppleの公式リファレンスを読む。
幸いにして、Google翻訳ニューラルネットワークが導入されて翻訳精度が劇的に向上していたので、分からない分をそのまま邦訳かけても大意をつかめるところまでは可能でした。

上記を繰り返しておそらくですが、Jump Right Inは5〜6回くらい、公式リファレンスもわからないところは何度も調べたので、おおよそリファレンスのみかたや、実際にxcode上でAPIのソース読んだりとiOS開発にあたって必要なことを一気に頭に詰め込みました。
何度かやっているとswiftのお作法やappleのお作法も勝手にインプットされるので、いちいち確認することなく、とりあえずコーディング規約や言語仕様は当たり前だよねという感じで理解できるようになり、swiftも読めるようになってきました。

気づき

受験勉強しているときみたいでしたが、未経験のスキルを学ぶ時に、躓く箇所として

  1. ツールの使い方
  2. 開発環境の理解
  3. ググり方

っていうのはおおよそ共通して躓くところではないかと思います。
そこで、言語の仕様の理解と開発環境の使い方の理解に重きをおいて、短期間に一気に詰め込むっていうのは案外自分に向いている学習法であることに気づきました。
1ヶ月という比較的猶予を与えられていたので、スケジュールを微調整しながら学習することはできました。
とは言え、反省点も多く、最初に色々寄り道しなければもっと色んな学習をできたのではないかなと思います。

何か新しく学習することは、この仕事についている以上避けられず、また、いつ何時そのタイミングが訪れるかわかりません。

特に僕はエンジニアとしてのスキルはまだまだなので、多少効率が悪く、また、同じことの繰り返しで不安になることもありますが、そこは我慢して、どうすれば最短で業務に入れるのか、業務に入った後も自走しながらiOS開発をキャッチアップできるのかを考えて、今回のような学習をしました。
今は一通りのコードは読めるようになってきたので、多少なりこの学習方法は自分にあっていたのかなと思います。
学習に必要な期間、スキル、OJTなど、置かれた環境で異なると思いますが、学習方法の一つとして、写経を繰り返すっていうのは有効です。

※今はRxの理解が追いつかずつらい…

UIStackViewの削除に関しての追加学習

以前書いたカスタムUIStackViewクラス内の子要素を削除するの追記

  1. removeArrangedSubview()
  2. (UIView).removeFromSuperView

の動作の違いとなぜ2つのメソッドを使わないと完全に削除できないのかということについて。

removeArrangedSubview
https://developer.apple.com/reference/uikit/uistackview/1616235-removearrangedsubview

removeFromSuperview
https://developer.apple.com/reference/uikit/uiview/1622421-removefromsuperview

removedArrengedSubView addArrangedSubviewで追加したviewのみ削除する。しかし公式リファレンスによると

However, this method does not remove the provided view from the stack’s subviews array; therefore, the view is still displayed as part of the view hierarchy.

stack’s subview arrayは削除できない。 この stack’s subview array が残る。

そもそも stack’s subview array とは何か?

removeArrangedSubview(削除対象UIView)メソッドが動作して削除するとき

stack’s sarrangedSubview → 削除できる。 stack’s subview → 削除できない。

という動作がある。

  1. arrangedSubview → https://developer.apple.com/reference/uikit/uistackview/1616235-removearrangedsubview
  2. subview → https://developer.apple.com/reference/uikit/uiview/1622614-subviews

arrangedSubviews は subview の 配列の 集合体 add した時は stack view が subview としてこの arrangedSubview を追加する
remove した時は stack view が arrangedSubview の配列を削除する。
このとき、もともとの stack view の subview は削除しない。
階層構造として、stackview に紐づくarrangedSubview は削除するけど、stackview に紐づく subview は削除してくれない。

stackview
  subview
    arrangedSubview

という階層構造になっているのだと思う。storyboard上に出てこないのでわからない…
なので、removeArrangedSubviewした時に stackview 直下の subview は残るので、このsubview も removeFromSuperView() メソッドで参照を切り離さないといけない。

removeArrangedSubview(削除対象UIView) の後に (削除対象UIView).removeFromSuperView を使うのは公式リファレンスでも書かれているので、一般的な方法なのだと思う。

To prevent the view from appearing on screen after calling the stack’s removeArrangedSubview: method, explicitly remove the view from the subviews array by calling the view’s removeFromSuperview() method, or set the view’s isHidden property to true.

(削除対象のUIView).removeFromSuperview or (削除対象UIView).isHidden = true で残っているStackview を削除 or 非表示にする必要がある。

PhotoLibraryから画像を選択して画面に描画する実装

画像を選択してUIImageに表示させるという処理を実装します。

手順

UIImagePickerControllerDelegateUINavigationViewControllerDelegate を実装したViewControllerに継承させます。

UIImagePickerControllerDelegate…UIImagePicler → Libraryから画像を取得(pick)するためのViewController UINavigationControllerDelegate…画像を 取得するControllerに遷移しているのUINavigationViewContorollerを介して(動作としてはUINavigationViewController)いるので、この動作を対象のViewControllerに移譲する。

UIImagePickerControllerDelegateを継承することで、

func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {}

の2つのメソッドが対象のViewControllerで利用できるようになる。

上記2つのメソッドについては Cancel は写真ライブラリから戻るときだとわかりやすい。

imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) のメソッドは UIImagePickerControllerDelegate プロトコルの持っているメソッド。

公式リファレンスはこちら
https://developer.apple.com/reference/uikit/uiimagepickercontrollerdelegate/1619126-imagepickercontroller

第一引数 picker … The controller object managing the image picker interface. ピックアップする動作(interface)
第二引数 info : Dictionary…
A dictionary containing the original image and the edited image, if an image was picked; or a filesystem URL for the movie, if a movie was picked. The dictionary also contains any relevant editing information. The keys for this dictionary are listed in Editing Information Keys.

originalImageとeditedImageをdictionaryが持っている。
JumpRighitInではoriginalimageを使っている。

UIImagePickerControllerOriginalImageの公式リファレンスは以下
https://developer.apple.com/reference/uikit/uiimagepickercontrolleroriginalimage

let UIImagePickerControllerOriginalImage: String

UIImagePickerControllerOriginalImage はImageと付いているが、UIImageを取り出すためのKey。
infoにKVSでUIImageが格納されている。

infoに保存されているUIImageのdectionaryでvalueを取り出すためのキーの一覧
https://developer.apple.com/reference/uikit/uiimagepickercontrollerdelegate/editing_information_keys

公式のリファレンス見ると、iOS側のimagePickerControllerで用意されているものが多く、普段使っているアプリ内の画像選択でも似たいような処理になっているところは多いので、イメージしやすかった。

コードからTableViewのeditボタンを生成する

UINavigationViewControllerをEnbedInしている状態で編集ボタンをコードから生成する。

navigationItem.leftBarButtonItem = editButtonItem

これで該当NavigationControllerを設置している箇所に対して、左上に編集ボタンを配置できる。

また、TableViewControllerで、

// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    // Return false if you do not want the specified item to be editable.
    return true
}

// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        // Delete the row from the data source
        tableView.deleteRows(at: [indexPath], with: .fade)
    } else if editingStyle == .insert {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }
}

上記箇所のコメントアウトを外す。

// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    // Return false if you do not want the specified item to be editable.
    return true
}

編集可能にする上記はTrueにする。

NSCodingのinitについて

さまり

Jump Right In でNSCodingを初期化する時に required と convenience を使って初期化している意図がわからなかったので調べた話

NSCodingの初期化について

公式のリファレンス https://developer.apple.com/reference/foundation/nscoding/1416145-init

init(coder:)
Required. Returns an object initialized from data in a given unarchiver.

NSCodingのinitの実装箇所にジャンプしても require 修飾子はついていなかったものの、公式リファレンスには、require が必須と書いてあった。

NSCoding は2つのメソッドの宣言を必要とする

  1. encode(aCoder: NSCoder) → KVOで値を保存(Archive)する
  2. init(aDecoder: NSCoder) → KVOで保存した値を解凍(UnArchive)する

上の2つのメソッドを宣言することでモデル層でKey Value Object形式であたりをアプリ内に保存します。

UIViewControllerのprepareメソッドについて

さまり

  1. prepareメソッドが理解できずにいた件
  2. swiftの外部引数と内部引数について

prepareメソッドが理解できずにいた件

prepare(for: ,sender:)メソッドがなかなか理解できずにいて、ようやく理解したので、その備忘録です。

まずprepare(for: ,sender:)について公式のリファレンスでは以下のように記載されています。
公式リファレンス

prepare(for:sender:)
Notifies the view controller that a segue is about to be performed.

func prepare(for segue: UIStoryboardSegue, sender: Any?)
// segue ... The segue object containing information about the view controllers involved in the segue.
// sender ... The object that initiated the segue. You might use this parameter to perform different actions based on which control (or other object) initiated the segue.

訳すと、segueが動作することをViewControllerに通知するということ。
取る引数については
segue : 動作するsegue
sender : 次のViewControllerに送信するObject(Any?だからなんでも送れる)

んで何がわからなかったかというと、メソッドのリファレンスにある (for segue: UIStoryboardSegue, sender: Any?) っていうかしょ。
for ってなに?っていうのが最初に抱いた疑問でした。

実装コードの中で親クラスの prepare メソッドを呼ぶ時に

super.prepare(for: segue, sender: sender)

って記述があって、最初のほう、頭混乱してました。
で結果なんですが、これ外部引数と内部引数なんですね。

外部引数と内部引数について

swiftはメソッドの呼び出し時に使用する外部引数と、メソッドの内部で利用する内部引数の2つを持つことができます。
外部引数と内部引数を分けるためには、 外部引数名 内部引数名 : 型 と書き方をします。
prepareメソッドで prepare(for segue: UIStoryboardSegue, sender(Any?)) と記載されていた箇所ですが、

for : 外部引数
segue : 内部引数

だったわけです。そのため、swiftでメソッドをドキュメント等で記載する時に prepare(for:,sender:) という書き方をしていたわけです。
ドキュメント等への書き方の場合は、外部引数を使います。
外部引数と内部引数がわかると、segue という変数はメソッド内部で変数の振る舞いがわかりやすいから内部引数と外部引数で分けています。
swiftでは可読性を上げるために、外部引数と内部引数を併記する場合があります。

例えば、ユーザーを特定のグループに招待するというメソッドを考え見ると

func invite (user : String, to group: String) {
    print("\(user)\(group)に招待します。")
}

となります。 この場合このメソッドをコールするときには

invite(user: "Taro", to: "Swift")

となり、誰をどのグループに呼んだのか、メソッドからわかり、可読性が上がります。
ただし、inviteメソッド内部では、変数が to のままではメソッド内部の振る舞いがわかりづらいので、メソッド内部では group という変数を使ってメソッド内部での可読性もあげています。

使うと非常に便利ですが、まだ、外部引数と内部引数を分けたコードについて、読み慣れていないので、prepareメソッドの理解の部分でハマりました。

emacsのパッケージをcaskで管理する上で気をつけていること

emacs のパッケージ管理

  • emacs 25.1
  • cask を使ってパッケージの管理をしていたりします

一応githubemacsのパッケージリストは公開中
my emacs conf

えぐさま

  1. Vagrantで立ち上げた仮想環境でcaskが動作しない
  2. Macでcaskを入れる場合とcentOSでcaskを入れる際の手順が違っていた
  3. centOSでcaskを入れる
  4. 作成済み.emacs.dのディレクトリ内にあるCaskを使ってパッケージをインストールする

手順とハマったところ

手順

  1. centOSyumemacsを入れる
  2. centOSにcaskを入れる
  3. caskでパッケージをインストールする

centOSyumemacsを入れる

まず最初にここでハマりました。

$ sudo yum install -y emacs
# emacs 23.* がインストールされてしまう

yumで管理されているemacsのパッケージが古く、自分の用意したemacs のcaskで管理しているパッケージが25.1用だったので、cask登録時にバージョン違いのエラーが起こりました。

そこでcentOSemacs 25.1 を入れます。
yumで入れられないので、ソースからコンパイルします。

このあたり参考にしました。
Installing Emacs 25.1.1 on CentOS 6.8

$ sudo yum install -y xz
$ curl http://core.ring.gr.jp/pub/GNU/emacs/emacs-25.1.tar.xz | tar Jxf -
$ cd emacs-25.1/
$ ./configure --without-x
$ make
$ sudo make install
$ emacs --version
GNU Emacs 25.1.1
Copyright (C) 2016 Free Software Foundation, Inc.
GNU Emacs comes with ABSOLUTELY NO WARRANTY.
You may redistribute copies of GNU Emacs
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING.

caskをインストールする

Macではbrewで提供されているので、brew入れた後にパス通してくれますが、centOSはソースからビルドするので、パスを通す必要あり。

$ curl -fsSL https://raw.githubusercontent.com/cask/cask/master/go | python
$ export PATH="$HOME/.cask/bin:$PATH"

ここでcaskのファイルはリポジトリの中にある
caskのコマンドを実行した時に、すでにインストールしていた.emacs.d のディレクトリ配下の.cask以下にコマンドを移動する

caskでパッケージ入れる

# コマンドは以下
$ /.cask/.cask/bin/cask
$ cd .emacs.d/
$ cask
# cask-bootstrap cask-cli cask がなくcaskが実行できない
# この状態でemacsを起動するとcaskがないと言われて起動できない

Macbrew経由でcaskを入れた場合はこのあたりをよしなにしてくれていたけど、CentOSでソースから入れた場合はcaskの立ち上げ*.elファイルを.emacs.d/.cask配下に置かないとcaskが起動しない。

$ cd
$ cp .cask/cask-bootstrap.el ../.emacs.d/.cask/
$ cp .cask/cask.el ../.emacs.d/.cask/
$ cp .cask/cask-cli.el ../.emacs.d/.cask
$ cd ../.emacs.d/
$ cask
# これでcaskが実行されてパッケージが入る

カスタムUIStackViewクラス内の子要素を削除する

UIStackViewとは?

iOS9から導入された概念
UIView郡をUIStackView内に入れ子として管理できる。
UIStackViewが親でUIButtonなどの各UIパーツが子要素になる。

Apple公式チュートリアル内でボタンを削除する

JumpRightIn

対象となるコードはこちら(抜粋)

private var ratingButtons = [UIButton]()

// clear any existing buttons
for button in ratingButtons {
    removeArrangedSubview(button)
    button.removeFromSuperview()
}
ratingButtons.removeAll()

UIStackViewの削除

メソッドの一つ一つ動作

  1. removeArrangedSubView でUIStackViewに割り当てられているUIパーツの配列から該当UIパーツを削除する
  2. burron.removeFromSuperview でSuperViewからUIButtonの参照を外す
  3. ratingButtons.removeAll() で配列を空にする

arrangedSubview はSubview(ここではUIStackView)に組み込まれたViewのこと。公式チュートリアルでは星型のUIButtonがこれにあたる。
このarrangedSubview は中に配列としてUIパーツを持つので、最初に対象のUIパーツをこの配列から外す。
次に、removeFromSuperView で対象のUIパーツの参照を親のViewから外す。

これで参照されるUIパーツがUIViewから削除されて新しくボタンを定義できるようになる。

参照 メソッドの意味

iTermのブルーが見づらかったので調整した話

iTerm2で青色がすごく見づらかった…

iTerm2で作業する時に青が見えづらくてしかたなかったので、青の文字の色彩を調整しました。
調整の仕方は、iTerm2の設定(Cmd + ,)を開いて、Profile -> Defauktの外観の設定 -> Colorを選択
Minimun Contrastを調整して、コントラストをいい感じにすると背景の黒と青文字のコントラストが変わって見やすくなります。

Markdownを書こうとしたり、ターミナルでディレクトリ見たりする時に大体、青色がものすごく見づらかったので、非常に目に優しくなりました

image

Bundleを使った画像のロードとキャッシュ from Apple公式チュートリアル

AppleiOS開発の公式チュートリアルに記載されている画像の読み込みについての備忘録。
画像はAssetsに入っているものとし、アプリ内で保持している画像を読み込むという前提。

対象箇所

Appleの公式チュートリアル「JumpRightIn」での画像を指定している箇所は以下。

// Load Button Images
let bundle = Bundle(for: type(of: self))
let filledStar = UIImage(named: "filledStar", in: bundle, compatibleWith: self.traitCollection)
let emptyStar = UIImage(named:"emptyStar", in: bundle, compatibleWith: self.traitCollection)
let highlightedStar = UIImage(named:"highlightedStar", in: bundle, compatibleWith: self.traitCollection)

画像の読み込みとキャッシュの方法について

定数ごとに考察していく。

let bundle = Bundle(for: (type: self)) について

これは、公式のリファレンスを参照すると省略せずに記載すると以下のようになる。

let bundle = Bundle.init(for: (type: self))

公式リファレンスには

//Creating and Initializing a Bundle

init(for: AnyClass)
Returns the NSBundle object with which the specified class is associated.

とあって、任意のクラスに関連する NSBundle オブジェクトを返す。

let **Star = UIImage(named:, in: bundle, compatibleWith: self.traitCollection) について

次にUIImageを初期化している箇所について触れていく。
UIImageの初期化の方法は省略せずに書くと以下

let **Star = UIImage.init?(named: String, in: Bundle?, compatibleWith: UITraitCollection?)

第1引数…Assetsに登録した名称を入れることでAssetsに登録した画像を使える。
第2引数…Bundleオブジェクトを指定することで画像をキャッシュできる。どういうことかというと、Bundleは入れ物オブジェクトのようなものなので、定義したBundleの中に、empty/filled/highlited の3つのステータスの画像を入れることで、3つの画像アセットをキャッシュすることができる。
第3引数…ここでのselfはRatingControlクラスそれ自体を表す。traitCollectionは該当の画像がUIStackViewに関連付けられているかを確認する(公式リファレンスだと、正確にするという訳がつけられる。)
ちなみにnilを入れることも可能であるが、nilの場合、RatingControlのStackViewではなく、この画面のUIView本体に紐づくので、ここではselfでRatignControlクラス自体を指定していると思われる。

参考

以下公式リファレンス参照
Bundle
UIImage
UIImage.init?
Array
enumrated

AtomでMarkdownを使うためのセットアップ

atommarkdownシンタックスハイライトとライブプレビューを使うお話です。

使っているパッケージ

  1. language-markdown
  2. linter-markdown

Core 1. markdown-preview

Markdownプレビュー

Ctl + Shift + Alt を同時に押した状態でキーボードの「M」を押すとMarkdownのプレビューが見れる

お試し投稿

お試し投稿です。

jekyll now で作ったgithubページから移行

もともと jekyll now を使った静的ページでブログ書いてましたが、画像等々を上げる時にホストするサーバーだったりを用意したりするのがめんどくさかったので、どうしようか考えたところ、はてブmarkdownでブログかけるtコトをしったので、思い切ってこちらに変更しました。
とりあえず過去にjekyllで書いた記事はこちらに移行。

ちなみに、はてブには今まで通り技術的な学習の記録だけ書いて、とりあえず無駄なつぶやきは note に書き流していこうと思います。