Swift4 CoreData まとめ

いろいろ探したけど、CoreDataについてまとめた、いい記事がなかったので作成します。

作るものはこれ

座標値を入力して、Coredataに保存する。 保存したデータはtabelViewに表示される。

f:id:happy_teeth_ago:20191220083715g:plain

  1. まず、アプリ作成時に Use CoreData にチェックを入れる。

    xcdatamodeldはこれ

f:id:happy_teeth_ago:20191220084214p:plain

codegen をmanualにしているので、

Editor>Create NSManagedObject Subclassを選択。

ファイルを生成

f:id:happy_teeth_ago:20191220084721p:plain

まずlocationを定義

//locationにはCoredataのLocation型が入るよ
   var location: Location? {
//値がセットされたら更新しようね
didSet{
//nilのときは落ちるのでバインディングしておこう!
        guard let location = location else {
            latitudeValue.text = nil
            longitudeValue.text = nil
            return
        }
        latitudeValue.text = String(location.latitude)
        longitudeValue.text = String(location.longitude)
        
        }
    }

Bootstrap ハンバーガーメニュー 忘備録 見ないこと

ハンバーガーメニューとは

これ f:id:happy_teeth_ago:20190430112530p:plain このページにハンバーガーの実装が掲載されていた。

https://codepen.io/ProfessorTony/pen/Ypaejg

しかし動かない!

で調べてみると

<script src="https://cdn.jsdelivr.net/bootstrap.native/1.0.4/bootstrap-native.js"></script>

通常のJavaScriptで実装 されていた。

Bootstrapならもっと簡単なはず

本家サイトを確認。

getbootstrap.com

<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarTogglerDemo03" aria-controls="navbarTogglerDemo03" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <a class="navbar-brand" href="#">Navbar</a>

  <div class="collapse navbar-collapse" id="navbarTogglerDemo03">
    <ul class="navbar-nav mr-auto mt-2 mt-lg-0">
      <li class="nav-item active">
        <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Link</a>
      </li>
      <li class="nav-item">
        <a class="nav-link disabled" href="#">Disabled</a>
      </li>
    </ul>
    <form class="form-inline my-2 my-lg-0">
      <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
      <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
    </form>
  </div>
</nav>

公式サイト大切です

VS Code HTML自動インテンド

HTMLはインテンドはデフォルトで入っているようだ。

f:id:happy_teeth_ago:20190429190837p:plain


検索窓に formationを入れて、検索

format on save にチェックを入れる

これで保存したら自動整形してくれる。 めでたし、めでたし f:id:happy_teeth_ago:20190429190908p:plain

Rails link_to image を貼り付ける

アフェリエイトリンク貼ったときの忘備録

<a href="https://www.agoda.com/partners/partnersearch.aspx?pcs=1&cid=11114&hl=ja&hid=111003" target="_blank">
hogehoge
</a>
<%= link_to image_tag("https://agoda.net/hotelImages/336/5325.jpg?s=240x180"),
    "https://www.agoda.com/partners/partnersearch.pcs=",
    {target: "_blank"} %>

サルだとわからん-やさしいSwift単体テスト 編集途中!

やさしいSwift単体テスト~テスト可能なクラス設計・後編~ - Qiita

そもそもテストとは

ざっくりいうと

入力値、引数を渡して、期待する結果も入力する。 そのとおり出力されるかをチェックする。

ポイント!

UIつまり、ビューと接続しているところは単体テストできない。必ずビューに依存しているので。

例えると結婚と筋肉トレーニングである。

あと1年以内に結婚すると決めたとしても、相手がいることなので、必ずしも結婚できるとは限らない。
そのようなものはテストできない。 しかし、筋肉トレーニングは、毎日時間を決めてやれば、必ず筋肉はつく。程度の差はあるが、、 同じように、画面と接続していると、StoryBoardが裏で(プログラムの影響範囲外)で動くので、基本単体テストはできない。 自動化して、できるようにすることもある。ここでは触れません。

だからMVVCの理論がある。

f:id:happy_teeth_ago:20190427124011p:plain
MVVMモデル
上記で赤のviewとつながっているところは、はテストできない しかし、緑と青のModel,Viewmodelはテスト可能。

ポイント

まずコードをViewとロジックで明確に切り分ける必要がある。

例 この関数をテストするとします。

まずこの関数はViewControllerに記載されているので、ViewControllerに依存しない、別クラスを作成します。

   func HogeHoge(_ y : Int) {
        do{
            let goals = try self.viewContext.fetch(goalQuery)
            if y == 0 {
                for goal in goals {
                    goalList.insert(goal, at: 0)
                    if goalList[0].image != nil {
                        let buttonImage = UIImage(data: goalList[0].image as! Data)
                        goButton.setImage(buttonImage, for: .normal)
                    }
//ここが良くない。Viewと接続している。ここを分離する。
                    self.mokuhyoLabel.text = goalList[0].name
                    self.dateLabel.text = goalList[0].date! + "までに"
//これはメンバに返却しているだけなので、OK
                    self.x = 1
                }
            }
            
        }catch{
            print("フェッチできない")
        }
    }

修正後 詳細はコメントをみてください

class HogeHoge_test {

//Viewに返す値を作成するためにstructを作成
//返却値を宣言
    struct ReturnValue{
        var x:Int
        var goButton:UIImage
        var mokuhyouLabel: String
        var dateLabel: String
        
    }
    
    let goalQuery: NSFetchRequest<Goal> = Goal.fetchRequest()
    var viewContext = (UIApplication.shared.delegate as!
        AppDelegate).persistentContainer.viewContext
    //他で追加していないので
    var goalList: [Goal] = []
    
    func getCoreData2(_ y : Int)-> ReturnValue? {
        do{
            let goals = try self.viewContext.fetch(goalQuery)
            if y == 0 {
                for goal in goals {
                    goalList.insert(goal, at: 0)
                }
                if goalList[0].image != nil {
                    let buttonImage = UIImage(data: goalList[0].image as! Data)
                  let returnValue =  ReturnValue.init(x: 1, goButton: buttonImage!, mokuhyouLabel: goalList[0].name!, dateLabel: goalList[0].date!)
                    //                        goButton.setImage(buttonImage, for: .normal)
                    //                    self.mokuhyoLabel.text = goalList[0].name
                    //                    self.dateLabel.text = goalList[0].date! + "までに"
                    //self.x = 1
                    return returnValue
                }
                return nil
            }

Swift テストコード書き方

参考にさせていただきました。

qiita.com

テストには大きく分けて2つある。

明示的出入力テスト

引数と戻り値があるもの 単体テストが書ける。

暗黙的出入力テスト

引数と戻り値はあるが、途中で他のクラスの変数を利用して処理する場合など こっちのほうが難しい

デフォルトテストコード

class HogeHogeTests: XCTestCase {

    override func setUp() {

        //setUp()クラス・メソッドは、最初のテスト・メソッドが呼び出される前に、テストケースに対して一度だけ呼び出されます。テストケース内のすべてのテストの初期状態をカスタマイズするには、このメソッドをオーバーライドします。
    }

    override func tearDown() {

//tearDown()クラス・メソッドは、その最後のテスト・メソッドが完了した後、テスト・ケースに対して一度だけ呼び出されます。このメソッドをオーバーライドして、すべてのテストメソッドが終了した後にクリーンアップを実行します。

    }

    func testExample() {
//XCTAssertクラスを利用する。関数定義は以下
func XCTAssert(_ expression: @autoclosure () throws -> Bool, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line)

:expression はboolean型
: message 失敗時の詳細
:file 失敗したときのファイル。この関数が呼び出されたテストケースのファイル名がデフォルトになります。 
:line 障害が発生した行番号

}

    func testPerformanceExample() {
        // This is an example of a performance test case.
        self.measure {
            // Put the code you want to measure the time of here.
        }
    }

}