Swiftで半角空白文字削除(trim)

半角空白削除の場合には、whitespaces、改行などの制御記号も取り除く場合にはNewlinesも追加する。

let myString = "  \t\t  Let's trim all the whitespace  \n \t  \n  "
let trimmedString = myString.trimmingCharacters(in: .whitespacesAndNewlines)
print(myString)

コンソールには以下の文字列が出力されます。

Let's trim all the whitespace

Does swift have a trim method on String? - Stack Overflow

@objcのwarning@Swift 4の対処

UIRefleshControlを使っているSwift3プロジェクトをSwift4にマイグレーションさせた場合、呼び出しメソッドに@objcが追加されますが、Swift3プロジェクトの設定のま まだとワーニングが表示されます。

ビルドセッティングでSwift3 @objc interfaceをOnからDefaultに変更するとワーニング消えます。

Swift 4で@objcに関するwarningが出たときの対処 - Qiita

なにやらよく分かりませんが、ここを読むとなんとなく雰囲気がわかります。 @objcキーワードはいつまで残るんでしょうか…?

​ #selector がswift4では使えない? → 使えます - MILLEN BOX

ワーニング

The use of Swift 3 @objc inference in Swift 4 mode is deprecated. Please address deprecated @objc inference warnings, test your code with “Use of deprecated Swift 3 @objc inference” logging enabled, and then disable inference by changing the "Swift 3 @objc Inference" build setting to "Default" for the "NewsReader" target.

マイグレーションされたコード

Xcode3
    override func viewDidLoad() {
        // (中略)
        self.refreshControl = UIRefreshControl()
        self.refreshControl?.addTarget(self, action: #selector(refresh(sender: )), for: .valueChanged)
        // (中略)
    }
    func refresh(sender: UIRefreshControl) {
        print("refresh")
        startDownload()
        self.refreshControl?.endRefreshing()
    }
Xcode4
    @objc func refresh(sender: UIRefreshControl) {
        print("refresh")
        startDownload()
        self.refreshControl?.endRefreshing()
    }

GolangとVue.js...

GolangとVue.js」というタイトルに惹かれて調べてみました。

Big Sky :: Golang と Vue.js で簡単なアプリケーションを作ってみた。

まずは、動かしてみます。

MacOS High Sierra 10.13.4

MongoDBインストール&起動

インストール済みであれば不要です。

$ brew install mongodb
$ sudo mkdir /var/lib/mongodb
$ sudo touch /var/log/mongodb.log
$ sudo mongod --dbpath /var/lib/mongodb --logpath /var/log/mongodb.log
$ export MONGODB_URI=mongodb://localhost

HomebrewでMacにMongoDBをインストールした時のメモ - Qiita

go-vue-example実行

githubからソースをダウンロードして実行しました。 depについてはこの記事を参照してください。

build & run

$ git clone https://github.com/mattn/go-vue-example
$ dep unsure
$ go build
$ ./go-vue-example

Webアプリをブラウザで開く

http://localhost:4000/

DBの状態を調べる

$ mongo
> show dbs;
admin                       0.000GB
config                      0.000GB
go-vue-example-development  0.000GB
local                       0.000GB
> use go-vue-example-development;
switched to db go-vue-example-development
> show collections;
tasks
> db.tasks.find();
{ "_id" : ObjectId("5abef638056d1b319501bdc6"), "body" : "Have a breaskfast", "done" : true, "created_at" : NumberLong(1522464312), "updated_at" : NumberLong(1522547660) }
{ "_id" : ObjectId("5ac03e6e056d1b319501bdc7"), "body" : "do second task", "done" : false, "created_at" : NumberLong(1522548334), "updated_at" : NumberLong(0) }
>

所感

CRUD的な操作を持つWebアプリをさっと作って動かすという観点だと、echo-scaffold(golang)とvueの組み合わせは便利そう。

必要な処理は、UIイベント処理(タスク入力および)、ajax呼び出し、取得したデータのDOMマッピングです。それぞれ、どのように記述するかは、以下のマニュアルを見てください。

はじめに — Vue.js

サーバーサイド(golang)

githubのコードと以下のコマンドで生成したコードには差分はありませんでした。

$ echo-scaffold init go-vue-example
$ cd go-vue-example
$ echo-scaffold scaffold task body:string done:bool

フロントエンド

element UIとaxiosのvuejsライブラリを使っており、実際に作成しているWebアプリ(vuejsのファイル)は以下の2ファイルです。

  • index.html
  • app.js

依存関係管理ツールdep(golang)

久しぶりにgo言語関連アプリ、Big Sky :: Golang と Vue.js で簡単なアプリケーションを作ってみた。を使ってみようと思ったらパッケージがないって怒られました。

個別にインストールするのは面倒です…

$ go get -u xxx

nodeやrubyのパッケージ管理ツールがないのかと思っていたら、depというパッケージ管理ツールがありました。

これで簡単に試してみることができます。

$ get clone https://github.com/mattn/go-vue-example
$ cd go-vue-example
$ dep init
  Using ^3.3.4 as constraint for direct dep github.com/labstack/echo
  Locking in 3.3.4 (a5d81b8) for direct dep github.com/labstack/echo
  Locking in master (e746df9) for transitive dep github.com/valyala/bytebufferpool
  Locking in v3.2.0 (06ea103) for transitive dep github.com/dgrijalva/jwt-go
  Locking in 0.2.4 (6fe1405) for transitive dep github.com/labstack/gommon
  Locking in v0.0.9 (167de6b) for transitive dep github.com/mattn/go-colorable
  Using v1 as constraint for direct dep gopkg.in/check.v1
  Locking in v1 (20d25e2) for direct dep gopkg.in/check.v1
  Locking in master (12892e8) for transitive dep golang.org/x/crypto
  Using master as constraint for direct dep github.com/globalsign/mgo
  Locking in master (baa28fc) for direct dep github.com/globalsign/mgo
  Locking in v0.0.3 (0360b2a) for transitive dep github.com/mattn/go-isatty
  Using ^1.0.5 as constraint for direct dep github.com/sirupsen/logrus
  Locking in v1.0.5 (c155da1) for direct dep github.com/sirupsen/logrus
  Locking in master (378d26f) for transitive dep golang.org/x/sys
  Locking in master (dcecefd) for transitive dep github.com/valyala/fasttemplate

$ cat Gopkg.toml
#   name = "github.com/x/y"
#   version = "2.4.0"
#
# [prune]
#   non-go = false
#   go-tests = true
#   unused-packages = true


[[constraint]]
  branch = "master"
  name = "github.com/globalsign/mgo"

[[constraint]]
  name = "github.com/labstack/echo"
  version = "3.3.4"

$ cat Gopkg.lock
  # This file is autogenerated, do not edit; changes may be undone by the next     'dep ensure'.

   [[projects]]
    name = "github.com/dgrijalva/jwt-go"
    packages = ["."]
    revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
    version = "v3.2.0"

$ dep ensure
$ go build

話題のflutterを使って見ました

Flutter - Beautiful native apps in record timeは、Googleが開発しているスマホアプリ開発環境(UIフレームワーク)です。同じコードでiOSアプリ、Androidアプリを開発することができます。開発言語はGoogleが開発しているDart programming language | Dartです。

React Native, Xamarinなど同じ環境でiPhone/Androidアプリを開発できるものはすでにありますが、選択肢が増えるのは良いことだと思います。 また、Android StudioVisual Studio Codeがサポートされているのも取っつきやすいかもしれません。

今回は、iPhoneアプリをシミュレータで動かすところまで実行しましたが、iPhoneアプリ開発環境(Xcode、cocoapod)のインストールは別サイトを参考にする必要があります。

以下、macOS XGet Started: Install on macOS - Flutterを試してみました。

Flutter SDKを取得

Clone the repo

git clone -b beta https://github.com/flutter/flutter.git
export PATH=`pwd`/flutter/bin:$PATH

環境チェック

flutter doctorを実行します。

$ flutter doctor
Downloading Dart SDK from Flutter engine ead227f118077d1f2b57842a32abaf105b573b8a...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 43.3M  100 43.3M    0     0  4290k      0  0:00:10  0:00:10 --:--:-- 5273k
Building flutter tool...

  ╔════════════════════════════════════════════════════════════════════════════╗
  ║                 Welcome to Flutter! - https://flutter.io                   ║
  ║                                                                            ║
  ║ The Flutter tool anonymously reports feature usage statistics and crash    ║
  ║ reports to Google in order to help Google contribute improvements to       ║
  ║ Flutter over time.                                                         ║
  ║                                                                            ║
  ║ Read about data we send with crash reports:                                ║
  ║ https://github.com/flutter/flutter/wiki/Flutter-CLI-crash-reporting        ║
  ║                                                                            ║
  ║ See Google's privacy policy:                                               ║
  ║ https://www.google.com/intl/en/policies/privacy/                           ║
  ║                                                                            ║
  ║ Use "flutter config --no-analytics" to disable analytics and crash         ║
  ║ reporting.                                                                 ║
  ╚════════════════════════════════════════════════════════════════════════════╝

Downloading Material fonts...                         0.6s
Downloading package sky_engine...                     0.6s
Downloading common tools...                           0.8s
Downloading darwin-x64 tools...                       3.8s
Downloading android-arm-profile/darwin-x64 tools...   0.7s
Downloading android-arm-release/darwin-x64 tools...   0.7s
Downloading android-arm64-profile/darwin-x64 tools...  0.7s
Downloading android-arm64-release/darwin-x64 tools...  0.5s
Downloading android-x86 tools...                      1.9s
Downloading android-x64 tools...                      2.2s
Downloading android-arm tools...                      1.0s
Downloading android-arm-profile tools...              0.7s
Downloading android-arm-release tools...              0.7s
Downloading android-arm64 tools...                    0.9s
Downloading android-arm64-profile tools...            1.2s
Downloading android-arm64-release tools...            0.9s
Downloading ios tools...                              4.9s
Downloading ios-profile tools...                      4.1s
Downloading ios-release tools...                      2.5s
Downloading Gradle Wrapper...                         0.3s
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel beta, v0.1.5, on Mac OS X 10.13.3 17D102, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK 25.0.2)
[!] iOS toolchain - develop for iOS devices (Xcode 9.2)
    ✗ libimobiledevice and ideviceinstaller are not installed. To install, run:
        brew install --HEAD libimobiledevice
        brew install ideviceinstaller
    ✗ ios-deploy not installed. To install:
        brew install ios-deploy
[✓] Android Studio (version 3.0)
[!] IntelliJ IDEA Community Edition (version 2017.3.4)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
[!] VS Code (version 1.20.1)
[!] Connected devices
    ! No devices available

! Doctor found issues in 4 categories.

×が問題点ですね。Editor plugin(IntelliJ IDEA)は後回しにします。

$ brew install --HEAD libimobiledevice
以下の依存モジュールをインストールします。
==> Installing dependencies for libimobiledevice: automake, libxml2, libtasn1, libplist, libusb, usbmuxd, openssl

$ brew install ideviceinstaller
以下の依存モジュールをインストールします。
==> Installing dependencies for ideviceinstaller: libzip

$ brew install ios-deploy
$ brew install

Update your path

以下の内容を.bash_profileに追加。使っているshに依存します。

export PATH=[PATH_TO_FLUTTER_GIT_DIRECTORY]/flutter/bin:$PATH”

確認。

$ echo $PATH

iOS Setup

Install Xcode

$ sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
$ sudo xcodebuild -license

Set up the iOS simulator

$ open -a Simulator

Deploy to iOS devices

iOS開発環境をセットアップしていない人は、以下の処理が必要ですが、知らないと少し難しいかもしれません。

外部ライブラリ追加

$ install cocoapods

$ cd flutter/examples/hello_world/ios
$ pod setup

example実行

$ cd flutter/examples/hello_world
$ flutter run

f:id:unokun3:20180311104921p:plain

TypeScriptで始めるJavascript再入門(1)

Javaなどのクラスベースオブジェクト指向言語を知っている人が最新のJavascriptを知る場合、Typescriptを使うのが良い方法です。

TypeScript - JavaScript that scales.は、マイクロソフトが開発しているaltJSの一つです。 TypeScriptはJavaScriptに対して、省略も可能な静的型付けとクラスベースオブジェクト指向を加えた厳密なスーパーセットとなっています。

使い方

Typescriptは、.tsという拡張子を持つファイルに記述し、tscというコマンドでjavascriptコンパイルします。コンパイルオプションは、tsconfig.jsonファイルに記述します。

$ cat age.ts
let age: number = 10;
console.log(age + ‘歳です。’);

$ cat ./tsconfig,json
{
    "buildOnSave": true,
    "compileOnSave": false,
    "compilerOptions": {
        "target": "es5",
        "sourceMap": true,
        "module": "commonjs",
        "charset": "utf8"
    }
}

$ tsc -p ./tsconfig,json

$ cat age.js
let age = 10;
console.log(age + '歳です。');

静的型付け

Typescriptは、静的型付け可能な言語のため、次のコードはコンパイルエラーになります。javascriptの暗黙型変換によるバグを未然に防ぐことができます。

let age: number = 10;
age += '1';
$ tsc -p ./tsconfig,json
error TS2322: Type 'string' is not assignable to type 'number'.

クラス

クラスは、javascriptのバージョンに応じてコンパイルしてくれます。javascriptのバージョンごとの記述方法を調べる方法としてTypescriptを使うのも良さそうです。

class car {
    speed:number;
    private _ownerName:string;

    accelarator(accelarateSpeed:number)
    {
        this.speed += accelarateSpeed;
    }

    public get ownerName():string {
        return this._ownerName;
    }
    public set ownerName(name:string) {
        this._ownerName = name;
    }
}

このクラスをes5準拠でコンパイルすると以下のjavascriptファイル(car.js)が生成されます。

var car = /** @class */ (function () {
    function car() {
    }
    car.prototype.accelarator = function (accelarateSpeed) {
        this.speed += accelarateSpeed;
    };
    Object.defineProperty(car.prototype, "ownerName", {
        get: function () {
            return this._ownerName;
        },
        set: function (name) {
            this._ownerName = name;
        },
        enumerable: true,
        configurable: true
    });
    return car;
}());

es2015(es6)準拠でコンパイルすると以下のjavascriptファイル(car.js)が生成されます。

class car {
    accelarator(accelarateSpeed) {
        this.speed += accelarateSpeed;
    }
    get ownerName() {
        return this._ownerName;
    }
    set ownerName(name) {
        this._ownerName = name;
    }
}

インタフェース

microsoft独自仕様としてTypescriptはinterfaceを使うことができる。コンパイル時に必須メソッドチェックなどを行ってくれます。

interface vehicle
{
    speed:number;
    accelarator(accelarateSpeed:number);
}
class car implements vehicle {
    speed:number;
    private _ownerName:string;

    accelarator(accelarateSpeed:number)
    {
        this.speed += accelarateSpeed;
    }

    public get ownerName():string {
        return this._ownerName;
    }
    public set ownerName(name:string) {
        this._ownerName = name;
    }
}
class motorcycle implements vehicle {
    speed:number;

    accelarator(accelarateSpeed:number)
    {
        this.speed += accelarateSpeed;
    }
}

リンク

Webアプリのコンポーネント化

vue, reactなどを使ってWebアプリを作成する時、どのようにコンポーネント化していくのが良いのでしょうか? 今、その設計方法(ベストプラクティス)に関心を持っています。

以下の記事は参考になりそうです。

iOSのStoryboard的なツールは便利かもしれない。