ushumpei’s blog

生活で気になったことを随時調べて書いていきます。

wgetでサイズ確認

ものすごく小さな話かつググったら速攻出ますが、自分にとっては切実な問題なのでメモします。

結論から言うと--spiderオプションです。

$ wget --spider ***URL.zip***

Spider mode enabled. Check if remote file exists.
--2017-08-31 09:49:43--  ***URL.zip***
...
Length: 11121426 (11M) [application/zip]
Remote file exists.

補足(curl)

たまにwget入ってないよ、となる時があるのでcurlの場合も追記します。普通にヘッダ取得しているだけです。

$ curl --head ***URL.zip***

HTTP/1.1 200 OK
...
Content-Length: 11121426
...

(単位byte)

ちなみにファイルのダウンロード自体はcurl -O ***URL.zip***なのですね。勉強不足です。

感想

一日の通信量上限のあるネット環境で生活しているため、迂闊に大きいファイルをダウンロードすると終わってしまう、と言う背景です。

URLの拡張子がzipな理由は特にないです。

辞書.appのデータ構造の補足

注意: 結論としては補足になっていません。。。RELAX NGXMLスキーマここで勉強した際のメモ書き程度になっています

先日書いた辞書.appの記事ではあまり辞書を作ることに関して調べきれていなかったところがあるので追記します。先日の記事でも単語と意味を登録することはできましたが、MyDictionary.xmlの構造(辞書のデータ構造)について補足していきたいと思います。

MyDictionary.xmlの構造(辞書のデータ構造)

MyDictionary.xmlRELAX NGというxml schema言語で記述されています。xmlに明るくないためやや中途半端な説明になりますが、RELAX NGは外部のデータセットを使用する前提で使われることが大半のようです(参考)

xmlなのでデータを定義するために、簡単な方法を提供してくれているそうです。例えば子要素はelement、属性はattributeなどがあり、それらに対し1つ以上持つ<oneOrMore>、つけてもつけなくても<optional>、どちらか一方だけ<choice>、などの制約をツリーとして書いていくことができます。私のイメージではタグを定義して作っていく感じです。

まず最初の方の行を見ていきます。

<?xml version="1.0" encoding="UTF-8"?>
<d:dictionary xmlns="http://www.w3.org/1999/xhtml" xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
...
</d:dictionary>

ここでは、2つのネームスペース、xmlhttp://www.apple.com/DTDs/DictionaryService-1.0.rngのを宣言しています。またxmlns:dの部分で、d:というプレフィックスを宣言しているため、データセットを使用する際は語頭にd:をつけて使用していくことになります。(ようやくd:entryなどd:をつけて記述していた意味がわかりました)

続いてデータセットを見てどんな定義があるのかを見ていきます。内容は/Dictionary Development Kit/documents/DictionarySchema/modules/dict-struct.rngに記載されております。(http://www.apple.com/DTDs/DictionaryService-1.0.rngはアクセスしても404でちょっと分かっていません。ネームスペースとしてだけ使っているのでしょうか?)

webで公開されているものもあるので、適宜そちらも参照ください。

まず初めに<grammer>が全体を囲っていることから、Named patternsと呼ばれるタグを分割して定義できるようにするパターンで記述していることがわかります(リンク先の セクション4. Named patterns)。

<grammer>は、1つの<start>と複数の<define>を持ちます。<define name="hoge">と定義したものは、<ref name="hoge">により参照することができるため、定義を組み合わせて最終的な<start>を組み立てていく形になります。

ここで定義されている主なものを見てみましょう;

dictionary

<define name="dictionary">
    <element name="dictionary" ns="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
        <zeroOrMore>
            <ref name="style"/>
        </zeroOrMore>
        <ref name="dictionary.attlist"/>
        <oneOrMore>
            <ref name="entry"/>
        </oneOrMore>
    </element>
</define>

dictionaryの定義は、

  • 実態はdictionaryタグ。アップルのネームスペースを属性として指定している。(ネームスペースの必要性の理解が曖昧です。名前が一般的なので、重複しないようにという慣習的なことでしょうか?それかプレフィックスを共通化するためとか関係している?)
    • タグは0個以上のstyleを使用できる
    • タグは1個以上のentryを使用できる
    • タグはdictionary.attlist属性リストを使用できる
      • dictionary.attlistはXTHMLのバージョンと国際化指定を属性として持っているようです

refでは参照先がelementなのかattributeなのかわからないため、どう表現したら適切か悩みます(おそらく言語で表現しにくいからこそ、この記法が使われているのでしょうが)。

entry

<define name="entry">
    <element name="entry" ns="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
        <ref name="entry.attlist"/>
        <zeroOrMore>
            <ref name="index"/>
        </zeroOrMore>
        <ref name="Flow.model"/>
    </element>
</define>

entryの定義は、

  • 実態はentryタグ。
    • 0個以上のindexが使用可
    • Flow.model(なんだこれ。内部にhtml書けることと関係している?)が使用可
    • entry.attlistが使用可
      • entry.attlistid.attrib属性が使用可能(<index id="hoge"とか書ける)
      • parental-control属性が使用可能(任意)
      • title属性が使用可能(任意) <- (なぜなくてもいいのだろう?)

index

<define name="index">
    <element name="index" ns="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
        <ref name="index.attlist"/>
    </element>
</define>

<define name="index.attlist">
    <attribute name="value" ns="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
        <text/>
    </attribute>
    <optional>
        <attribute name="title" ns="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
            <text/>
        </attribute>
    </optional>
    <optional>
        <ref name="parental-control.attrib"/>
    </optional>
    <optional>
        <ref name="priority.attrib"/>
    </optional>
    <optional>
        <attribute name="anchor" ns="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
            <text/>
        </attribute>
    </optional>
    <optional>
        <attribute name="yomi" ns="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
            <text/>
        </attribute>
    </optional>
</define>

indexの定義は

  • 実態はindexタグで、属性としてvalue、オプションの属性としてtitleparental-controlpriorityanchoryomiなどが使用可能

といった形になっています。

つまり?

つまり今のところ、そういうデータ構造になっているということがここを読むとわかるようになったというだけのことでした。。。

これらのデータ構造が辞書データとして取り込まれた時に実際どのように扱われるかをみていく必要があり、補足し切れていないです。

データ構造の読み方はわかった、ならばタグとしてどのような形をしているか、その子要素、属性はどのように扱われるか、それらのことを次にまとめていきたいと思います。

外国語学習のためにMacの辞書.appに追加する辞書を作成する

概要

Macでは設定すると三本指タップで単語の辞書検索が行えます、文章書いている時や読んでる時に作業を中断せずに意味を調べられるのですごく便利に使わせていただいています。

最近フィリピンで生活しているので、タガログ語を読み書きすることがたまにあります。わからない単語を調べるために辞書.appに追加する辞書ファイル(.dictionary)が欲しかったのですが、ネットを探しても見当たりませんでした。

html形式の辞書を見つけたので、Appleの公式ガイドライン(Dictionary Services Programming Guide)から辞書ファイルを作成してみました。その時の手順をメモしておきます。

注意: 以下の手順を行うにはApple Developer Programへの登録が必要です

Dictionary Development Kitのダウンロード

ガイドラインの指示に従い、Downloads for Apple DevelopersからAuxiliary Tools for Xcode - February 2012を検索してダウンロードします。

ダウンロードしたdmgを開くと、Dictionary Development Kitディレクトリがあるので、/Developer/Extras/以下にコピーします。その後、その中にあるproject_templateを自分用の辞書に書き換えていきます。(テンプレートなのでコピーとかして使っていきます)

テンプレートの中身はこんな感じです。

.
├── Makefile
├── MyDictionary.css
├── MyDictionary.xml
├── MyInfo.plist
└── OtherResources
    ├── Images
    │   └── dictionary.png
    ├── MyDictionary.xsl
    └── MyDictionary_prefs.html

2 directories, 7 files

バリデーションツール: jing.jar

辞書ファイルはxmlで、RELAX NGという記法で作成します。xmlフォーマットバリデーションのためjingを、githubから落としてきてビルドしておきます。

$ git clone git@github.com:relaxng/jing-trang.git
$ cd jing-trang
$ ./ant

javaがいります。jdkインストールしてJAVA_HOMEの設定もしておきましょう。

辞書の作成

MyInfo.plistの編集

製作者などのメタ情報を記載していきます。特に配布の予定はないのでざっと変更したくらいです。各キーの説明はCreating Dictionaries > Table 2-1を参照ください。

一旦make

まだ辞書の内容はテンプレートのままですが、完成イメージを見たいのでとりあえずmake & make installしてみます。

$ make
"""/Developer/Extras/Dictionary Development Kit"/bin"/build_dict.sh"  "My Tagalog English Dictionary" MyDictionary.xml MyDictionary.css MyInfo.plist
- Building My Tagalog English Dictionary.dictionary.
- Cleaning objects directory.
- Preparing dictionary template.
- Preprocessing dictionary sources.
- Extracting index data.
- Preparing dictionary bundle.
- Adding body data.
- Preparing index data.
- Building key_text index.
- Building reference index.
- Fixing dictionary property.
- Copying CSS.
- Copying other resources.
- Finished building ./objects/My Tagalog English Dictionary.dictionary.
echo "Done."
Done.

$ make install
echo "Installing into ~/Library/Dictionaries".
Installing into ~/Library/Dictionaries.
mkdir -p ~/Library/Dictionaries
ditto --noextattr --norsrc ./objects/"My Tagalog English Dictionary".dictionary  ~/Library/Dictionaries/"My Tagalog English Dictionary".dictionary
touch ~/Library/Dictionaries
echo "Done."
Done.
echo "To test the new dictionary, try Dictionary.app."
To test the new dictionary, try Dictionary.app.

辞書.appを開き、環境設定から自分の辞書を選べるようになっているので、探してチェックを入れます。これで三本指タップで自分の辞書が表示されるようになりました。

後は辞書の内容をちゃんと書いていくだけです。

MyDictionary.xmlの編集

今回は簡単な辞書を作成していきます。タガログ語から英語の翻訳はwebからスクレイピングしました。

単語の定義ファイルは以下のようになりました

<?xml version="1.0" encoding="UTF-8"?>
<!--
   This is a sample dictionary source file.
   It can be built using Dictionary Development Kit.
-->
<d:dictionary xmlns="http://www.w3.org/1999/xhtml" xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
<d:entry id="dictionary_application" d:title="Dictionary application">
    <d:index d:value="Dictionary application"/>
    <h1>Dictionary application </h1>
    <p>
        An application to look up dictionary on Mac OS X.<br/>
    </p>
    <span class="column">
        The Dictionary application first appeared in Tiger.
    </span>
    <span class="picture">
        It's application icon looks like below.<br/>
        <img src="Images/dictionary.png" alt="Dictionary.app Icon"/>
    </span>
</d:entry>
...
<!-- 単語ごとにd:entryタグを作っていきます -->
<d:entry id="一意な値" d:title="単語名">
  <d:index d:value="検索キー"/>
  <h1>Hoge</h1> <!-- 単語のの内容、htmlかけます -->
</d:entry>
...
</d:entry>
</d:dictionary>
  • htmlMyDictionary.cssマークアップ可能です
  • OtherResourcesディレクトリにアセット、例えばOtherResources/hoge/image1.pngを入れておけばhoge/image1.pngで参照できます

以上です。

感想

ものすごい必要最小限のものができました。 単語間のリンクとかうまくいっていない…今度調べないと…

何よりも辞書を作る作業がとても面倒でした。著作権フリーのものを使って、.dictionary形式で配布したほうがいいかもしれません。というか絶対どこかに「タガログ -> 英語」とか「タガログ -> 日本語」あると思うのですが、なんか見つからないです…

あとhtmlから抜いてきたのも失敗でした、他の辞書フォーマットから変換する処理を書いた方が楽だったかと思います。

iTunes ConnectにアプリをアップロードしてTestFlightでテスト

概要

iTunes ConnectにアプリをあげてTest Flightする方法がわからなかったので、多分これでいけるんじゃないかという手順をまとめました。個人的にメモしておきます。間違い、訂正ありましたら教えていただきたいです。

前提としてApple Developer Program登録済みです

当記事で使用しているXcodeのバージョンは8.3.3です、7以下のバージョンでは「3. XcodeからArchiveをアップロード」で言及しているAutomatically manage sigining機能は使えないようです

手順

0. 既存アプリのリネーム(optional)

簡単のため既存のReact Nativeアプリを再利用します。他の環境の方は無視していただいて結構です。

React Nativeアプリのリネームは簡単です。react-native-renameをインストールし、コマンドを発行します。

$ npm install -g react-native-rename
$ cd path/to/project/root
$ react-native-rename 新しいアプリの名前

1. Apple Developer Portalで新しいApp IDを作成

Developper Portalにログインし、Certificates, Identifiers & Profiles画面のサイドメニューIdentifiers > App IDsをクリックします。画面右上の+を押してApp ID作成に必要な情報を入力していきます。以下は各入力項目の説明です。

f:id:ushumpei:20170710170637p:plain

  1. App ID Description
    • name: 整理しやすいような名前をつける
  2. App ID Suffix (以下どちらかを選択、今回はExplicit App ID)
    • Explicit App ID > Bundle ID: reverse-domain name style stringとか一意になるように名前をつける
    • Wildcard App ID > Bundle ID: com.domainname.*のように指定すると、App IDを複数の(iTunes Connectのレコードという意味での)アプリで使用できるらしいですが、今回は使用しません。

その他は特に変更しませんでした、お好みで設定してください。

2. iTunes Connectで新規アプリレコードを作成

iTunes Connectにログインし、マイ App画面の左上の+を押して新規アプリに必要な情報を入力していきます。

f:id:ushumpei:20170710170736p:plain

今回は、

  • プラットフォーム: iOS
  • 名前: 新しいアプリの名前
  • プライマリ言語: 日本語
  • バンドルID: 先ほどApp IDを作成した時のバンドルIDを選択。
    • セレクトボックスにはname - bundle_idのように表示されます
    • 選択肢に表示されない場合はリロードして見てください
  • SKU: バンドルIDと同じもの
    • SKUはiTunes Connect IDと呼ばれるiTunes Connect内で一意になる値のようです。

を入力しました。

3. XcodeからArchiveをアップロード

3.1. アプリの情報の編集

新しいアプリの名前.xcodeprojファイルをxcodeで開いてGeneralタブへ行き項目を編集します。(react-nativeであればプロジェクトルート以下のios/新しいアプリの名前.xcodeprojにあります)

f:id:ushumpei:20170710170904p:plain

  • Identity
    • Bundle Identifier: iTunes Connectで新規アプリレコード作成の際に入力した値
    • Version: 0.0.1
    • Build: 0.0.1
      • VersionとBuildは変えなくてもいいですがせっかくなので。
  • Signing
    • Automatically manage sigining: チェックを入れます、プロビジョニングファイルの作成などやってくれるのでおすすめです。
    • Team: 自分のチームを選択してください

以上で設定終了です。

3.2. Archiveのアップロード

画面上部、Product > Archiveを選択しアーカイブを実行します。しばらく時間がかかる処理です。アーカイブが完了すると、ウィンドウが立ち上がります。

注意: Archiveが選択できない場合があるので、こちらを参考にしてください。

f:id:ushumpei:20170710170940p:plain

アップロードしたいArchiveを選択し、ウィンドウ右のUpload to App Store...を押すとアップロードの準備に入ります(先にValidate...を押してからの方が堅実だと思います、今回はやりませんでしたが)。

チームを聞かれるので自分のものを選択すると、アップロード画面になります。内容が問題なければUploadを押してください。これも、しばらく時間がかかる処理です。アップロードが完了しビルドが作成されるとiTunes Connectからメールが来るので、気楽に待ちましょう。

ただし、失敗することもあるので、20分くらい音沙汰がなければアップロード画面の結果にエラーがないか確認しましょう。(Validate...してからのアップロードなら、多少は安心していいかもしれません)

注意: Uploadを押した後、処理の表示がAuthenticating with the iTunes storeで止まってしまうことがあるようです。全てに対応できる方法かはわかりませんが、この辺りが参考になりました

4. iTunes Connect でTestFlightのテストを開始

4.1. TestFlightの準備

再びiTunes Connectにログインし、マイ Appで先ほど作成したアプリを選択します。タブからTestFlightを選択すると、アップロードしたビルドが表示されているかと思います。

f:id:ushumpei:20170710172810p:plain

ビルドに「輸出コンプライアンスがありません」と警告が表示されています、この状態ではまだTestFlightでテストを開始することができません。ビルドの値を押すと、画面が切り替わり、コンプライアンス情報を提出というボタンを押すとモーダルが表示されます。今回特に暗号化していないのでいいえを選択しました。モーダル右下の内部テストを開始を押すと、テストの準備が整いました。

f:id:ushumpei:20170710173317p:plain

4.2. テストへの招待

サイドメニューのテスター & グループの小項目iTunes Connect ユーザを追加外部テスターを追加を選択しテストへの招待を行います。今回はiTunes Connect ユーザを追加から自分に対して招待を行いました。

5. 終わり

TestFlightからメールが届くので指示に従い、TestFlightアプリをインストールしている端末からテストが開始できるようになります!

感想

おそらくはこれでいいだろうというものをまとめてみました。自分の環境ではダメだったなど、ご指摘いただければ幸いです。

特に使いだしてから色々いじった気がするのでXcode周りの手順がやや不安です。

FlatListのデータ更新時に再描画されない

概要

ちょっと困ってしまって、検索が時間かかったので他の人の手助けになればと思いメモします。

問題

React NavigationとFlatListでリスト編集サンプルアプリを作成した時に、FlatListのデータ更新時に再描画されない問題に遭遇しました。

  • データをFlatListで表示する画面がある
  • 他の画面でデータを更新する
  • FlatListの画面を開くとデータが描画されていない(更新したものだけでなく、元からあったものの描画されない)
  • ちょっとスクロールすると再描画される

なんだこれ?と悩んでしまいました。

解決

検索するとextraDataを設定しろとか色々見つかったのですが、このIssueから解決できました。

github.com

コメントで言及されているケースと同じ状態だったのでFlatListremoveClippedSubviews={false}を追加してあげると再描画されるようになりました。

感想

removeClippedSubviewsは高速化のためのフラグだそうです。FlatListがラップしているVirtualizedListのドキュメントにこのプロパティに関する言及があります。またこのページに「バグを引き起こすかも」、という注意がされているのも確認できます。

上記の方法でもうまくいかないケースがあるそうなのでIssueを読んでみると何か糸口が見つかるかもしれません。