higan96技術メモ

https://github.com/higan96

CoreLocationで国、都道府県、市区町村の取得

import CoreLocation
 
let location:CLLocation = CLLocation(latitude: lat, longitude:lon)
geocoder.reverseGeocodeLocation(location, completionHandler:{(placeMarks, error) -> Void in
  if error == nil {
    if placeMarks.count > 0{
      let placemark: CLPlacemark = placeMarks[0] as CLPlacemark
      println(placemark.ISOcountryCode)     // JP
      println(placemark.administrativeArea)  // 都道府県
      println(placemark.subAdministrativeArea) // 群
      println(placemark.locality) // 市町村区
    }
  }else{
    println(error)
  }
})

コレクションはオプショナル型にしない

Swiftを始めてオプショナル型覚えたてで、オプショナル型使いたい病にかかってしまい、 メソッドの返り値のコレクションデータまでオプショナル型で返していました。

ですが、やっぱアンラップするのがめんどくさい。

そもそも、ArrayにもDictionaryにもisEmptyというメソッドが用意されているのだから、コレクションの中身がない場合を想定したコードを書くなら、オプショナル型を使わずにそれを使うべき。

なので、あるかないかわからないコレクションデータを扱いたい場合、空のコレクションを用意し、ない場合は空のコレクションを返したほうがいい

func getSomething() -> Array<Something> {
  //[Something]()
  items = Array<Something>()
  fetchSomething({(data, error) in
    if error == nil{
       if let unwrappedData = data {
          items.append(unwrappedData)
       }
    }else{
       // error
    }
    return items
  })
}

他にどんな書き方があるんだ、という話でもある 明らかに自分がアホだった

定義済みクラスで「Use of undeclared type "ClassName"」のエラー

とっくに定義済みのクラスなのundeclaredと言われて怒られた。

Use of undeclared type "ClassName"

解決方法

右側の「Taget Membership」でテストターゲットの方にもチェックを入れる。

原因

あるクラスのテストを書こうとクラスが定義されたファイルだけテストターゲットに含めても、そのクラスの中で使われているクラスであれば、そのクラスが定義されたファイルもテストターゲットに含めないとエラーが出る。

これは、ビルド時にも起こる。

自分はそういったケースはテストの時にしか発生しないと思っていたので、ちょっとはまった。

ダミーのjsonファイルからjsonデータを作る

サーバーサイドの実装がまだだけど、APIの仕様が決まっているようなときに。 開発が進んだらjsonファイルは消すか、ターゲットをテストだけにしよう。

How do I create dummy JSON data on the client in objective C / iOS? - Stack Overflow

let filepath = NSBundle.mainBundle().pathForResource("dummy", ofType: "json")
var jsonDict:NSDictionary?
        
if let unwrappedFilepath = filepath{
    let jsonData = NSData(contentsOfFile: unwrappedFilepath)
    if let unwrappedJsonData = jsonData{
      var error:NSError?
      jsonDict = NSJSONSerialization.JSONObjectWithData(unwrappedJsonData, options: nil, error: &error) as? NSDictionary
    }
}

Rspecでインスタンス変数に任意の値がセットされているかテストする方法

タイトルのままです。
GETメソッドなんかで、インスタンス変数の値に期待通りの値がセットされているかをcontrollerのテストで行う方法です。

it { expect(controller.instance_variable_get("@user").name).to eq  'hoge' } 

ここではインスタンス変数@userのnameが'hoge'であるかのテストをしています。

updateでバリデーションの検証

どっかでとちりそうなのでメモ
update - リファレンス - Railsドキュメント

バリデーションによる検証を行う

  • update
  • update_attributes

バリデーションによる検証を行わない

  • update_all
  • update_attribute

Rspecでbefore_actionなどをテストするときはAnonymousControllerを使うと便利

ApplicationControllerなどにすべてのControllerで読み込まれるbefore_actionなどを定義していて、そのbefore_actionをテストをしたいときは、AnonymousControllerを使うと便利です。

anonymous controller - Controller specs - RSpec Rails - RSpec - Relish

ようは、テストだけにつかうコントローラとアクションをテストの度に作って、before_actionなんかの振る舞いをテストできるわけです。

describe ApplicationController do
  controller do
    def index
    end
  end
end

これで、おわり。Annonymousコントローラのindexアクションがこれでできあがり。
最初、ルート設定が必要なのかなと思っていたけど、特に必要ないっぽい。

使いどころとしては、ApplicationControllerなので通常アクションを持たせないけどbefore_actionはここに書いている、っていうよくあるパターン。before_actionのテストをどこで書くのさ、となったときに他の特定の機能を持たせているコントローラに書くと、なにかそのコントローラに特有のテストのようになってしまうし、テストの条件が偏る。

要は、ApplicationControllerに定義した機能はApplicationControllerでテストしたほうがわかりやすいので、AnonymousController超便利ってことです。