Swift2とSwift3の違いメモ
ほんきで学ぶSwift+iOSアプリ開発入門 写経中メモ
この本はSwift2で書かれているのでSwift3の環境だとそのまま動かない。
URLを使って画像を表示する
Swift2
let url = NSURL(string: "http://hogehoge.png")!
let imageData:NSData = NSData(contentsOfURL: url!)!
let image2 = UIImage(data:imageData);
Swift3
let url = URL(string: "http://hogehoge.png")!
let imageData = try? Data(contentsOf: url)
let image2 = UIImage(data:imageData!)
NSURLがURL、NSDataがDataに変わった模様。そしてtry-catch使わないと怒られるようになった模様
CGRectMakeが無くなっている
// CGRectMake関数を用意してSwift2と同じように呼べるようにする
func CGRectMake(_ x: CGFloat, _ y: CGFloat, _ width: CGFloat, _ height: CGFloat) -> CGRect {
return CGRect(x: x, y: y, width: width, height: height)
}
var button = UIButton(frame: CGRectMake(0,0,100,50))
// CGRectを使う。
var button2 = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
XCPlaygroundが無くなっている
Swift3
import UIKit
import PlaygroundSupport
let datePicker = UIDatePicker()
datePicker.datePickerMode = UIDatePickerMode.date
datePicker.backgroundColor = UIColor.white
PlaygroundPage.current.liveView = datePicker
Vue2 + TypeScript2 を使ったサンプル
やりたいこと
vue.js2ではTypeScriptに対応したらしいのでどんなもんなのかを試したい。
試すものたち
- vue.js 2.0.3
- vuex
- typescript 2.0.3
- vue-ts-loader
- av-ts
- kilimanjaro
参考サイト
http://herringtondarkholme.github.io/2016/10/03/vue2-ts2/
作ってく
プロジェクトの作成
mkdir vue-ts-test
cd vue-ts-test
npm init -y
npm i -S vue typescript
ここまででpackage.jsonとnode_modulesが出来ている
STEP1:テンプレートのindex.htmlとちっちゃいVue
index.html
<div id="app"></div>
<script src="node_modules/vue/dist/vue.js"></script>
<script src="app.js"></script>
app.ts
declare var Vue: any
new Vue({
el: '#app',
render(h) {
return h('h1', 'hello world')
}
})
app.tsをコンパイルする
./node_modules/.bin/tsc app.ts
ブラウザでindex.htmlを開き"hello world"が表示されることを確認する
STEP2: webpack使って.vueファイルでコンポーネントを作る
npm i -D webpack vue-loader css-loader
npm i -D vue-ts-loader
webpack.config.js
module.exports = {
entry: { app: './app.ts', },
output: { filename: 'app.js' },
// resolve TypeScript and Vue file
resolve: {
extensions: ['', '.ts', '.vue', '.js']
},
module: {
loaders: [
{ test: /\.vue$/, loader: 'vue' },
{ test: /\.ts$/, loader: 'vue-ts' }
],
},
vue: {
// instruct vue-loader to load TypeScript
loaders: { js: 'vue-ts-loader', },
// make TS' generated code cooperate with vue-loader
esModule: true
},
}
app.vue
<template>
<h1 @click="hello">hello world</h1>
</template>
<script>
export default {
methods: {
// type annotation!
hello(): void {
alert('hello world')
}
}
}
</script>
app.ts
declare var require: any
import Vue = require('vue')
var App = require('./app.vue').default
new Vue({
el: '#app',
components: { App },
render: h => h('app')
})
ここでwebpack
コマンドでコンパイルしてindex.htmlを表示したときにhello worldをクリックしてアラートが出ればOK
STEP3:もっと型を
npm i -S av-ts
app.vueを改造
<template>
<h1 @click="hello">hello {{name}}</h1>
</template>
<script>
// av-tsからVue関連のインポート
import {Vue, Component} from 'av-ts'
@Component
export default class App extends Vue {
name = 'kuroko'
// type annotation!
hello(): void {
alert('hello ' + this.name)
}
}
</script>
ここでwebpackコマンドを叩いて動作確認
STEP4:Vuex導入
npm i -S kilimanjaro
store.tsの追加
import { create } from 'kilimanjaro'
var store =
create({count: 0})
.getter('count', s => s.count)
.mutation('increment', s => () => s.count++)
.mutation('decrement', s => () => s.count--)
.done()
export default store
app.vue修正
<template>
<h1 @click="hello">hello {{name}} now count is {{count}}
<button @click.stop="add">+</button>
<button @click.stop="sub">-</button>
</h1>
</template>
<script>
// av-tsからVue関連のインポート
import {Vue, Component} from 'av-ts'
import {Vuex, getHelper} from 'kilimanjaro'
import store from './store'
const { getters, commit } = getHelper(store)
@Component
export default class App extends Vue {
@Vuex count: number = getters('count')
@Vuex add:Function = commit('increment')
@Vuex sub:Function = commit('decrement')
name = 'kuroko'
// type annotation!
hello(): void {
alert('hello ' + this.name)
}
}
</script>
webpackコマンドを叩いて動作を確認する。
webpackコマンドを叩くとerror TS2304: Cannot find name 'Promise'.
というエラーがいくつがでる。
単純にこのエラーを消したい場合はtsconfig.jsonのcompilerOptions.targetをes6に変えればエラーは出なくなる。
しかし、それが根本的な解決なのかはわからない。
次に確認したいこと
vue-cliのwebpack相当の構成でnpm run dev
でデバッグしながらリアルタイムにプレビューできるようにするにはどうすればよいのかを調べたい。
が・・・ちょっとvue-cliで生成したプロジェクトを使って改造していくのは僕には歩幅が大きすぎて挫折したので小さくすすめる。
- フォルダ構成を./srcとか./src/componentsとか./src/storeとかにわけれるようにしたい
- sass使えるようにしたい
- TypeScript -> ES5じゃなくてTypeScript -> ES6 (babelで) -> ES5にしたい。TypeScriptでES6チックにかければ不要か?
- propなど今回使用していないvueの機能はどうやって書くのかを調べたい
今回のサンプルを作ってみてまだわからないこと
- webpack.config.jsにある
vue:
の指定は一体なんなのか? - vuexのgitterとかあんまり馴染みがない(ただの勉強不足)
- tsconfig.jsonの中身全般。そもそもTypeScriptに関する知識が殆ど無い。
最近やったことやら色々メモ
- haskell挫折中。タイミングを見てまた集中して学習したい。
- やりたいこととに対してSpring batchはtoo much だったので素のSpringを使うことにした。
- Springのトランザクション周り(requires_newしたときのテストの書き方とか)いろいろ面倒だった。
- ラムダ乱用は良くないと思うけど、まず乱用できるほどラムダの使い方わかってない
- Doma2良かった。
- Gradleでマルチプロジェクトできたけどプロダクトのバージョン管理とかよくわからん。
- githubとgitに関して簡単な操作はできるようになったけどまだあまり理解できていない
- java8っぽい書き方をなんとなくわかるようになってきた。がまだまだ。
- 年内はSwiftやiOS関係の開発についてお勉強することにした。
- Dockerをちゃんと理解して開発時のDBとかそのた環境まわりとかをスマートに準備したいなぁ
- Typescript2がリリースされたけど全然チェックできてないわ
- Vue.jsの2が発表リリースされたけど全然チェックできてないわ
- 軽度肥満から標準体型になったぞー
jacksonでunix timeをparse
どうやるんだろ?
文字列としてparseしてLocalDateTimeに変換してくれるgetterを作るぐらいしかパッと作れない。
yyyy-mm-ddとかそういうフォーマット指定する例はいろいろ出ててわかるんだけど、unix timeの10桁の数字をLocalDateTimeに変換する方法がわからないーーー
吸収中めも。
Spring Batchの日本語の情報すくないなー。軽い紹介ならいくつかあって参考になって嬉しいんだけど、踏み込んだものがないなー。
本家の英語ドキュメントがなかなかしっかりしてそうなんだけど、英語読むの遅い&読み間違いしそうでツライ。
あんまり実戦投入されてないのかなぁ?
Doma2との連携はなんとかできた。
トランザクション管理は今はSpring任せにしてるけど、doma側でもローカルトランザクションのマネージャーとか存在するみたいだし、どうすべきなのか?
データを書き込むときにdb見て重複チェックしたいときはどうすればいいんだろう?
ファイルの存在チェックはreaderのリスナーで前処理でやるべきか?それともタスクレットでやるべきか
DBと受領ファイル内容の突き合わせチェックをするバッチはどうつくるのか?これはタスクレットで良さそうな気がしてきた。
入力ファイルの項目レベルのバリデーションをアノテーションで実装するには?apt?googleさんのauto-common?勉強不足。これは後で
常駐バッチやら、1日1回のバッチやらいっぱいを1個のプロジェクトで作りたいんだけどmainがあるクラスいっぱいつくればいいのかな?共通的なものはどう定義するんだろな?
今日わかったこと
- CommandLineJobRunnerにconfigのクラスを渡して実行できる
- そのとき各jobのconfigクラスはコンポーネントスキャンからはずさないと面倒
- Domaでinsertは比較的簡単だったけどselectが面倒くさい
- DomaにStream<T> selectが用意されていたけどどう利用していいかわからん・・・
ただのメモ
- intellij::lombok→Annotation Processorsのチェックをつける
- intellij::javadocの追加を⌘+Shift+JでやりたいときはKeymapのfix doc commentに設定
- gradle::domaでcompileJavaが走る前にresourcesにコピーする設定が必要
- intellij::インポートの整理はcontrol+alt+o
最近のことめも
- haskellのお勉強を始めました。
- Springの再入門とか最近のjavaについていろいろお勉強をしている
- Spring BatchでDomaを利用する方法を調査中。
- Spring Batchで○○ファイルが存在するときは処理をする。みたいなことをどうやって実現するのか調査中
- Spring で@Autowiredとかつかわずに@Injectとか書いてインジェクトするためには?
- Spring Batchでlog4j2を使うためにはどうすれば?
- Gradleでマルチプロジェクトの設定方法?
- GradleでCIの設定どうやるの?
- Bean Validation? アノテーションだけでバリデーションかける方法とバリデーションエラー時の挙動の設定は?
その他
- コミュ症を脱出するぞー
- 軽度肥満体型から標準体型になるぞー
vueプロジェクトセットアップ2016/4/14版
2ヶ月も前のやり方でbuildが通るわけないじゃない。
javascriptおそるべし
今回の改良ポイント
- 以前のままだとbuildできない箇所の修正
- vueの公式でおすすめのテスト構成(karma,jasmine)でテストを作る
- ちょっとまともなtestを用意する 簡易コンポーネントを用意してそのテストをする
各モジュールバージョン
- node: v5.10.1
- npm:3.8.6
- babel-core:6.7.6
- vue:1.0.21
まずテストを作る前準備(小さいvueプロジェクト)
setup directory and node_modules
mkdir -p {build,test/{unit,e2e},src/{components,views/app,filters,directives,assets/{js,style,images,html}}}
npm init -y
npm i -g webpack webpack-dev-server babel-core babel-loader node-sass
npm i -S vue vuex
npm i -D babel-core babel-loader webpack style-loader css-loader node-sass sass-loader html-loader babel-plugin-add-module-exports babel-plugin-transform-runtime babel-polyfill babel-preset-es2015 babel-preset-stage-2 babel-runtime file-loader url-loader lodash
npm i -D extract-text-webpack-plugin html-webpack-plugin@2
npm i -D node-bourbon node-neat
.babelrc
{
"presets": ["es2015", "stage-2"]
}
webpack.config.js
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var bourbon = require('node-bourbon').includePaths;
var neat = require('node-neat').includePaths;
var contentBase = __dirname + '/build';
var cssLoader = ExtractTextPlugin.extract('style', 'css?sourceMap!sass')
var htmlWebpackPlugin = new HtmlWebpackPlugin({
filename: 'index.html',
template: 'src/assets/html/index.template.html'
});
var pkg = require('./package.json');
var vendor = Object.keys(pkg.dependencies);
var options = {
sassLoader: {
includePaths: [bourbon, neat]
},
entry: {
app: ["./src/assets/js/app.js", "./src/assets/style/app.scss"],
vendor: vendor,
},
output: {
path: contentBase + '/',
filename: "js/[name].js",
contentBase: contentBase + '/build'
},
resolve: {
alias: {
vue: "vue/dist/vue",
lodash: "lodash"
},
modulesDirectories: ['node_modules', 'src/', 'src/assets/js/', 'src/assets/style/', 'src/views/', 'src/directives/', 'src/filters/', 'src/components/'],
// require()するときに拡張子を省略可能にします
extensions: ['', '.webpack.js', '.web.js', '.js']
},
devServer: {
contentBase: "./build",
},
module: {
preloaders: [],
loaders: [
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "url-loader?limit=10000&minetype=application/font-woff"
},
{
test: /\.png$/,
loader: "url-loader?limit=100000"
},
{
test: /\.jpg$/,
loader: "file-loader"
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "file-loader"
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style', 'css?sourceMap!sass')
},
{
test: /\.html$/,
loader: "html"
},
{
test: /\.js(x?)$/,
loader: 'babel-loader?sourceMaps=true'
}
]
},
plugins: [
htmlWebpackPlugin,
new ExtractTextPlugin('./css/app.css', {disable: false}),
new webpack.optimize.CommonsChunkPlugin('vendor', 'js/vendor.js')
]
};
if (process.env.NODE_ENV === 'production') {
var defplugin = new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
});
var minplugin = new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
});
options.plugins.push(defplugin);
options.plugins.push(minplugin);
options.plugins.push(new webpack.optimize.OccurenceOrderPlugin());
}
module.exports = options;
package.json(script property)
"scripts": {
"hot": "webpack-dev-server -d --inline",
"build": "NODE_ENV=production webpack --progress --hide-modules",
"test": "karma start karma.conf.js",
},
src/assets/html/index.template.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>タイトルを入れてね</title>
</head>
<body>
<app><!-- ここにAPPが入ります --></app>
</body>
</html>
src/assets/js/app.js
import Vue from 'vue';
import App from '../../views/app'
require('../style/app.scss');
new Vue({
el:'body',
components: {App}
});
src/assets/style/app.scss
@import "~bourbon/app/assets/stylesheets/bourbon";
@import "~bourbon-neat/app/assets/stylesheets/neat";
body {
@include outer-container();
background-color: #000000;
color: yellow;
.header {
@include span-columns(12);
background-color: #999999;
}
.navigator {
@include span-columns(5);
background-color: #333333;
}
.footer {
@include span-columns(12);
background-color: #666666;
}
}
src/views/app/index.js
export default {
template: require("./template.html")
}
src/views/app/template.html
<div class="header">ヘッダー</div>
<div class="navigator">ナビゲーター</div>
<div class="contents">コンテンツ</div>
<div class="footer">フッター</div>
ここでnpm run hot
を実行してみる。
ログを見てエラーが出ずにwebpack: bundle is now VALID.
と表示されたら↓URLで確認
http://localhost:8080/
CSSが効いてれば多分問題なし。
停止するときはctrl+c
ついでにnpm run build
でビルドして、buildディレクトリに吐き出されるソースもちょろっと確認
テストを作る
npmまわり準備
npm i -D function-bind jasmine-core karma karma-jasmine karma-phantomjs-launcher karma-spec-reporter karma-webpack phantomjs phantomjs-polyfill phantomjs-prebuilt
やろうとしていること
- ナビゲーター部分をコンポーネントにしてそれをテストする
components/navigator/index.js
export default {
template: require("./template.html"),
data() {
return {
'calcResult': 0,
'value1': 0,
'value2': 0
}
},
methods: {
init(value1, value2) {
this.value1 = value1;
this.value2 = value2;
},
doCalc() {
this.calcResult = Number(this.value1) + Number(this.value2);
}
}
}
components/navigator/template.html
<div class="navigator">
<input type="number" v-model="value1" />
<span> + </span>
<input type="number" v-model="value2" />
<button @click="doCalc">calc</button>
<span class="result" v-text="calcResult"></span>
</div>
views/app/index.js 書き換え
import Navigator from '../../components/navigator'
export default {
template: require("./template.html"),
components: {
Navigator
}
}
views/app/template.html 書き換え
<div class="header">ヘッダー</div>
<navigator></navigator>
<div class="contents">コンテンツ</div>
<div class="footer">フッター</div>
karma.conf.js
// webpackの設定でテストするのに都合の悪い部分を上書き ここから
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var htmlWebpackPlugin = new HtmlWebpackPlugin({
filename: 'index.html',
template: 'src/assets/html/index.template.html'
});
var webpackConf = require('./webpack.config.js');
delete webpackConf.entry;
webpackConf.plugins = [
htmlWebpackPlugin,
new ExtractTextPlugin('./css/app.css', {disable: false})
];
// webpackの設定でテストするのに都合の悪い部分を上書き ここまで
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: './',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'./test/unit/index.js'
],
proxies: {
// 静的なファイルで必要なものはここに登録
//'/assets/images/hoge.svg': './src/assets/images/hoge.svg'
},
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'test/unit/index.js': ['webpack'],
'src/**/*.js': ['webpack'],
},
webpack: webpackConf,
webpackMiddleware: {
noInfo: true
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['spec'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
};
webpackの設定の書き換えはpluginsのCommonsChunkPluginが絡んでくるとkarmaちゃんが動いてくれなくなっちゃうから
何かもっと良い解決方法があるといいな
test/unit/index.js
Function.prototype.bind = require('function-bind');
var testsContext = require.context('.', true, /\.spec$/);
testsContext.keys().forEach(testsContext);
test/unit/navigator.spec.js
import Vue from 'vue';
import Navigator from 'components/navigator';
describe('navigatorのテスト', () => {
Vue.config.debug = true;
Vue.options.replace = false;
const vm = new Vue({
template: '<div><navigator></navigator></div>',
components: { Navigator }
}).$mount();
it('test sample', () => {
expect(vm.$el.querySelector('.result').textContent).toBe('0');
});
it ('calc test', (done) => {
vm.$children[0].init(100, 50);
vm.$children[0].doCalc();
expect(vm.$children[0].$data.calcResult).toBe(150);
// まだ反映していないはず
expect(vm.$el.querySelector('.result').textContent).toBe('0');
vm.$nextTick(() => {
// 反映されるはず
expect(vm.$el.querySelector('.result').textContent).toBe('150');
done();
})
});
});
ここで、npm run test
もしくはnpm test
を実行してみる。
navigatorのテスト
✓ test sample
✓ calc test
PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 2 of 2 SUCCESS (0.003 secs / 0.003 secs)
このようなログがでたら成功。