GitHub
iOS
Swift

Storyboardを極力使わずSwiftでGithubのissuesとpull requestsを一覧で見れるアプリ作る

More than 3 years have passed since last update.

業務で扱うGithubのリポジトリが20個くらいあってどこにissuesがあってどのpull requestsを見ていないかがわちゃわちゃしています。

なので管理したいなと、swiftでアプリ作ってます。

今回はSwiftに触れてみたいという思いなのでStoryboardは極力使わずコードのみという異端な方法で作っています。

Storyboardでできることをコードで書くのでコードが増えたり見通しが悪くなるのでどうやってるかとswiftで困ったことをまとめます。

個人的にはStoryboardがそれほど好きではないので、コードやplaygroundをうまく使いたい派です。Storyboard便利なんですけどね。

(こんなの)

写真 2015-04-02 23 18 46.png

個人でもしくわチーム内で使えばいいアプリなのでリリースするつもりはなく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)
}

を書けば許されるけどなんでなん?