業務で作成したiOSアプリの障害についてのメモ
障害内容
iOS 12.2
以降の端末でIonic v3.9.3
で作成したiOSアプリを動かしたら、スクロールができなかった。
改修方法
Ionic v3.9.5
以前のバージョンによるバグが原因の障害となる。ionic-angular
のバージョンを3.9.5
までアップグレードすると、スクロールできるようになる。
参考サイト
詳細は、Ionicのv 3.9.5のドキュメントを参照のこと
業務で作成したiOSアプリの障害についてのメモ
iOS 12.2
以降の端末でIonic v3.9.3
で作成したiOSアプリを動かしたら、スクロールができなかった。
Ionic v3.9.5
以前のバージョンによるバグが原因の障害となる。ionic-angular
のバージョンを3.9.5
までアップグレードすると、スクロールできるようになる。
詳細は、Ionicのv 3.9.5のドキュメントを参照のこと
Angularで作成したサイト(GitHub Pagesにデプロイ)を、更新したくなった時はどうすればいいんだろう?私、わかりません...という記事です。ググるなり Stack Overflowで聞くなりしろよという話なんですが
WebサイトはAngular v7で作成しました、Web APIとかはない。
上記のサイトを、angular-cli-ghpagesというライブラリを利用してデプロイしました(デプロイ対象のブランチはgh-pages
)。
デプロイするにあたって実行したコマンドは下記となります。
$ npm install -g angular-cli-ghpages $ ng build --prod --base-href "https://l08084.github.io/morse-code-translate-website/" $ git checkout -b gh-pages $ git push origin gh-pages $ ng build --prod --base-href "https://l08084.github.io/morse-code-translate-website/" $ ngh --dir=dist/morse-code-tweet
普通に修正したい資源を更新して、gh-pages
ブランチにプッシュするだけだとサイトの表示が変になってしまったので、適当なやり方でサイトの更新をしました。正しい更新方法が知りたい。
gh-pages
ブランチを削除する
Angularを使用して、日本語・英語をモールス信号に変換するWebサイト「モールス信号 翻訳」を作成しました。
↓のURLから実際に触ることができます
https://l08084.github.io/morse-code-translate-website/
GitHubにソースコードもアップしています
TypeScript(JavaScriptのスーパーセット)のフレームワークであるAngular(v7)を使用して作成しました。 CSSフレームワークはAngular Materialを利用しています。
「モールス信号 翻訳」には、日本語・英語をモールス信号に変換する機能と、モールス信号を日本語・英語に逆変換する機能があります。
アカウント登録などの機能はないためAPIがない、いわゆる静的サイトになっています。(フロントサイドで完結するから作るのが楽だったということを言いたい)
ソースコードの中身について解説していきます
$ tree -I node_modules
コマンドで出力したディレクトリ構成(一部ファイル省略)。
. ├── src │ ├── app │ │ ├── app.component.html │ │ ├── app.component.scss │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── components │ │ │ ├── description │ │ │ │ ├── description.component.html │ │ │ │ ├── description.component.scss │ │ │ │ └── description.component.ts │ │ │ ├── header │ │ │ │ ├── header.component.html │ │ │ │ ├── header.component.scss │ │ │ │ └── header.component.ts │ │ │ ├── input │ │ │ │ ├── input.component.html │ │ │ │ ├── input.component.scss │ │ │ │ └── input.component.ts │ │ │ ├── output │ │ │ │ ├── output.component.html │ │ │ │ ├── output.component.scss │ │ │ │ └── output.component.ts │ │ │ ├── select │ │ │ │ ├── select.component.html │ │ │ │ ├── select.component.scss │ │ │ │ └── select.component.ts │ │ │ └── share-button │ │ │ ├── share-button.component.html │ │ │ ├── share-button.component.scss │ │ │ └── share-button.component.ts │ │ └── service │ │ ├── convert.service.spec.ts │ │ └── convert.service.ts │ ├── assets │ │ └── mapping.json │ ├── index.html │ ├── styles.scss └── tslint.json
ディレクトリ構成をみればわかる通り(?)、ルートコンポーネントに下記のコンポーネントがぶら下がっている構成になっています。
上記のコンポーネントに加えて、テキスト⇄信号 変換のビジネスロジックが記述されているConvert サービスクラスがあります
ルートコンポーネント(AppComponent)では、子コンポーネントにAngularの@Input
と@Output
を使用して値の受け取りと受け渡しを行なっています。
input コンポーネントは、翻訳したいテキスト・モールス信号を入力するテキストエリアの役割を持っています。
input コンポーネントでは、下記の処理を行なっています。
テキストからモールス信号に変換するロジックですが、Mapデータ構造を使用しました。具体的には下記の手順になります。
数字がずっと0から変わらない気がする...share-buttonコンポーネントの実装、ひいてはSNSシェアボタンの表示方法ですが、各種SNSの開発者サイトにいくとシェアボタンのコードが提供されているので、それをコピペして貼り付けるだけです(開発者アカウントの登録などは必要ありません)。
注意点としては、SNSの開発者サイトだと、ボタンのHTMLタグとスクリプト(script)タグが一緒くたにされているため、コピペするときは分割する必要があります。ボタンのHTMLについては、コンポーネントのHTMLにコピペして、<script>
については、index.html
の方に貼り付ける必要があります。
テンプレートファイルには、SNSシェアボタンのHTMLタグだけを貼り付けます。
share-buttonコンポーネントのテンプレートファイル
SNSシェアボタンの<script>
はindex.html
に貼り付けます
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>モールス信号翻訳</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content="日本語(ひらがな・カタカナ)や英語(アルファベット)をモールス信号に変換するサービスです。"> <meta name="keywords" content="モールス信号,モールス符号,モールス,和文モールス,和文モールス符号,和文モールス信号"> <link rel="icon" type="image/x-icon" href="favicon.ico"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <script async defer crossorigin="anonymous" src="https://connect.facebook.net/ja_JP/sdk.js#xfbml=1&version=v3.2"> </script> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> <script type="text/javascript" src="https://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"> </script> </head> <body> <app-root></app-root> </body> </html>
GitHub Pageへのデプロイ方法について
How to deploy an Angular 7 app to Github Pages | by Marina Ferreira | Code Sketch | Medium
Angular 7系以降のデプロイ方法については、上のサイトが詳しいです。
↓は自分がGitHub Pagesにデプロイした時のコマンドです。
$ npm install -g angular-cli-ghpages $ ng build --prod --base-href "https://l08084.github.io/morse-code-translate-website/" $ git checkout -b gh-pages $ git push origin gh-pages $ ng build --prod --base-href "https://l08084.github.io/morse-code-translate-website/" $ ngh --dir=dist/morse-code-tweet
休日にテキストとモールス信号のマッピング表を作ってると虚無感がすごい。「あ・い・う・え・お」とか打つ必要があるので(虚無感というか虚無そのものだった気がする)
SourceTreeでgit push
を実行した時に下記のようなメッセージが表示されて失敗した。
git -c diff.mnemonicprefix=false -c core.quotepath=false --no-optional-locks -c credential.helper= -c credential.helper="C:/Users/XXX/AppData/Local/ATLASS~1/SOURCE~1/GIT_EX~1/GIT-CR~1.EXE" push -v --tags origin master:master Pushing to https:/XXX/gitlab/XX/XXX.api To https://XXX/gitlab/XX/dXXX.api updating local tracking ref 'refs/remotes/origin/master' error: failed to push some refs to 'https:/XXX/gitlab/XX/XXX.api' hint: Updates were rejected because the tag already exists in the remote.
git pull --tags
ターミナルを立ち上げて上記コマンドを実行すると、git push
ができるようになる。
AngularでFluxを実現するために採用されるライブラリについては、NgRxがデファクトスタンダードになりつつあるのではないか.....という話を結構前に聞いたのでNgRxの学習をそろそろ始めることにする。
NgRx以外のFluxライブラリを使ったことは何度かあるので、Fluxの概念については理解しているつもり
Angular CLIを利用して、Angularプロジェクトを作成した後に@ngrx/store
ライブラリをインストールする。
https://ngrx.io/guide/store/install
Angular CLIのバージョンが6以上の場合は、npmやyarnで@ngrx/store
ライブラリをインストールする以外にも、ng add
コマンドを使用して(Angular CLI経由で)@ngrx/store
ライブラリをインストールすることができる。
$ ng add @ngrx/store
ng add
コマンドで@ngrx/store
ライブラリをインストールすると、app.module.ts
の設定と、src/app/reducers/index.ts
の新規作成まで自動でやってくれる。
ただ、今回は自分で設定をしたかったので、npm i @ngrx/store
でインストールを実行した。
公式サイトで@ngrx/store
のチュートリアルアプリとして用意されているカウンターアプリを作成したので、解説する。(なお、公式サイトのものとはディレクトリ構成が異なっている)。
作成したカウンターアプリのディレクトリ構成を$ tree -I node_modules
コマンドで出力した(一部ファイルは省略している)。
├── src │ ├── app │ │ ├── app.component.html │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ └── components │ │ └── my-counter │ │ ├── action │ │ │ └── counter.actions.ts │ │ ├── reducer │ │ │ └── counter.reducer.ts │ │ └── view │ │ ├── my-counter.component.html │ │ └── my-counter.component.ts └── ・・・
まず、FluxのActionを担当するファイルであるcounter.actions.ts
から解説する。今仕事で使っているFluxライブラリ(自社製)とはすでに大きく違っている。
カウンターアプリのイベントである"加算"、"減算"、"リセット"をそれぞれアクションとして定義している。
今の仕事で使っているFluxライブラリだと、アクションの定義だけでなくWebAPIの呼び出しや、実際にStateの値を変更するStoraクラスの呼び出しなど(ActionをStoreに渡す)をやっていたため、結構な違いを感じてとまどう。
続いてReducerを担当しているcounter.reducer.ts
について。今仕事で使っているFluxライブラリだとStoreでStateの変更をおこなっているが、NgRxでは渡されたアクションに応じてReducerが新しいStateを返す形式になっているらしい。
export const initialState = 0;
の部分でStateの初期化を行っている。
ルートモジュール設定ファイルであるapp.module.ts
について。NgRxに関連している設定として、imports[]
でReducerの登録を行っている(StoreModule.forRoot({ count: counterReducer })
)のと、Redux Dev Toolの設定をしている(StoreDevtoolsModule.instrument({}),
)。
カウンターコンポーネントのテンプレートファイル。カウンター値の表示と、加算、減算、リセットボタンを表示を担当している。
stateの値であるcount$
はObservable
型なのでasync
パイプを使用して値の表示を行っている。
select
でstate
の値の読み込みと、加算、減算、リセットのアクションをディスパッチして、Reducerを呼び出すメソッドをそれぞれ定義している。
ルートコンポーネントでは、カウンターコンポーネントを定義しているだけ
少し触ってみた感想としては、NgRxはReduxよりのFluxライブラリなのでは...という印象を受けた。Redux使ったことないので習得に時間がかかりそう
引き続き、『入門 Python 3』を読んでいて印象に残った箇所をメモに残していく
【Python3】特徴的だと思った機能まとめ その3 - 中安拓也のブログ
https://www.oreilly.co.jp/books/9784873117386/
オライリーの『入門 Python 3』
\
による長い行の分割バックスラッシュ(\
)で行を分割することができる。
>>> age = 15 # 三項演算子の行を分割して読みやすくしている >>> name = 'みゃー姉' \ ... if age >= 18 \ ... else 'アカネ' >>> name 'アカネ'
内包表記とは、イテレータ*1からPythonのデータ構造をコンパクトな構文で作成できる機能を指す。
内包表記で作成できるデータ構造として、リスト、辞書、集合などがあり、それぞれリスト内包表記、辞書内包表記、集合内包表記といった感じに命名されている。
リストをシンプルな構文で作成できる。リスト内包表記の文法は下記の通りとなる。
[expression for item in iterable]
[expression for item in iterable if condition]
# 単純な形式のリスト内包表記 >>> numList = [num for num in range(1, 7)] >>> numList [1, 2, 3, 4, 5, 6] # 0 ~ 7の値を取り出して二乗した後、リスト化している >>> squaringList = [i * i for i in range(0, 8)] >>> squaringList [0, 1, 4, 9, 16, 25, 36, 49] # 条件を追加したリスト内包表記 >>> evenList = [j for j in range(0, 8) if j % 2 == 0] >>> evenList [0, 2, 4, 6]
ディクショナリも内包表記を使用してワンライナーで作成することができる。{key_item : value_item for item in iterable}
# リストを定義 >>> marshalList = ['ランヌ', 'ミュラ', 'ダヴー', 'ベルティエ', 'ネイ'] # 内包表記でdictを作成 >>> marshal_dict = {i : marshalList[i] for i in range(0, 5)} >>> marshal_dict {0: 'ランヌ', 1: 'ミュラ', 2: 'ダヴー', 3: 'ベルティエ', 4: 'ネイ'}
*1:要素を順番に取り出すことのできるオブジェクトのこと。リスト(配列)、辞書、集合、タプルなど
引き続き、面白いな〜と思った機能をまとめていく(2)
【Python3】特徴的だと思った機能まとめ その2 - 中安拓也のブログ
https://www.oreilly.co.jp/books/9784873117386/
オライリーの「入門 Python 3」
del
文を使用することで、指定したオフセットの要素または、配列(リスト)や辞書そのものを削除することができます。
>>> soulBorne = ['DARK SOULS', 'DARK SOULS II', 'DARK SOULS III', 'Bloodborne'] # リストを定義 >>> del soulBorne[1] # リストの2番目の要素を削除 >>> soulBorne # 要素が削除されていることを確認 ['DARK SOULS', 'DARK SOULS III', 'Bloodborne'] >>> del soulBorne # 配列soulBorneごと削除 >>> soulBorne #削除されていることを確認 Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'soulBorne' is not defined
あんまり使わなそうな機能な気がする。。Pythonの経験0なのでわかりませんが...
リストや文字列、辞書や集合などに指定した値が含まれているかを確認する
>>> fromsoftware = ['DARK SOULS', 'DARK SOULS II', 'DARK SOULS III', 'Bloodborne', 'SEKIRO'] # リストを定義 >>> 'SEKIRO' in fromsoftware # 'SEKIRO'はリストに含まれている True >>> 'splatoon' in fromsoftware # 'splatoon'はリストに含まれていない False >>> 'hedoro' in 'Dorohedoro' # リストだけではなく、文字列にも使える True >>> 'hayashida' in 'Dorohedoro' False
TypeScriptにもタプル型はあり、関数から複数の値を返す時などに使用することができます。
Pythonのタプルについても同様に一度に複数の変数に代入するなどの使い方もできますが、イミュータブルで値の追加・削除・変更ができない、定数リストとして使われることの方が多いそうです。
# ()を使って空のタプルを作成することができる >>> empty_tuple = () >>> empty_tuple () # 2個の値を持ったタプルの作成 >>> brother = ('虎杖', '藤堂') >>> brother ('虎杖', '藤堂') # ()を省略してもカンマがあればタプルを作成できる >>> freshman = '虎杖', '伏黒', '釘崎' >>> freshman ('虎杖', '伏黒', '釘崎') # 一度に複数の変数に値を代入することができる(タプルのアンパックと呼ばれる) >>> omimura, mikuriya = 'hinata', 'hikage' >>> omimura 'hinata' >>> mikuriya 'hikage'