TOKOROM BLOG

iOSとかVimとかその他日々の雑多な技術情報

Swiftで部分適用(カリー化) はてなブックマーク - Swiftで部分適用(カリー化)

Permalink

Swiftオフィシャルの部分適用

まず、Swiftオフィシャルな構文として

1
2
3
func addTwoNumbers(a: Int)(b: Int) -> Int {
  return a + b
}

というように引数を1つ1つ別の括弧で囲ってfunctionを定義すると

1
2
let add1 = addTwoNumbers(1)
add1(b: 2) //< 3

というかんじに、

  • まず、1つめの引数だけ部分適用(ここでは a
  • 部分適用したものに後から次の引数を適用(ここでは b

というのができる。

専用の書き方じゃなくてふつうのfunctionに部分適用できないの?

使うかどうかは別としてHaskellみたいに全ての関数に部分適用できたら面白いなーと。

また、上のような専用の定義にしちゃうと addTwoNumbers(1, 2) みたいな普通の呼び方ができなくなっちゃうし。

そんなとき、 Swiftの関数の引数は、常に一つ という記事に出会い、勉強になるなーと眺めていたら、あれ?ふつうのfunctionに部分適用するための関数作れるかもなーと思い立った。

実装

https://github.com/tokorom/partial-swift

1
2
3
func partial<A, B, R>(function: (A, B) -> R, a: @auto_closure () -> A) -> (B) -> R {
    return { function(a(), $0) }
}

これがXcodeでのバージョニングの決定版になるかも はてなブックマーク - これがXcodeでのバージョニングの決定版になるかも

Permalink

概要

この記事でできるようになること

  • 安定してInfo.plistの内容(ここではBuild番号)を変更できる
  • ふつうにRun Scriptで編集するとタイミングによってすぐにアプリに反映されないことがあったりしたがそれが解消される
  • Info.plistに差分がでないのでcommitのときに邪魔にならない

なお、この方法を教えてくれた熊谷さんがこの方法に行き着いた経緯や所感がこちらに詳しくまとめられています。詳細や考え方などをきちんと知りたいかたは是非、熊谷さんの記事をご一読ください!

必要な設定

  • Preprocess Info.plist file でInfo.plistをビルド前に確定させる
  • Run Scriptで${TEMP_DIR}/Preprocessed-Info.plistを編集する

以下、具体的な話をします。

Objective-Cで非同期処理のテストをシンプルに書く方法 はてなブックマーク - Objective-Cで非同期処理のテストをシンプルに書く方法

Permalink

非同期処理のテストってどう書いてますか?

標準のXCTest自体がサポートしていれば良いのですがそうではないので、非同期処理のテストを書きたい場合には、その仕組みを自作するか出来合いのライブラリを利用する必要があります。現実的な選択肢としては、

  • GHUnitやKiwiなど非同期処理をサポートしたテストフレームワークを利用する
  • GHunitの非同期処理のテストの仕組みを真似て抜粋したライブラリを利用する(意外とこれが多いかも?)
  • expectaなどのマッチャーライブラリに付属の非同期処理の仕組みを使う

となるかと思います。 ただ、私が調べた時点だとどれもしっくりきませんでした。

まず、GHUnitやKiwiなどを採択している場合には良いのですが、非同期処理のテストを書くという目的だけのためにそれらのフレームワークを使うというのは冗長すぎます。

また、GHUnitの非同期処理の仕組みだけを抜き出したライブラリもありますが、TestCaseの親クラスを決まったものにしないといけない(例えばGHAsyncTestCaseを継承したTestCaseで場合のみ利用できるとか)という縛りができるのと、非同期処理を発火する前にprepareとかを呼ばないといけないのがちょっと鬱陶しい。

そういう意味だとexpectaなどのマッチャー系のライブラリの場合、親クラスも限定されないし、非同期でマッチさせたいところでその機能を使うだけなのでとてもシンプルではあります。ただ、これはこれでマッチャーで非同期処理の完了を待つ性質上、マッチするときはいいけどマッチしないときはタイムアウトまでそこで処理が待たされるという大きな課題があります。

こうしたい!

ぼくとしては理想的にはこういうライブラリを使いたいと思いました。

  1. テストフレームワークを使っていなくても非同期処理のテストだけが実現できるシンプルなもの
  2. TestCaseの親クラスが限定されないほうがよい
  3. 余分なコードを書かずにシンプルに書きたい
  4. それを利用することでテストの実行が遅くなったりしない

しかし、当初探した限りではこの条件にマッチするものが見つかりませんでした。

Storyboardでの画面遷移をスマートにやる方法 はてなブックマーク - Storyboardでの画面遷移をスマートにやる方法

Permalink

これは potatotips第6回め で発表した この話 のまとめと後書きです。

Storyboardいいですよね!

Storyboardを使うことで、

  • 画面と画面が疎結合になる
  • 簡単な画面遷移ならノンコーディングで実現できてソースコードを汚さない

といったメリットがあります。

Storyboard登場以前だと、次の画面に遷移させるだけでも

1
2
3
4
#import "NextViewController.h"

NextViewController *nextViewController = [NextViewController new];
[self.navigationController pushViewController:nextViewController animated:YES];

といったコーディングをし、遷移元のViewControlelrは遷移先のViewControllerに依存する(importしないといけない)形でした。

しかし、Storyboardを活用することで画面遷移のために画面同士が密結合になることを避けることができるようになりました。

ただしStoryboardを使って今まで以上に悪くなるパターンがある

とはいえ、Storyboardも完璧ではなく、画面遷移時に次の画面になにか値を渡したいときにはこんな実装をする必要があります。

Xcodeのプロジェクトファイル(pbxproj)がコンフリクトしまくるのをなんとかしたい! はてなブックマーク - Xcodeのプロジェクトファイル(pbxproj)がコンフリクトしまくるのをなんとかしたい!

Permalink

2014/02/09 追記
コメントのところでやり取りしているようにmergepbxの作者さんから連絡があって、この記事で書いた問題が修正されました!
今現在は merge=mergepbx がいい感じになってきているのでそっちがオススメです。

複数人でプログラミングしているとpbxprojがやたらとコンフリクトする

例えば、

  • Aさんが AALabel.m をプロジェクトに追加して
  • Bさんが BBLabel.m をプロジェクトに追加して

とただそれだけなのにマージのときにコンフリクトするpbxprojさん。。。

ただそれぞれファイルを追加だけのことでコンフリクトするなんて…
どうにかならんもんかいとTwitterでつぶやいたところ、 @azu_re さんから有り難い教えが!