Swiftのコンパイルはストレスが溜まるので
SwiftでiOSアプリを作成しているとコンパイル速度が遅くてストレス溜まるなーというタイミングが多々あるのでコンパイル速度というかストレスを減らそうという対応を幾つか記載。
やったこと
プロジェクトのコンパイル時間計測オプションを設定する
Xcodeプロジェクトの Bundle Settings
にある Swift Compiler - Custom Flags
で -Xfrontend -debug-time-function-bodies
を設定する
BuildTimeAnalyzer を入れる
BuildTimeAnalyzer プラグインをインストールする
現行バージョンではBuildTimeAnalyzerの更新中にビルドし直すとクラッシュするけど重いメソッドが見られるので便利。
InterfaceBuilderの自動コンパイルを止める
StoryboardかXibファイルを開いてInterfaceBuilderが表示されているときに Automatically Refresh Views
のチェックを外す。
Xcode -> Editor -> Automatically Refresh Views
これは多分 @IBDesignable
を使っているときくらいしか出番が無いけどスペックの低い端末で開発するときには便利。
Automatically Refresh Views
のチェックを外すと Refresh All Views
が有効になるので任意のタイミングで更新することができる。
コーディング
1. 型を宣言する
よく言われている対策だけど本当に効果があるので型は宣言するべき。
対応を忘れやすいのはこんな感じで引数にdictionaryを突っ込んでしまったりして。
NSError(domain: "domain", code: 0, userInfo: [ NSLocalizedDescriptionKey: "error message" ])
その他、コーディングで気をつけたほうがいいこと
細かく書く気分じゃないのでソース貼ります。メソッド名の横にコンパイル時間だけ書きます。検証用コードなので適当に書いています。
class ViewController: UIViewController {
// dictionary pattern 1
func dict1() { // 20.4ms
let error: NSError = NSError(domain: "domain", code: 0, userInfo: [ NSLocalizedDescriptionKey: "error message" ])
print("error: \(error)")
}
// dictionary pattern 2
func dict2() { // 1.9ms
let userInfo: [String: AnyObject] = [ NSLocalizedDescriptionKey: "error message" ]
let error: NSError = NSError(domain: "domain", code: 0, userInfo: userInfo)
print("error: \(error)")
}
// dictionary pattern 3
func dict3() { // 1.7
let domain: String = "domain"
let code: Int = 0
let userInfo: [String: AnyObject] = [ NSLocalizedDescriptionKey: "error message" ]
let error: NSError = NSError(domain: domain, code: code, userInfo: userInfo)
print("error: \(error)")
}
// ceil pattern 1
func height1() { // 21.6ms
let window: UIWindow = UIApplication.sharedApplication().windows.first!
let width: CGFloat = self.view.frame.size.width
let margin: CGFloat = (width-window.frame.size.width)
let height: CGFloat = ceil((width - margin) / 16.0 * 9.0)
print("height: \(height)")
}
// ceil pattern 2
func height2() { // 2.7ms
let window: UIWindow = UIApplication.sharedApplication().windows.first!
let width: CGFloat = self.view.frame.size.width
let margin: CGFloat = (width-window.frame.size.width)
var height: CGFloat = width - margin
height = height / 16.0 * 9.0
height = ceil(height)
print("height: \(height)")
}
// ceil pattern 3
func height3() { // 3.1ms
let window: UIWindow = UIApplication.sharedApplication().windows.first!
let width: CGFloat = self.view.frame.size.width
let margin: CGFloat = (width-window.frame.size.width)
var height: CGFloat = (width - margin) / 16.0 * 9.0
height = ceil(height)
print("height: \(height)")
}
// ceil pattern 4
func height4() { // 2.7ms
let window: UIWindow = UIApplication.sharedApplication().windows.first!
let width: CGFloat = self.view.frame.size.width
let margin: CGFloat = (width-window.frame.size.width)
var height: CGFloat = (width - margin) / 16.0
height = ceil(height * 9.0)
print("height: \(height)")
}
// CGRectGet pattern 1-1
func rectGet1_1() { // 2.3ms
let y: CGFloat = CGRectGetMaxX(self.view.subviews[0].frame)
print("y: \(y)")
}
// CGRectGet pattern 1-2
func rectGet1_2() { // 2.0ms
let frame: CGRect = self.view.subviews[0].frame
let y: CGFloat = CGRectGetMaxX(frame)
print("y: \(y)")
}
// CGRectGet pattern 1-3
func rectGet1_3() { // 1.8ms
let view: UIView = self.view.subviews[0]
let y: CGFloat = CGRectGetMaxX(view.frame)
print("y: \(y)")
}
// CGRectGet pattern 2-1
func rectGet2_1() { // 3.0ms
let y: CGFloat = self.view.subviews[0].frame.origin.y + self.view.subviews[0].frame.size.height
print("y: \(y)")
}
// CGRectGet pattern 2-2
func rectGet2_2() { // 1.8ms
let frame: CGRect = self.view.subviews[0].frame
let y: CGFloat = frame.origin.y + frame.size.height
print("y: \(y)")
}
// CGRectGet pattern 2-3
func rectGet2_3() { // 1.8ms
let view: UIView = self.view.subviews[0]
let y: CGFloat = view.frame.origin.y + view.frame.size.height
print("y: \(y)")
}
}
ビルドにかかった時間はこんな感じでした。ソース読んでもらえれば分かりますよね。
検証機のスペック