Swift xlibファイルを使ってViewを組み立ててみる。

いままでレイアウトは全てコードで書いてきたが、 複雑にレイアウトになった場合に、コード内のみとうしがかなり悪くなる。xlibでのレイアウトを試してみた。

その時の作業ログ

f:id:loosefingers:20160815205149p:plain

viewを新規作成

f:id:loosefingers:20160815210522p:plain

viewのOwnerを変更

f:id:loosefingers:20160815205444p:plain

UseXibVieクラスは先に作成しておく。

f:id:loosefingers:20160815205453p:plain

UINibでxibファイルを指定する

これでコードとxibが関連づけされる。

class UseXibView: UIViewController {
    override func loadView() {
        if let view = UINib(nibName: "SampleView", bundle: nil).instantiateWithOwner(self, options: nil).first as? UIView {
            self.view = view
        }
    }
}

Buttonを配置した場合

class UseXibView: UIViewController {
    @IBOutlet weak var Button: UILabel!
    override func loadView() {
        if let view = UINib(nibName: "SampleView", bundle: nil).instantiateWithOwner(self, options: nil).first as? UIView {
            self.view = view
            Button.text="chnageName";
        }
    }
}

weakに関しては、以下の記事が参考になった。 qiita.com

ちなみに、xibファイルの中身はこちら、

userLabel="File's Owner" customClass="UseXibView

上記の記述があるけれどこのファイルを移植すればそのまますんなりと流用できるのだろうか、それとも何か依存ファイルがあるのか、

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10117" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
    </dependencies>
    <objects>
        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="UseXibView" customModule="app" customModuleProvider="target">
            <connections>
                <outlet property="Button" destination="EOh-jw-9AA" id="fHZ-33-s40"/>
            </connections>
        </placeholder>
        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
        <view contentMode="scaleToFill" id="iN0-l3-epB">
            <rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
            <subviews>
                <label opaque="NO" userInteractionEnabled="NO" alpha="0.80000000000000004" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Buttom" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EOh-jw-9AA">
                    <rect key="frame" x="130" y="357" width="144" height="22"/>
                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
                    <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
                    <nil key="highlightedColor"/>
                    <color key="shadowColor" red="0.49803921579999999" green="0.49803921579999999" blue="0.49803921579999999" alpha="1" colorSpace="calibratedRGB"/>
                </label>
            </subviews>
            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
            <simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina55"/>
        </view>
    </objects>
</document>

json.Marshalとjson.Unmarshal

Go言語でJsonの扱いがわからなかったのでしらべてみた。

ざっくりと言えば、

json.Marshal

構造体からJSON文字列へ変換

json.Unmarshal

JSON文字列から構造体へ変換

package main

import (
    "encoding/json"
    "fmt"
)

type MessageMarshal struct {
        Name string
    Body string `json:"body_json"`
        Time int64
}

type MessageUnmarshal struct {
    Name string
    Body string
    Time int64
}

func main() {
    
    //Marshal
    mm := MessageMarshal{"Alice", "Hello", 1294706395881547000}
    b, _ := json.Marshal(mm)
    fmt.Println(string(b))
    
    //Unmarshal 
    c := []byte(`{"Name":"Alice","Body":"Hello","Time":1294706395881547000}`)
    var mu MessageUnmarshal
    json.Unmarshal(c, &mu)
    fmt.Println(mu.Name)
    fmt.Println(mu.Body)
    fmt.Println(mu.Time)
    
    //Interface
    var f interface{}
    json.Unmarshal(c, &f)
    fmt.Println(f)
    
}
{"Name":"Alice","body_json":"Hello","Time":1294706395881547000}
Alice
Hello
1294706395881547000
map[Name:Alice Body:Hello Time:1.294706395881547e+18]

JSON and Go - The Go Blog

Go言語でMySQLのtimestamp型の日付変換をしてみる

Go言語でMySQLのtimestamp型の日付変換をしてみた。

package main

import (
    "fmt"
    "time"
)

func main() {
    t, _ := time.Parse("2006-01-02 15:04:05.999999999 -0700 MST", "2016-08-15 01:15:57.065962927 +0900 JST")
    fmt.Println(t)
    fmt.Println(t.Format("2006-01-02T15:04:05Z07:00"))
    fmt.Println(t.Format("2006/01/02 15:04"))
    fmt.Println(t.Format("2006年01月02日 15時04分"))
    fmt.Println(t.Format("2006_01_02"))
}

結果は以下、

2016-08-15 01:15:57.065962927 +0900 JST
2016-08-15T01:15:57+09:00
2016/08/15 01:15
2016年08月15日 01時15分
2016_08_15

The Go Playground

time.Parseの第一引数には定数が用意されている。定数にない場合は、自分で定義をする必要がある。

たとえばこんな感じに使える。

fmt.Println(time.Now().Format(time.ANSIC))

//2016-08-15T01:35:48+09:00

定数の一覧

const (
        ANSIC       = "Mon Jan _2 15:04:05 2006"
        UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
        RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
        RFC822      = "02 Jan 06 15:04 MST"
        RFC822Z     = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
        RFC850      = "Monday, 02-Jan-06 15:04:05 MST"
        RFC1123     = "Mon, 02 Jan 2006 15:04:05 MST"
        RFC1123Z    = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
        RFC3339     = "2006-01-02T15:04:05Z07:00"
        RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
        Kitchen     = "3:04PM"
        // Handy time stamps.
        Stamp      = "Jan _2 15:04:05"
        StampMilli = "Jan _2 15:04:05.000"
        StampMicro = "Jan _2 15:04:05.000000"
        StampNano  = "Jan _2 15:04:05.000000000"
)

time - The Go Programming Language

SwiftからAlamofireを使う

Alamofireの作業ログ、何点かハマるポイントがあったのでその記録。

httpファイルにアクセスできない

https://以外のhttpのアクセスは制限されています。

App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be >configured via your app's Info.plist file.

NSAppTransportSecurityのkeyを追加する必要がありました。追加して無事OK。

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>

localホストにアクセスできない。

Alamofireからlocalhostに接続できずにハマる。

stackoverflowにありました。 stackoverflow.com

要点としては、この記述ではアクセスできませんでした。

let url = "http://localhost:8080/"

以下のように変更してOK.

let url = "http://0.0.0.0:8080/post/1"

Test時には、expectationWithDescriptionを使う必要がある。

let expectation = expectationWithDescription("scync")

gist.github.com

Go製サーバーをGoogleApp Engineに設置してみる&Google Cloud SQLの設定

GoのEchoで作ったサーバーをGoogleApp Engineに設置してみる。その時の作業ログ。

まずDBの作成

webサーバーをと思ったがまずはDBを作成する。

Google Cloud SQLとは?

Google Cloud SQL は、使いやすいフルマネージドの MySQL データベースです。Google Cloud SQL を使うと、パッチやアップデート、バックアップや複製の設定など、単調であるけれども必要で、時に時間のかかるタスクを Google に任せることができるようになります。MySQL のほぼすべての機能を持ち、あとで示すように追加機能や非サポート機能がいくつかあります。Google Cloud SQL は使いやすく、ほとんど全てのアプリケーションからアクセスできます。ソフトウェアのインストールやメンテナンスも不要です。

との事、AWSのRDSよりも安価に使えそうという事で今回選んだ、

比較記事はここを参考にさせていただいた。 qiita.com

Cloud SQL 第 2 世代(ベータ)は、分単位の従量課金制、自動の継続利用割引、予算にあったインスタンスを用意しています。利用していない>間は料金は発生せず、事前の申し込みなしで継続利用には割引が自動で適用されます。

料金は分単位の課金制となる、ここは実際に使ってみないと細かい部分までわかっていない。

Google Cloud SQLを設定する。

f:id:loosefingers:20160812232901p:plain

インスタンスを作成

f:id:loosefingers:20160812234518p:plain

第1世代を選択する

f:id:loosefingers:20160812233019p:plain

場所の設定

f:id:loosefingers:20160812233233p:plain

インスタンスが作成される、しばらく時間がかかる。

f:id:loosefingers:20160812234951p:plain

rootパスワードの変更は

アクセス制限  >  ユーザー から実行できる。

f:id:loosefingers:20160813001706p:plain

timezoneの設定も管理画面からできる。MySQLフラグを追加 f:id:loosefingers:20160816125129p:plain

DB設定初期はパスワードが設定されていないので以下で接続できる。

mysql --host=<ip> --user=root 

ユーザーのパスワードを設定した場合

mysql --host=<ip> --user=root --password

databaseを作成する。

CREATE DATABASE db_name;

ひとまず、DBの設定がここまでで完了する。

アプリの作成

Goを選択します。

f:id:loosefingers:20160813013624p:plain

サンプルコードが表示されます。

f:id:loosefingers:20160813013902p:plain

Google App Engine SDK for Go

まず、Google App Engine SDK for Goをダウンロードする。

Download the Google App Engine SDK  |  App Engine Documentation  |  Google Cloud Platform

pathを通す

$ cp -R go_appengine ~/go_appengine/
$ export PATH=~/go_appengine:$PATH

Python 2.7がインストールされている事が必要らしい。

以下のコマンドで確認してみる。なければインストールが必要。

$ /usr/bin/env python -V

$ Python 2.7.10

バージョン確認

$ goapp version
$ go version go1.6.2 (appengine-1.9.40) darwin/amd64

ファイル構成

application: ********

の部分にプロジェクトIDを設定する。

gist.github.com

Serveコマンド

ローカル環境でサービスを立ち上げる

goapp serve ./hello

Deployコマンド

本番環境にDeploy

goapp deploy  ./hello/

Deployに失敗する場合

deploy最中に処理が落ちたりする場合に、以下のエラーが発生する事があります。

 That user can undo the transaction with "appcfg rollback".

その時は、rollbackで解決

appcfg.py rollback ./app/

Error

突然、CloudSqlに接続できない現象が発生した。 原因としてはよくわかっていないのだが、Deployし直す事で解消した。

Cloud SQL connection error 2 

stackoverflowにあった、どうも大量のコネクションが発生している事が原因らしい、ソースからdbへの接続方法が変更して対応。

I ran into similar issues using Go on App Engine with Cloud SQL that seemed to ?be related to the creating too many connections to the cloudsql instance. I changed my code to create a single connection to the db during init which I reused throughout the program and seems to work, similar to what is recommended here.

stackoverflow.com

課題、

マイグレーションはどう行うのがいいのだろろうか?

The cloudsql package

The cloudsql package  |  Go  |  Google Cloud Platform

Go言語からGORMとECHOでJSONを返すAPIサーバー作ってみる。

GORMとECHOでMYSQLのデータからJSONを返すシンプルなAPIサーバー作ってみる。 ECHOはシンプルな構成でサーバーを構築できる印象、使いやすい。ひとまずDBから取得したデータをJSON化して返す事ができました。

echo.labstack.com

github.com

GORMの部分は前回作成したサンプルをAPIサーバー用にアレンジ。 onga-tec.hatenadiary.jp

ルーティングは以下のように指定できる。

func main() {
        fmt.Println("sever start")
        e := echo.New()
        u := userModel.User{}
        h := handler.CreateHandler(u)
        e.GET("/", status)
        e.GET("/user/:id", h.GetUser)
        e.POST("/user", h.CreateUser)
        e.DELETE("/user", h.DeleteUser)
        e.Run(standard.New(":3001"))
}

今回作成したサンプル、ところどころ修正が必要を感じる、、ここはおってベストプラクティスを探していこう。 gist.github.com

TEST

handler部分のtest

go test ./handler/ -v

model部分のtest

go test ./models/user/ -v

WEB

サーバー起動

go run app.go

以下のアドレスで確認できるはず。

http://127.0.0.1:3001/user/1

Goはtestが前提の設計がされているので、自然に無理なくtestを書く事ができるのは本当にいいところ、積極的にtestを書いていこう。

ちなみに、gopherって何の動物をモチーフにしているのだろうか、?きになる、、 f:id:loosefingers:20140321181137j:plain