業務で扱うGithubのリポジトリが20個くらいあってどこにissuesがあってどのpull requestsを見ていないかがわちゃわちゃしています。
なので管理したいなと、swiftでアプリ作ってます。
今回はSwiftに触れてみたいという思いなのでStoryboardは極力使わずコードのみという異端な方法で作っています。
Storyboardでできることをコードで書くのでコードが増えたり見通しが悪くなるのでどうやってるかとswiftで困ったことをまとめます。
個人的にはStoryboardがそれほど好きではないので、コードやplaygroundをうまく使いたい派です。Storyboard便利なんですけどね。
個人でもしくわチーム内で使えばいいアプリなのでリリースするつもりはなくTest Flightで配布します。
bonegollira/GitOdo
さて、気にしているポイントですが
Viewとロジックを分ける
Storyboardを使わないとViewのプロパティの設定とロジックがごっちゃになるのでextension
を使って分けます
protocol ViewComponentLayout {
func render ()
}
// Viewに関するコード
// funcは基本的にconfigure__***とautolayout__***の2種類
extension TableHeaderView: ViewComponentLayout {
// configure__***でプロパティのセット
func configure__self () {
self.contentView.backgroundColor = UIColor.whiteColor()
}
func configure__titleLabel () {
self.titleLabel.font = UIFont(name: "Helvetica-Bold", size: 12)
self.titleLabel.textColor = UIColor.blackColor()
self.titleLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
}
// autolayout__***でautolayoutの設定
// Cartographyを使ってます
func autolayout__titleLabel () {
layout(self.titleLabel) { titleLabel in
titleLabel.left == (titleLabel.superview!.left + 20) ~ 250
titleLabel.right == (titleLabel.superview!.right - 20) ~ 250
titleLabel.bottom == titleLabel.superview!.bottom - 5
}
}
// このview自体はaddSubviewせずrenderを呼ぶ
// addSubview、configure、autolayoutを設定
func render () {
self.contentView.addSubview(self.titleLabel)
self.configure__titleLabel()
self.autolayout__titleLabel()
}
}
// ロジックのコード
class TableHeaderView: UITableViewHeaderFooterView {
class var identifier: String {
return "TableHeaderView"
}
// viewパーツの初期化はこちらで
let titleLabel = UILabel()
var sectionName: String? {
get {
return self.titleLabel.text
}
set {
self.titleLabel.text = newValue
}
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
override init(reuseIdentifier: String?) {
super.init(reuseIdentifier: reuseIdentifier)
self.render()
}
}
と書いて
-
extension
でStoryboardでできたViewの設定を -
class
でロジックを
書いてます。
ただStoryboardの強みである
-
ViewController
同士のつながり - Viewの確認
の良さげなやり方が分かっていません。
エラーですぎワロタ
ぶちあたったエラー書いとく、swift関係なくてもだ
SourceKitクラッシュしまくり
orz
CocoaPodsでライブラリ入れられないん?
Swiftで書かれたライブラリのサポートはCocoaPodsのバージョン0.36かららしい
使っていたバージョンが0.35だったためアップデートで回避
http://www.infoq.com/jp/news/2015/01/cocoapods-adds-swift-framework
Dictionaryにnilいれらないん?
いれるならNSNull()
な
@selectorってどうやって書くん?
UIBarButtonItem(
barButtonSystemItem: .Add,
target: self,
action: "someMethod:"
)
とStringで書けばいい
クラスメソッドどうやるん?
class Class {
class func classMethod () {
// do something...
}
}
クラス変数どうやるん?
// getを省略してるで
class var identifier: String {
return "tableViewCell"
}
http://qiita.com/takkyun/items/384013e52f404773893b
にプロパティについて詳しくまとめてくださっています。
カスタムUITableViewCellでinit実装で文句言われるで?
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
// を実装すると
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
// を求められる
とrequired
で実装しないとエラーがでる。これ書いたら動くから原因はわかってません。
型宣言だけした空のDictionaryを作っておきたいで?
OptionalつけるとアンラップだらけになってややこしいのでArrayとDictionaryに関しては極力空の値をいれて初期化しておきたい。
// こっちをしたくない
var list: [String: String]?
// けどこうするとエラー
var list: [String: String] = []
// なのでこうする
let list = [String: String]()
追記
@akuraruさんに教えていただきました。
var list: [String: String] = [:]
でいける。
UITableViewDataSource実装してるで?
does not conform to protocol 'UITableViewDataSource'
と言われるのはUITableViewDataSource
のrequireメソッドを定義していないから。
swiftのバージョンがあがって?引数のOptional指定が変更になってたりして、web上にある古いUITableViewDataSource
のメソッドをコピペとかしたりしてると実装しているつもりでもエラーがでる。
ちゃんと
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
}
を補完で打ち込もう。
ちなみに僕はタイポでエラー言われてた。
省略形の3項演算子使えんのん?
:?
は使えないみたい
let str = nil :? "string"
と書けない
追記
@YoshimasaAokiさんに教えていただきました。
let str = nil ?? "string"
と??
でいける
didSet定義したやつ、init内で初期化しても呼ばれんのん?
// init内で初期化してもdidSetは呼ばれない
var prop: Bool {
didSet {
println(prop)
println(oldValue)
}
}
override init () {
// init内でセットしてもdidSetは呼ばれない
self.prop = true
super.init()
マクロどう定義するん?
public func rgba(r: Int, g: Int, b: Int, a: CGFloat = 1.0) -> UIColor {
let red = CGFloat(r)
let green = CGFloat(g)
let blue = CGFloat(b)
return UIColor(
red: CGFloat(red / 255),
green: CGFloat(green / 255),
blue: CGFloat(blue / 255),
alpha: a
)
}
SwiftってRefactor使えないん?
使えない
Autolayoutの設定のタイミングってどこが適切?
init
で全部NSConstraint
をつけてるけど本来はどのタイミングがいいのか?
initの実装でrequired求められるで?
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
を書けば許されるけどなんでなん?