文字っぽいの。

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

Swiftで与えられたIndexがArrayのindex有効範囲内にあるか確認する

こんな感じ。

let array = [2,3,5,6,9,10]
let index = 0

if 0..<array.count ~= index {
    let value = array[index]
} else {
    print("Out of range: \(index)")
}

indexを適当にいじってみるとわかりやすいです。今回はArrayでやりましたが、 index がある数値範囲にはいっているかを調べるのにも便利です。

エンジニア立ち居振舞い:なんでもかんでも技術で解決しない

お題「エンジニア立ち居振舞い」

面白そうなので便乗する。

だいたい表題通りで、エンジニアはエンジニアリングができてしまうので、エンジニアリング(技術)で解決できる or できないの視点で見がち。 自動化とかスケールするかとかの話も好きなので、自動化できてかつスケールするような仕組みを、新機能を作り始める初期から考えることが多い。

例えば、「今日のおすすめ10選」という毎日更新される機能を実装しようとなった時に、「じゃあLIKEが付いた順と更新日時でいい感じに計算して、バッチ処理でもしましょう。」となる。 ただ、その機能を実装するためには工数がかかるし、そもそも「今日のおすすめ10選」によってKPIにどのくらいの影響があるか分からない。 わからないのにそこに工数を割いてしまうと「なんかすごい時間かかって疲れて作った機能だけどユーザには全然使われない。」という不幸を産んでしまう。

これは正解では無いと思うけど、

  • 簡素な管理画面を作り、当番制で登録
  • 管理画面にあれこれ便利機能を追加
  • 読まれる記事の傾向が分かってきてるはずなのでアルゴリズムを組んで自動化

という手順を踏んでいった方が、無駄に疲れることは減りそう。

エンジニアリングでガッと解決するのはかっこいいし気持ち良いけども、ユーザが得られる幸福量が変わらないのであれば、初期は泥臭く人間の力によって解決していけば良いと思っている。コード量が増えれば増えるほどバグも増えますからね。

なので、なるべく小さな実装で施策や新機能を試せるように、設計や提案の段階で発言できるように考えて立ち居振る舞っている。

※自動化をしなくても良いとか、技術で解決してはいけないという話ではない

Swift3でCornerRadiusが効かない、というか崩れて背景色がおかしくなる。

UITableViewCellの中でよくやってた、

override func layoutSubviews() {
    super.layoutSubviews()

    someView.layer.cornerRadius = someView.frame.height / 2.0
    someView.clipsToBounds = true
}

という書き方だとはViewが崩れたり、角丸にならなかったり、背景色が反映されなかったり(実際は反映されてるんだけどViewのサイズがおかしいからか見えない)する。

こう書けば良い、

override func awakeFromNib() {
    super.awakeFromNib()

    layoutIfNeeded()
    someView.layer.cornerRadius = someView.frame.height / 2.0
    someView.clipsToBounds = true
}

layoutIfNeeded() を先に呼んでおけば良いらしいです。

参考

stackoverflow.com

Swift3でオブジェクトのシリアライズ・デシリアライズがうまくいかなくなった問題の対処

いままではこんなふう required init?(coder aDecoder: NSCoder)に書いていた。

guard let id = aDecoder.decodeObject(forKey: "id") as? Int else {    
    // なんかする
    return
}

Swift3 & Xcode8環境下では、idにずっとnilが返ってきて、デシリアライズができなくて困っていたらこうすればよかった。

let id = aDecoder.decodeInteger(forKey: "id")

ただこの方法だとdecodeに失敗した際に常に0が返ってくる。違う書き方があるのだろうか……。

iOS10でUIToolBarが半透明じゃなくなる問題対策

ここ読んだら書いてあった、

# swift3

toolbar.setBackgroundImage(UIImage(), forToolbarPosition: .any, barMetrics: .default)
toolbar.setShadowImage(UIImage(), forToolbarPosition: .any)
toolbar.isTranslucent = true

UITabBarUINavigationBar を透明(半透明)にしたいときも同じような処理が必要そうです(未調査)。

Swiftで配列の一番最後のIndexをおしゃれにとる

毎回忘れてTwilog見に行ってるので書いておく。

let array: [Int] = [1, 2, 3, 4, 5]
let lastIndex = array.endIndex.predecessor()
print(lastIndex) // => 4

gitのpre-commitで、変更のある"*.swift"ファイルだけSwiftLintをかける。

題名の通り。git commitにHookして、変更がある*.swiftファイルにのみLintをかける。Lintでコケたらcommitされなくて便利。

#!/usr/bin/env ruby
require 'yaml'

LINT_CONFIG_FILE_NAME = '.swiftlint.yml'

updated_swiftfiles = `git diff --cached --name-only --diff-filter=AM -- '*.swift'`.split("\n")
exit if updated_swiftfiles.empty?

lint_config = YAML.load_file(LINT_CONFIG_FILE_NAME)
default_included = lint_config['included']
lint_config['included'] = updated_swiftfiles

open(LINT_CONFIG_FILE_NAME, 'w') do |file|
  YAML.dump(lint_config, file)
end

`swiftlint lint`

lint_config['included'] = default_included
open(LINT_CONFIG_FILE_NAME, 'w') do |file|
  YAML.dump(lint_config, file)
end

こういう内容を "your-repo/.git/hooks/pre-commit" に書いておくだけ。