LoginSignup
24

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-04-02

業務で扱う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)
  }

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24