tag:blogger.com,1999:blog-77939124853911975842024-02-22T13:36:49.920+09:00guess what?iOSのこととか いろいろ。Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comBlogger436125tag:blogger.com,1999:blog-7793912485391197584.post-52867117333345865152021-11-12T16:11:00.011+09:002021-11-12T17:20:20.027+09:00UIColor の Hex String と Color Space<p>UIColorを、#000000 のような 16進数(Hex String)に変換する方法。ググるといくつか出てくると思う。以下のようなやつ。<br /><br /></p>
<script src="https://gist.github.com/aqubi/e1ac6b6e37279ec576616518ed69ba41.js"></script>
<p><br /></p><p>toHexString1() は、cgColorのcomponentを使う方法。<br />toHexString2() は、getRed で取得する方法。<br />toHexString3() は、CIColor 経由で取得する方法。</p><p>コレらをそのまま使うと、変換に失敗する場合もある。<br /></p><p>注目すべきは、UIColor が どの Color Spaceが使われているか?<br /><br /></p><p>Display P3などは、sRGBよりも大きな範囲が対象になるので、、Extended sRGBに変換すると0.0 から 1.0 に収まらない値、つまり、マイナスや、1.0 より大きい数字になる場合がある。</p><p>Display P3 で r, g, b = 1.0, 0.0, 0.0 は、Extended sRGB で、r, g, b = 1.093, -0.227, 0.15 になる。<br />(使用しているiOSのバージョンによって差異あるかも)</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipnI_wQCVF4x2xGCUteR1S9ISdadu-V6rreSoZVw9bnGCL7r7fB_UYH9jq3aZKRNQJ430JELzVAQLFbCnQdU0A8Pi3alsEfTbJqmLOmKk3hVLVRZaeN9giODJZpvaYFtMgM80HCi1PohE/s1978/Screen+Shot+2021-11-12+at+15.19.19.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="852" data-original-width="1978" height="276" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipnI_wQCVF4x2xGCUteR1S9ISdadu-V6rreSoZVw9bnGCL7r7fB_UYH9jq3aZKRNQJ430JELzVAQLFbCnQdU0A8Pi3alsEfTbJqmLOmKk3hVLVRZaeN9giODJZpvaYFtMgM80HCi1PohE/w640-h276/Screen+Shot+2021-11-12+at+15.19.19.png" width="640" /></a></div><p><br /></p><p>「1. CGColorSpace.displayP3 で作成」と、「2. displayP3Red で作成」は、ともにDisplay P3 の値を指定して作成する方法だが、上記のように構成は変わるみたい。</p><p>「2. displayP3Red で作成」の時のように、UIColorをprintで表示した情報と、cgColorの情報は一致しない場合もある。</p><p>UIColorPickerViewControllerで取得できる色は、「1. CGColorSpace.displayP3 で作成」の方の構成。<br />UIColorPickerViewControllerで、Color Spaceを指定できれば良いのになぁ。</p><p>また、GrayScaleの場合、componentsの数は2つになることも注意。</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhXiiwNU3ByO8kCDUSL-nzIgIRF37iO85WxZ25nJrOa2TcatCk2EBwEgkpovKybjx2t-Ab-ol3qJFqfYYBzdrPwKhMqTilNYTfoC5gT2vBnxYh6wsJ8b0Z0_4sBn6sB8R4vvl2_f8IgJA/s1458/Screen+Shot+2021-11-12+at+15.32.05.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="308" data-original-width="1458" height="136" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhXiiwNU3ByO8kCDUSL-nzIgIRF37iO85WxZ25nJrOa2TcatCk2EBwEgkpovKybjx2t-Ab-ol3qJFqfYYBzdrPwKhMqTilNYTfoC5gT2vBnxYh6wsJ8b0Z0_4sBn6sB8R4vvl2_f8IgJA/w640-h136/Screen+Shot+2021-11-12+at+15.32.05.png" width="640" /></a></div><p><br /></p><p>安全に Hex Stringを作成するためには、sRGB (or Display P3) に変換してから作成するのが良さそう。</p>
<p>
<script src="https://gist.github.com/aqubi/4cd0aae1a732825f6f9b3a05d374835e.js"></script>
</p>
<br /><br />
<h2 style="text-align: left;">UIColor をアプリに保存する</h2>
<div>UserDefaultなどに保存する場合、Hex Stringにする、NSKeyedArchiverでDataにするとがが考えられる。</div><div>Display P3の色をNSKeyedArchiverでアーカイブして復元すると、Extended sRGB の構成の色になるみたいだ。</div><div>なので、選択した色をできるだけ同じ構成で復元したい場合は、Color Space名、componentsの値の両方を保存するのが良さげかも。</div><div><br /></div><div><br /></div>
<h3 style="text-align: left;">おまけ</h3><div>Hex StringからUIColor(sRGB)を作成するコード</div><div>
<script src="https://gist.github.com/aqubi/212cf6dd50dc870d394d8c9f4f8bb547.js"></script>
<br /></div>Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-90451694539598801812021-11-03T23:18:00.006+09:002021-11-04T00:11:02.392+09:00Ratio 電卓 アプリを作りました!<div class="separator" style="clear: both; text-align: center;">
<a href="https://apps.apple.com/app/id1592937943" style="margin-left: 1em; margin-right: 1em;">
<img border="0" data-original-height="1080" data-original-width="1080" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilj-2XnblaqwBFDGKGH3inp54FvXBEJdqnyHFBO-n3f9yZGYMaXUA1RRcuD54JuOlWUhFk0tirJnXGrFGNZlrtqiBbG9jmq3ZM8fuHz3cZ2j8NVeJ17NfGDvp5owIHL7qeZDtjvSxFgMs/s320/ratio_1080x1080.png" width="320" />
</a>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgx9e8-AiFTrpLdWUyg08S440F9IrIX2vF0H_8i_ljMZabRVCX8VpWdJzU3dWlkBl61mOoRHGlSkJ-auGSKb5OkqYO19Y37YoMyoCx7dpoZJFhWYLhLEJqXCj-tOPfSOtzpxtwDnpcvULc/s1080/preview.png" style="margin-left: 1em; margin-right: 1em;">
<img border="0" data-original-height="1080" data-original-width="1080" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgx9e8-AiFTrpLdWUyg08S440F9IrIX2vF0H_8i_ljMZabRVCX8VpWdJzU3dWlkBl61mOoRHGlSkJ-auGSKb5OkqYO19Y37YoMyoCx7dpoZJFhWYLhLEJqXCj-tOPfSOtzpxtwDnpcvULc/s320/preview.png" width="320" />
</a>
</div>
<br />
<div class="separator" style="clear: both; text-align: center;"><br /></div><p>個人的に作っていたアプリがいくつかあるのだが、その一つ、シンプルな電卓アプリをリリースしてみた。</p><p>きっかけは、「おからを、おからパウダーで代用する時の計算を簡単にしたい」 </p><p></p><blockquote>おからパウダー 1g に対して、水を3.5gを加えると、おからができる。<br />そのとき、おから ○○g を作るには、それぞれ何g必要なのか? </blockquote><p></p><p>というのが、いつも暗算できない。</p><p>最近のマイブームが糖質オフのお菓子作りなのもあり、この計算をすることが度々ある。おからパウダーは100均で入手できるのでお財布にも優しく、保存もきく、食物繊維も多い、という有難い食材。</p><p>このようなパターンを汎用的にしてみたものに加え、比例式の計算もできるようにした。<br />こういう理解しやすいレイアウトで数値を並べないと、頭が働かない私...。</p><p><br /></p><h2 style="text-align: left;">Text Calculator</h2><p>そして、iPadの時は、KeyboardよりもApple Pencilで数字を書いた方が早いんじゃ?と思い、追加したのが Text Calculator。</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKrjeJbe8tT6k6S2j7Cs7owOFmCu59-48gfjee7umYaQELPrVEfM1-67DkVMHKFDV3yRKZ0lo3rDls5KbCzyX1JQwGTGhRH-o1urx8OIqNW4Rf-peXquDRSPu-akoTRHalIG65KzInoUc/s1133/ipad.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="744" data-original-width="1133" height="263" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKrjeJbe8tT6k6S2j7Cs7owOFmCu59-48gfjee7umYaQELPrVEfM1-67DkVMHKFDV3yRKZ0lo3rDls5KbCzyX1JQwGTGhRH-o1urx8OIqNW4Rf-peXquDRSPu-akoTRHalIG65KzInoUc/w400-h263/ipad.png" width="400" /></a></div><br /><p>Pencilで書き込みやすいように、レイアウトしている。また、+, - などの計算記号は、うまく認識できないことが多いのでボタンで配置している。</p><p>計算は、<a href="https://developer.apple.com/documentation/foundation/nsexpression" target="_blank">NSExpression</a> を利用しているので、( ) を使ったものなど、ある程度の計算式は認識可能。<br /></p><p><br /></p><p>限られたシチュエーションであれば、便利と思うので、よければお使いください。<br />無料でーす!広告なしでーす!</p>
<br />
<br />
<div>
<a href="https://apps.apple.com/app/id1592937943">
<img alt="Download on the App Store" src="https://tools.applemediaservices.com/api/badges/download-on-the-app-store/black/en-us?size=250x83&releaseDate=1635811200&h=c0b39b674d1eebdbed8e027d3291b23c" style="border-radius: 13px; height: 83px; width: 250px;" />
</a>
</div>Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-61405443761793497832020-09-20T13:45:00.002+09:002020-09-20T13:56:50.693+09:00Ermine をリリースしました!<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://apps.apple.com/jp/app/ermine/id1524806091" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1190" data-original-width="1720" height="443" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikeaMMvZmtkdDpMEEfD5hQGfcNxTImFfhTK971ppoAtBxma7KH9yH06kUN7h8MDh4Rr3wirulLULj53mPIj_rtwX-WArR47l1nMaCzy5Nq-Fr7Eip427Z6CXbEbSIsejHUDNx3lZpING8/w640-h443/Ermine2%25402x.png" width="640" /></a></div><br /> <p></p><p>Monthly Calendar & Widgets アプリ、<a href="https://apps.apple.com/jp/app/ermine/id1524806091" target="_blank">Ermine</a>(アーミン)をリリースしました!<br />月カレンダーのウィジェットをカスタマイズができるのが一番の特徴。<br />iOS 14にしてウィジェットを探している方、ぜひお試しくださいませ。無料です。</p><p><br /></p><h3 style="text-align: left;">ウィジェット (iOS 14)</h3><p>ウィジェットに置きたいものは、やっぱり定番の天気予報とカレンダー。両方ともAppleのアプリであるのですが、祝日が赤色にならないのが不満。</p><p>...という人、いませんか?</p><p>Ermineは、祝日が赤色になって、イベントがある日はドット・がつきます。小さいウィジェットに情報がぎゅっぎゅっと詰まっています!<br /></p><p>イラストカレンダーは、<a href="https://nicovo.com/" target="_blank">nicovoさん</a> とのコラボです。初コラボ!<br />月ごとにイラスト変わりますよー<br />9月のクマポイも好きなんですが、8月のウサコさんも好き。8月が一年後なのが寂しい。<br />コラボしようと思い立ちお話始めたのが、8月20日というギリギリのタイミングだったのに快諾してくれて感謝!</p><p><br /></p><h3 style="text-align: left;">アプリのカレンダー</h3><p>アプリ本体のカレンダーは、月表示のみのシンプルなもので、大事な予定に注目できるような作りになっています。<br />月表示のところは、枠線や背景塗りが無いスッキリ表示、祝日のイベント名は表示なし です。</p><p>私だけでデザインしたら、よくあるカレンダーアプリのように、枠線つけたり、カレンダーの色で背景塗りしたりと、ぐちゃぐちゃ入れちゃってると思うので、デザイン案をみたときは、わー!となりました。</p><p><br /></p><h3 style="text-align: left;">開発のきっかけ</h3><p>もともと、こよみ(Coyomi)という、同様な機能の月カレンダーをToday ウィジェットに表示できる小さなアプリを作っていたのですが、その iOS 14のウィジェット版が欲しいというのが開発を始めたきっかけ。</p><p>開発当初は、機能はウィジェットだけの予定でした。<br />ですが、アプリ本体にもカレンダー機能が一通り入ることになり、どんどん機能が増えていき....最後は休みなしの開発でなんとか作り上げました。間に合ってよかったー</p><p><br /></p><h3 style="text-align: left;">キャラクター</h3><p>アプリアイコンになっている、イメージキャラクターは、オコジョ(冬毛) です。<br />(オコジョは英語でErmine)</p><p>小さい、シンプル、動きが早いというイメージがアプリに合っているかなと。<br />オコジョ、かわゆすぎる...!気になった方は画像検索してみてください。<br /><br /></p><p>時間が足りなくて、アプリ内にはまだあまり登場できてないけど、今後増えていく..カモ?</p><p><br /></p><h3 style="text-align: left;">SwiftUI</h3><div>内部の話になりますが、このアプリは全てSwiftUIで作ってみました。<br />本格的に使ってみるのは初めてだったので、どうなるかな?と思っていたけど、なんとかなったみたい。<br />だけど大変でした。慣れていないせいもあるのだろうけど、まだ少し採用するのは早かったかな?という気もしてます。<br />SwiftUIの経験談はまた別途書こうと思います。</div><div><br /></div><div><br /></div><div><br /></div><div>アプリを気に入ってくれましたら、レビュー、Tip よろしくお願いします!</div>Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-82439963266607368622020-07-23T13:08:00.002+09:002020-07-23T13:24:21.673+09:00SwiftUIのみでアプリを作れるか?ただいま、SwiftUIだけを使って新規アプリを作ってみるチャレンジ中。<div>いままでSwiftUIをApple Watchの一部でしか使ってなかったので、ほぼイチから学ぶ状態ではあるが、iOS14 Day1に向けて頑張り中。</div><div><br /><div>せっかく新しく作るのであれば、Multi Window / Multi Platform でも大丈夫なものを作成したい。が、まだ頭がなれなくて難しい。</div><div><br /></div><h2 style="text-align: left;">SwiftUIの第一印象</h2><div>現時点でのSwiftUIの感想は、</div><div>Viewを作成しなおすことを躊躇なくやることにしたんだな </div><div>と。</div><div><br /></div><div>いままでUIKitを使っていたときは、Viewをレイアウトして描画する処理はコストが高いので、Viewはできるだけ使いまわし、データを入れ替える という設計思想があった。</div><div>対して、SwiftUIは、Viewに対するデータは、1対1にして結合することで管理しやすくなる反面、Viewを作成する回数は増える。</div><div><br /></div><div>その代わり、SwiftUIのViewのレイアウトの計算は、UIKitに比べてコストがかからないようになっているように感じる。</div><div>まだ把握しきれてないが、Viewのサイズは自身のViewが決定し、親Viewで決定できない感じ?StackViewのfillの指定が無いみたいな。</div><div>いまはまだ、UIKitのときのように設定できないのが、イライラしてしまうがw</div><div><br /></div><div>とはいえ、無駄に大きなViewを何回も作成しなおすのは良くないので、データ設計はいままでよりも、しっかりやらないといけない感。</div><div><br /></div><div>変更される可能性があるデータと、変更されないデータ。</div><div>データを保持する場所と、参照する範囲。</div><div><br /></div><div>そして、ViewはPreviewしやすいものにしたいので、EnvironmentObjectはあまり使わないように...と考えると、考慮することは多い。</div><div><br /></div><div>デバイスのスペックは高くなったし、macOSだとユーザがViewサイズを変えることができるので、こういう方向性になったのは納得感はある。</div><div><br /></div><div><br /></div><h2 style="text-align: left;">プログラム初心者には?</h2><div>SwiftUIは、プログラム初心者が学ぶにはいい?って思ってたけど、考えが変わった。</div><div>データが変更された → Viewを変更する という手順をOSが行うので、コード量は減る。が、見えないところも多くなるので、理解は難しそう。値渡し/参照渡しの理解も必須だろうし。</div><div>BlackBoxのところでハマるのはツラい。</div><div>だけど、ViewControllerのDelegateを作る必要もなさそうだし、理解が必要なことが単純に増えるわけではない。</div><div>classよりもstructに慣れる強制力としてはいいかもしれない。</div><div><br /></div><div><br /></div><h2 style="text-align: left;">デザイナーさんとの分担は?</h2><div><a href="https://flaskapp.com" target="_blank">Flask</a> では、UIデザインの修正を @horiuni さんに分担にしていて、いままではStoryboardの修正をお願いしている。SwiftUIではどういう形がよいのか?</div><div><br /></div><div>Storyboardではできないデザイン設定 例えばAttributedStringとか、Button内のLabelの設定などがあるので、SwiftUIで一箇所にデザインに関することをすべて書けるのは良い。</div><div>個々の小さいViewごとにPreviewできるのも良い。</div><div>だが、Viewとデータのコードが混在するのは避けられない。</div><div><br /></div><div>UIKitでは、画面の枠をざっくり作ってからその中のViewを整えていたけど、SwiftUIでは、反対がよさそう。つまり、小さな部品Viewをつくってから画面を作る流れ。</div><div>データクラスの枠と、そのプレビュー用データがあれば、小さな部品Viewが作れるし。</div><div><br /></div><div>Viewとデータクラスを一つのファイルにまとめて閉じた形にすれば、他アプリへコピーしやすくなるかもしれないなぁ。</div><div><br /></div><div>アプリ完成時に、SwiftUIへの感想がどう変わっているかが楽しみ。</div><div><br /></div><div><div><div><br /></div></div></div></div>Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-59765179082710751832020-06-05T11:30:00.000+09:002020-06-05T11:30:24.894+09:00iPhoneアプリのiPad対応5 - Page Sheetの位置iPad対応 第5回、Page Sheetの位置 について。<br />
<br />
<h2>
Page Sheetの位置</h2>
iPadのように大きな画面の場合、Page Sheetには下にマージンが付く。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwbJIORWL46Y94ny_LIjn5Xz8IhSrN1TOdb596PWOUaTaHQt2_qIhMOkFBdgZFhkjhkZEvKKizecrcTOh8gL8ii3_C7zxVqbSoDsfBMzMD58N_aRbh5RdwXxlQanp5neLZC2lMJa9WvpI/s1600/Screen+Shot+2020-06-05+at+10.19.55.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="834" data-original-width="1076" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwbJIORWL46Y94ny_LIjn5Xz8IhSrN1TOdb596PWOUaTaHQt2_qIhMOkFBdgZFhkjhkZEvKKizecrcTOh8gL8ii3_C7zxVqbSoDsfBMzMD58N_aRbh5RdwXxlQanp5neLZC2lMJa9WvpI/s400/Screen+Shot+2020-06-05+at+10.19.55.png" width="400" /></a></div>
<br />
上図の赤枠が、Page SheetのModal画面。<br />
iPhoneや、iPadのSplit Viewで別アプリを同時表示などの場合、下のマージンはなく、上のマージンのみある。<br />
そのため、iPhone Onlyアプリでは下マージンの考慮ができていなかった。<br />
<br />
それが、Keyboard表示時に、Keyboardのサイズに合わせて画面を変える場合。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg14sIEoBRUwWKe-XZk0NQd8lFi8GdlJaPDouS-X0i7VHZDOQ0-L0qbbdLB51qAO9qsAr_oe4rKojxh_9KkWjHWQVxotJmTrDAPJJ2oup7t5twNKJqsd3qipohzQVlD15T0HXD48TzMBcg/s1600/Screen+Shot+2020-06-05+at+10.28.16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="780" data-original-width="1036" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg14sIEoBRUwWKe-XZk0NQd8lFi8GdlJaPDouS-X0i7VHZDOQ0-L0qbbdLB51qAO9qsAr_oe4rKojxh_9KkWjHWQVxotJmTrDAPJJ2oup7t5twNKJqsd3qipohzQVlD15T0HXD48TzMBcg/s320/Screen+Shot+2020-06-05+at+10.28.16.png" width="320" /></a></div>
<br />
上図は、Keyboardの高さ分、ボタン類を上に移動させたいパターン。<br />
Keyboardの高さから、画面下マージンの高さを引いた分だけ移動したい。<br />
他にも、Keyboardの高さに合わせて、画面を上にスクロールさせる等 も同じ考慮が必要と思う。<br />
<br />
だが、Modalの view.frame.origin は 0, 0 になっていて、view.frameでは上下マージンのサイズがわからない。<br />
<br />
<h3>
マージンの取得方法</h3>
結論から言うと、<a href="https://developer.apple.com/documentation/uikit/uipresentationcontroller">UIPresentationController</a> から取得できる。<br />
この例だと、self.presentationController?.presentedView?.frame の値は、(156.0, 40.0, 712.0, 688.0) になっていた。<br />
<br />
UIPresentationControllerとは、画面の表示を管理するクラス。<br />
今回取り上げたような、画面サイズによって表示方法を変えたり、画面表示時のアニメーションを制御したりする。<br />
カスタムしたことがある人には、おなじみ。<br />
<br />
<h2>
iPad対応 おわり</h2>
これにて iPad対応おわり!<br />
<a href="https://apps.apple.com/jp/app/recipenote/id1456128363?mt=8">Recipe Note</a> ver 1.3.0 として、先程アップデート完了。<br />
<br />
iPad対応の他に、iOS 13 で追加された、検索のUISearchTokenや、LinkのリッチViewのLPLinkView も入れて楽しんでみたので、よければお試しください ー。<br />
<br />
<br />
<br />Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-73768985737655757502020-06-02T13:15:00.002+09:002020-06-02T13:31:52.162+09:00iPhoneアプリのiPad対応4 - TableCell制御iPad対応 第四弾。テーブルのセルの表示制御について。<br />
<br />
まず、目標を設定アプリで確認。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsRIlhaQ69AeYVtzr96Ukm28YnyI9xZyf4s7GOrqFWP-KTXCD4hPazdREXoQ4wNVPaVpU-LXs6TOLoXmm1vkrde_3ZLtaa6Tzq7W6oZ_wCXUA0sHaVD5oG0zk2cD_fmLIXwKDtqgcOLQ8/s1600/Screen+Shot+2020-06-02+at+0.01.07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="996" data-original-width="1478" height="428" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsRIlhaQ69AeYVtzr96Ukm28YnyI9xZyf4s7GOrqFWP-KTXCD4hPazdREXoQ4wNVPaVpU-LXs6TOLoXmm1vkrde_3ZLtaa6Tzq7W6oZ_wCXUA0sHaVD5oG0zk2cD_fmLIXwKDtqgcOLQ8/s640/Screen+Shot+2020-06-02+at+0.01.07.png" width="640" /></a></div>
<b>1. Accessory Type</b><br />
縦向き (Small Size) のときは DisclosureIndicator<br />
横向き (Regular Size) のときは None<br />
<br />
<b>2. 選択セル</b><br />
横向き (Regular Size) のときは、セルの選択状態を保持<br />
<br />
<b>3. Table Style</b><br />
縦向き (Small Size) のときは Detailテーブルは Grouped<br />
横向き (Regular Size) のときは Detailテーブルは Inset Grouped<br />
<br />
3については方法はわからなかった。Styleは作成時にのみ設定可能なので、途中で変えることはできなさそうだし...方法はあるのかな?<br />
ということで、1 と 2 を実装していく。<br />
<br />
<h2>
Accessory Type</h2>
Size Classが変わったときに、Accessory Type を切り替えるようにする。<br />
以下のようなクラスをMasterのTableCellに設定すると、実現できる。<br />
<br />
<script src="https://gist.github.com/aqubi/d03dbef5b8cc84abd992b703a342b397.js"></script>
Size Classは traitCollection.horizontalSizeClassで取得、変更タイミングは traitCollectionDidChange でトリガーできる。<br />
<br />
<h2>
選択セル</h2>
<div>
<h3>
選択の解除</h3>
まずは、Detail が非表示になったときMasterの選択を外す処理を考える。<br />
外す処理は、Masterの viewWillAppear に入れていくが、方法は UITableViewController のときと、UIViewController のときとで変える必要がありそう。<br />
<br />
UITableViewControllerのときは、clearsSelectionOnViewWillAppear を設定すればOKのようだ。<br />
UITableViewControllerのviewWillAppearの中には、選択を解除する処理が入っているみたいなので、その前に設定が必要。<br />
<script src="https://gist.github.com/aqubi/7bd5f986e584c8bfb164c1add786403a.js"></script>
UIViewControllerのときは、UITableView.deselectRow を組み込む。<br />
<script src="https://gist.github.com/aqubi/317a9a68793372106be9279cb98b2941.js"></script>
</div>
<div>
DetailViewを「何も選択していないView」を使わず、「常になにか選択されている」ようにする場合は、1カラムから2カラムに変更されたときにも選択する処理が必要。
</div>
<div>
<br />
<h3>
選択しないCell</h3>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoKoH4ef2228e6JubrFtgmjRDDvxT6UEx3qtZOa2zHZvDrHXq38ojzgLrGuBDL-PbuQBRTtKivt3lydMJJLa9cpZ17q67QL8aWO3suE-5vkEZkQIm0MfbVTlFpu2ubkcbfdy8EpVYYdbA/s1600/Screen+Shot+2020-06-02+at+1.50.28.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1072" data-original-width="1340" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoKoH4ef2228e6JubrFtgmjRDDvxT6UEx3qtZOa2zHZvDrHXq38ojzgLrGuBDL-PbuQBRTtKivt3lydMJJLa9cpZ17q67QL8aWO3suE-5vkEZkQIm0MfbVTlFpu2ubkcbfdy8EpVYYdbA/s400/Screen+Shot+2020-06-02+at+1.50.28.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Recipeアプリの設定画面では、上図の構成になっている。</div>
<div>
これら選択状態にしないCellについての実装方法について。</div>
<div>
<br /></div>
<div>
<h4>
タップ不可のCell</h4>
</div>
<div>
Switchがあるタップ不可のCellの実装は、Selection を Noneにするとともに、<a href="https://developer.apple.com/documentation/uikit/uitableviewdelegate/1614988-tableview">tableView(_:shouldHighlightRowAt:) </a>で false を返す。</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfW_3GhpfyWg7Im5cWVGZr59BfnldTT-oIrCGLh2RzSiSclqPdDUhWiRxLEWBp4tlH0tLDnlePsWLvGwQdzxzWijzSmEhLgnvM2lWbIwua4FV9TjJ-zUmGmROP_Yx9T4jVQlK750y5QOI/s1600/Screen+Shot+2020-06-02+at+1.55.33.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="386" data-original-width="526" height="233" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfW_3GhpfyWg7Im5cWVGZr59BfnldTT-oIrCGLh2RzSiSclqPdDUhWiRxLEWBp4tlH0tLDnlePsWLvGwQdzxzWijzSmEhLgnvM2lWbIwua4FV9TjJ-zUmGmROP_Yx9T4jVQlK750y5QOI/s320/Screen+Shot+2020-06-02+at+1.55.33.png" width="320" /></a></div>
<div>
見た目では、SelectionをNoneにするだけでタップ不可に見えるけど、内部では選択する処理が入っているから、shouldHighlightRowAt の処理も必要。<br />
<br /></div>
<div>
<h4>
タップ可で選択不可のCell</h4>
</div>
<div>
ヘルプなどのCellは、TapできるけどSafariで表示するだけなので選択状態にはしないCell。</div>
<div>
この場合は、<a href="https://developer.apple.com/documentation/uikit/uitableviewdelegate/1614988-tableview">tableView(_:shouldHighlightRowAt:)</a> は true で返し、<a href="https://www.blogger.com/tableView(_:willSelectRowAt:)">tableView(_:willSelectRowAt:)</a> の中で処理を入れ、戻り値のIndexPathをnil にする。</div>
<div>
<br />
<br />
今回のTableCellの制御は、見かけの調整なので、実装しなくても実害はないけど、ちゃんと整えると気持ちが良い。<br />
iPadだからという話題ではなかったけど、いままでiPhoneの縦のみのアプリが多かったのもあり、あまり気にしていなかったので、良いお勉強になった。<br />
<br />
<br />
次回につづく。<br />
<br /></div>
Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-39931616685012617262020-05-31T15:08:00.001+09:002020-05-31T15:15:43.844+09:00iPhoneアプリのiPad対応3 - Drag and DropiPad対応 第3回目は、Drag and Drop。<br />
SplitViewで、複数のアプリを同時に表示するメリットの一つが、他アプリのデータをDrag and Dropでコピーできること。<br />
<br />
UITextField, UITextAreaは、デフォルトでテキストのDnDに対応している様子。<br />
今回対応中のレシピアプリでは、画像が登録できる機能があるので、他アプリから画像をDropで追加できるようにしてみた。<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWJUy3MhvnqHWtJxTqQCr6qKsi7VhOP72QsZASOxDh2TlWi6Jdxn0-2ZcbZ69FUHwEgdle9C9Q-1io-dKOY4S-VWsRJCJQhJ0oerggkUCud1L56v9L8mOrKOmzM-lOpUaYnlPGN8DoFn0/s1600/dnd.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="1080" height="425" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWJUy3MhvnqHWtJxTqQCr6qKsi7VhOP72QsZASOxDh2TlWi6Jdxn0-2ZcbZ69FUHwEgdle9C9Q-1io-dKOY4S-VWsRJCJQhJ0oerggkUCud1L56v9L8mOrKOmzM-lOpUaYnlPGN8DoFn0/s640/dnd.gif" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Web上の画像をアプリに登録する場合は、かなり楽になる!<br />
Drag and Dropの仕組みは、iOS 11以上のUITableView, UICollectionView で実装が可能。<br />
<br />
<h3>
Dropの実装</h3>
使用するのは、<a href="https://developer.apple.com/documentation/uikit/uitableviewdropdelegate">UITableViewDropDelegate</a><br />
<br />
<script src="https://gist.github.com/aqubi/3611bf0c78c12a94881f62588680431d.js"></script>
canHandleのメソッドで、受け取り可能なClassかをチェックする。今回はUIImageのみ可能に。
<br />
<br />
Dropの処理は、以下のように実装した。<br />
<script src="https://gist.github.com/aqubi/e4f14f14db70268bd7e18e90410c3528.js"></script>
UITableViewDropPlaceholder で一時的なViewを作り、処理が完了したら削除する。<br />
<br />
<h3>
Dragの実装</h3>
Dragを実装すると、外部アプリへデータをドラッグできるようになる。使用するのは<a href="https://developer.apple.com/documentation/uikit/uitableviewdragdelegate">UITableViewDragDelegate</a>。<br />
itemsForBeginning で、受け渡したい情報を設定する。<br />
<script src="https://gist.github.com/aqubi/5fe1ac77c014a296ebd855c03b0d08b3.js"></script>
<br />
DragDelegateとともに、<a href="https://developer.apple.com/documentation/uikit/uitableviewdatasource/1614927-tableview">tableView(_:canMoveRowAt:)</a>、<a href="https://developer.apple.com/documentation/uikit/uitableviewdatasource/1614867-tableview">tableView(_:moveRowAt:to:)</a> などを実装すると、テーブル内のセルの順番をDnDで操作することも可能になる。<br />
以下は、同じSection内に限りDnDで行を入れ替えることができる実装例。<br />
<br />
<script src="https://gist.github.com/aqubi/13012c3eacc9804b2524decbf70f6f2b.js"></script>
<br />
外部アプリにデータを渡さないのであれば、itemsForBeginningの戻り値は設定なしでOK。<br />
<br />
ただし、tableView(_:moveRowAt:to:) の処理中で、tableView.reloadSections で更新すると、次回から行移動ができなくなるバグ?があるみたいなので注意。tableView.reloadData() だと大丈夫のようだ。<br />
<br />
iPadだと、登録がかなり楽になる! 素敵!<br />
次回につづく。Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-44542145564433400972020-05-30T21:06:00.001+09:002020-05-30T21:21:15.463+09:00iPhoneアプリのiPad対応2 - Readable Width<h2 style="clear: both; text-align: left;">
読みやすい表示幅 - Readable Width</h2>
iPhoneアプリのiPad対応。<a href="https://blog.sorausagi.org/2020/05/iphoneipad-splitview.html">前回のSplitView</a>に続いて、今回は表示幅について。
<br />
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF1e4VejVKajj0fACInG0oRPWV76txCT4mljlz1FSWDeF5N-5B7uHeyDyyskHWTl6W-Ua8cfXXAY6IooOqbMArPaXT6cCnEZFvDjv75aDaeeda85uGLcrCaCQCQ43Ig7pO7qZfsVAk4Cc/s1600/ChangeMargin.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF1e4VejVKajj0fACInG0oRPWV76txCT4mljlz1FSWDeF5N-5B7uHeyDyyskHWTl6W-Ua8cfXXAY6IooOqbMArPaXT6cCnEZFvDjv75aDaeeda85uGLcrCaCQCQ43Ig7pO7qZfsVAk4Cc/s320/ChangeMargin.gif" width="320" /></a></div>
<br />
画面の横幅が大きくなったとき、デフォルトのMarginサイズだと横に間延びして読みにくくなってしまう。<br />
読みやすい表示幅を制御する仕組みはすでにOSにあり、Readable Width を設定すれば反映できる。<br />
(iOS 12以上で利用可)<br />
<br />
<h3>
設定方法</h3>
Storyboard > Size Inspector の "Follow Readable Width" がその設定になる。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3muKAEHYAjX2eZp1ItAh_BnZSDp7yxLUefYgZqPUHID1vednfZyiPqOA8vp8qfrnj2X7MH2ClOTPqMIrVuuPv97U0UkTkKW7iNrlHRj3kihu2q0qb7FS1Y1SROQWYb_bBnJzwbkXPIOY/s1600/Screen+Shot+2020-05-30+at+19.38.42.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="212" data-original-width="512" height="132" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3muKAEHYAjX2eZp1ItAh_BnZSDp7yxLUefYgZqPUHID1vednfZyiPqOA8vp8qfrnj2X7MH2ClOTPqMIrVuuPv97U0UkTkKW7iNrlHRj3kihu2q0qb7FS1Y1SROQWYb_bBnJzwbkXPIOY/s320/Screen+Shot+2020-05-30+at+19.38.42.png" width="320" /></a></div>
<br />
ちなみに、Preserve Superview Marginsは、SuperviewのMarginも考慮するプロパティ。カスタムテーブルセルを作るとき、標準セルのMarginと合わせることができます。<br />
<br />
Readable Widthの幅は、OSで設定されているText Sizeによって変わるのに注意。<br />
Text Sizeが大きくなると、幅は大きくなる。<br />
<br />
<h3>
デフォルトのMarginを無しでReadable Widthのみ反映する</h3>
レシピの画像は、Compactサイズでは左右Margin無し、Readable Widthが反応するサイズではそのMarginに反応するよう設定した。<br />
この設定は以下の通り。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_fb0y0DS8leB9xGfm62sPambk0hopMxr_DuPhlVTkYmRapO99OVflCRj7-QNH74vUbgL1JsFI8fi6qGuOpDOEXAU66CzqLum87cnMYI5yJ7VXZ8MEf-K6ca5zpxj4zKK6NhlFEXWBSPk/s1600/Screen+Shot+2020-05-30+at+20.06.04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="366" data-original-width="518" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_fb0y0DS8leB9xGfm62sPambk0hopMxr_DuPhlVTkYmRapO99OVflCRj7-QNH74vUbgL1JsFI8fi6qGuOpDOEXAU66CzqLum87cnMYI5yJ7VXZ8MEf-K6ca5zpxj4zKK6NhlFEXWBSPk/s320/Screen+Shot+2020-05-30+at+20.06.04.png" width="320" /></a></div>
<br />
Layout Margins は 0 を設定し、Follow Readable Width にチェックをいれる。<br />
これで、以下のように、画面幅に応じてMarginが切り替わる。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlJq42Rq7MCnv03zm93efbzNAhnEnEDLLidUkazQpeCl8vI_gUtcdJ8mY3CfOkjaLisouCtpoX0cER-OJRcVysQZaPWypCM9hKVTTz1H7FYD-ebASeUnpu4pu5wBFwpx0sichjRyNbOWI/s1600/Screen+Shot+2020-05-30+at+21.17.24.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1060" data-original-width="1260" height="336" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlJq42Rq7MCnv03zm93efbzNAhnEnEDLLidUkazQpeCl8vI_gUtcdJ8mY3CfOkjaLisouCtpoX0cER-OJRcVysQZaPWypCM9hKVTTz1H7FYD-ebASeUnpu4pu5wBFwpx0sichjRyNbOWI/s400/Screen+Shot+2020-05-30+at+21.17.24.png" width="400" /></a></div>
<br />
<h3>
Readable Marginのサイズを取得する</h3>
<div>
UIViewの<a href="https://developer.apple.com/documentation/uikit/uiview/1622566-layoutmargins">layoutMargins</a>に、Readable Widthも含めたMarginが含まれている模様。</div>
<div>
ただ、アプリ操作途中でOSのText Sizeを変えることによりReadable Widthの幅が変わった場合、layoutMargins には変更後の値は含まれていないっぽい。(iPadOS 13.5 で確認)</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
iPhoneアプリをiPad対応する際、Readable Marginの対応することは多くありそう。</div>
<div>
Storyboardの設定だけで完結できるのはとても良い。</div>
<div>
<br /></div>
<div>
次回につづく。</div>
Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-29133069652417201862020-05-30T17:08:00.000+09:002020-05-30T17:30:41.032+09:00iPhoneアプリのiPad対応1 - SplitView<a href="https://www.apple.com/jp/ipados/">iPadOS</a>、<a href="https://developer.apple.com/jp/mac-catalyst/">Mac Catalyst</a> のお勉強として、既存のiPhoneアプリ <a href="https://apps.apple.com/jp/app/recipenote/id1456128363?mt=8">Recipe Note</a> のiPad対応を試し中。WWDC 2020 でなにか進展がありそう予測も兼ねた復習として。<br />
学んだこと、迷ったことを書いてみる。<br />
<br />
OSになるべく逆らわず、以下の基本方針で。<br />
<br />
<ul>
<li>iPhone/iPad で同じUI(Storyboard)を使う</li>
<li>UIDevice.currentDevice().userInterfaceIdiom でOSの条件分岐しない</li>
<li>Size Classでの条件分岐しない</li>
</ul>
<br />
<h2>
UISplitViewController</h2>
<div>
iPadOSでSplit Viewの操作をすると、大きいサイズ(Regular) ⇔ 小さいサイズ(Small) が頻繁に切り替わることになる。</div>
<div>
その操作をしても、いい感じの表示にするには、やはり<a href="https://developer.apple.com/documentation/uikit/uisplitviewcontroller">UISplitViewController</a> を使いたい。<br />
<br /></div>
<div>
<iframe allowfullscreen="" frameborder="0" height="344" src="https://www.youtube.com/embed/miOPwbCY1RU" width="459"></iframe></div>
<div>
<br /></div>
<div>
<br />
<h3>
UISplitViewController を使うポイント</h3>
<h4>
状態の設定と取得</h4>
<div>
SplitViewの種類は、<a href="https://developer.apple.com/documentation/uikit/uisplitviewcontroller/1623170-preferreddisplaymode">preferredDisplayMode</a> で設定できる。</div>
<div>
Master/Detailを両方表示(例: 設定アプリ)や、MasterをOverlay表示など。</div>
<div>
<a href="https://developer.apple.com/documentation/uikit/uisplitviewcontroller/1623185-iscollapsed">isCollapsed</a> で折りたたまれているかどうか?を取得できる。</div>
<div>
<br /></div>
<div>
<a href="https://developer.apple.com/documentation/uikit/uisplitviewcontroller/1623196-displaymodebuttonitem">displayModeButtonItem</a> を、navigationItem.leftBarButtonItem に設定することにより、Back / 全画面表示 の処理をするボタンが表示できる。上記動画の右ペインの左上にあるボタンがそれ。状態によって表示も自動的に切り替わってくれる。</div>
<div>
<br /></div>
<h4>
サイズに関する挙動差</h4>
Master(左ペイン) → Detail(右ペイン)と画面遷移していく、それらの画面がどこにStackされるのかは、Splitの表示状態によって異なる。<br />
サイズがSmall、つまり1ペイン表示のときは、MasterのUINavigationViewControllerにStackされ、サイズがRegularのときは、UISplitViewControllerにStackされる。<br />
<br />
<h4>
iPhoneのときは初期表示をMasterのみにする</h4>
</div>
<div>
UISplitViewControllerのDetailにViewがあると、デフォルトでは初期表示はDetailになる。<br />
iPhoneのときは初期表示をMasterのみにしたい場合は、<a href="https://developer.apple.com/documentation/uikit/uisplitviewcontrollerdelegate">UISplitViewControllerDelegate</a> の <a href="https://developer.apple.com/documentation/uikit/uisplitviewcontrollerdelegate/1623184-splitviewcontroller">splitViewController(_:collapseSecondary:onto:)</a> で制御する。<br />
<br />
<script src="https://gist.github.com/aqubi/be36f83d7d6cdc1d9f10275222914080.js"></script>
Masterのみにしたい場合、false を返せばOK。<br />
このメソッドは、iPhoneの初期表示だけでなく、サイズがRegular → Smallに変わった場合にも対応する。<br />
<br />
ちなみにMasterのViewControllerにSplitViewのDelegateを設定したい場合、delegateの設定をviewLoadでしても間に合わないので、awakeFromNibで行う。(が、SplitView継承してカスタマイズする方がよいかもしれない)<br />
<br />
<h4>
Small → Regularに変わったときのDetailの指定</h4>
</div>
<div>
<a href="https://developer.apple.com/documentation/uikit/uisplitviewcontrollerdelegate">UISplitViewControllerDelegate</a> の <a href="https://developer.apple.com/documentation/uikit/uisplitviewcontrollerdelegate/1623189-splitviewcontroller">splitViewController(_:separateSecondaryFrom:)</a> で制御する。</div>
<div>
<script src="https://gist.github.com/aqubi/8cf1a5639ac585a4e1ca45ca0a41aa41.js"></script>
</div>
<div>
<br /></div>
<div>
上記のコードでは、MasterのUINavigationViewControllerがTopのときは「なにも設定されていないView」をDetailに設定、それ以外はデフォルト = 表示されていたViewがDetailに表示 するようにしてみている。<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="344" src="https://www.youtube.com/embed/Xm0Egp887eM" width="459"></iframe>
<br />
当初は、「なにも設定されていないView」を使わない方法でアレコレ試していたが、いろんなパターンに対応するのは大変なので、使用する形の方が素直に実装できると思った。<br />
<br />
<h4>
Tabをデフォルトの挙動に合わせる</h4>
今回、Tabの中にSplitViewを入れる形で実装を進めているのだが、そうすると動かくなった機能がある。<br />
<ol>
<li>Hide Button Bar on Push (タブを非表示にする設定)</li>
<li>TabItemタップ時、NavigationのTopに戻る</li>
</ol>
1については、setNavigationBarHiddenを使って自前で制御するしかない予感。iPhoneのときのみタブを非表示にしようかとも思ったが、無理に制御しないほうが無難かもと思い中。<br />
<br />
2については、UITabBarControllerDelegate で以下のコードをいれてみた。<br />
<br />
<script src="https://gist.github.com/aqubi/ac66ac5d51cf7560d6eca97ab0e354be.js"></script>
折りたたまれているときは、NavigationをRootに遷移。折りたたまれていない + Masterが非表示の場合には、Masterを表示する。(preferredDisplayModeにはallVisibleを設定している)<br />
<br />
ちなみに、<a href="https://developer.apple.com/documentation/uikit/uisplitviewcontroller">SplitViewのドキュメント</a>に<br />
<blockquote class="tr_bq">
Split view controllers are normally installed at the root of your app’s window.</blockquote>
とあるので、Window Root以外にSplit Viewを使うのは推奨されていないかもしれない。<br />
<br />
<br />
今回はここまで。<br />
次回はSplitView以外のことを書いていこうと思う。</div>
Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-48035651173626916802019-11-20T23:41:00.005+09:002019-11-20T23:53:56.538+09:00個人事業主の税金対策個人事業主になってもうすぐ6年。<br />
いまさらながらだけど、税金についてお勉強してみた。<br />
<br />
<h2>
控除を増やしたい</h2>
<ol>
<li>基礎控除 (所得税: 38万円、住民税: 33万円)</li>
<li>青色申告控除 65万円</li>
</ol>
上記に加え、社会保険や生命保険、扶養控除などがある。<br />
昨年の私の控除合計額は 89万程度しかない。<br />
<br />
どれだけ控除が増やせるか??<br />
<br />
<br />
<h3>
付加年金</h3>
<a href="https://www.nenkin.go.jp/service/jukyu/sonota-kyufu/1go-dokuji/20140625.html" target="_blank">付加年金</a>は、国民年金に追加できる任意加入の制度。<br />
<br />
<ul>
<li>月々の掛金は 400円</li>
<li>掛金は「社会保険料控除」</li>
<li>老齢基礎年金が 200円 × 付加保険料納付月数 プラス</li>
<li>国民年金基金と同時加入はできない</li>
</ul>
<br />
定額のため、物価スライド無いけど、終身年金。<br />
2年で元がとれる。長生きするほどお得。<br />
<br />
さっそく区役所にいって、手続きしてきた。<br />
<br />
<br />
<h3>
小規模企業共済</h3>
<a href="https://www.smrj.go.jp/kyosai/skyosai/about/index.html" target="_blank">小規模企業共済</a>は、小規模経営者が事業をやめたときに解約できる退職金代わりの共済。<br />
<ul>
<li>月々の掛金は1,000~70,000円まで(500円単位)</li>
<li>加入後も増額・減額可能</li>
<li>掛金は「小規模企業共済等掛金控除」</li>
<li>一括受取りの場合は退職所得扱い、分割受取りの場合は、公的年金等の雑所得扱い</li>
<li>貸付制度あり</li>
</ul>
受取りのときまで、税負担を引き伸ばしできる。<br />
MAXの掛金で、84万円 / 年。<br />
受取りも、退職所得 になるのでオトク。<br />
<br />
<a href="https://www.smrj.go.jp/kyosai/skyosai/about/proceed/index.html" target="_blank">給付金額は、解約理由により異なる</a>。<br />
納付期間が6ヶ月未満は給付なし。3年以上、加入しておきたい。<br />
3年の内に急激なインフレが起こったらツライけど、日本だったら大丈夫かな。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwxuF8iRwlNINVtKvu-X9txh_-01tnpB-FGYKHxVbyVi5BgnuZaYgh2DcaK-wH5vrTsHpoVwBpGZnT6GAo2a_EyZ2ZMozXjLUVphuuTiIXivajMHVCe2eKUFCWy4iBhi4QUUiww1BJjnI/s1600/Screen+Shot+2019-11-20+at+21.10.21.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="384" data-original-width="1398" height="175" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwxuF8iRwlNINVtKvu-X9txh_-01tnpB-FGYKHxVbyVi5BgnuZaYgh2DcaK-wH5vrTsHpoVwBpGZnT6GAo2a_EyZ2ZMozXjLUVphuuTiIXivajMHVCe2eKUFCWy4iBhi4QUUiww1BJjnI/s640/Screen+Shot+2019-11-20+at+21.10.21.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: x-small;">サルワカ: <a href="https://saruwakakun.com/learn/money/kyosai-okane" target="_blank">小規模企業共済の仕組み〜お金の種類と受け取り方〜</a> から引用</span></div>
<br />
<br />
<a href="https://www.smrj.go.jp/kyosai/skyosai/customer/procedure/installment/02.html" target="_blank">前納払い</a>が可能。<br />
現金であれば12月に前納(一括)で支払いで、今年の控除に間に合うらしい。<br />
<br />
フリーランス状態も落ち着いて、もう会社員に戻る気がない私としては、よい制度かも。<br />
とりあえず、<a href="https://www.smrj.go.jp/kyosai/skyosai/customer/forms/index.html" target="_blank">資料請求</a>をポチっと。<br />
<br />
<br />
<br />
<h3>
個人型確定拠出年金(<a href="https://www.ideco-koushiki.jp/guide/" target="_blank">iDeco</a>)</h3>
毎月積み立てして金融商品を運用し、60歳以降に年金または一時金で受け取りするもの。<br />
(60歳になるまで引き出すことはできない。)<br />
<ul>
<li>月々の掛金は5,000円~68,000円まで(上限は国民年金基金や付加保険料の合計)</li>
<li>掛金の変更は、年に1回だけ可能</li>
<li>掛金は「小規模企業共済等掛金控除」</li>
<li>運用で得た定期預金利息や投資信託運用益は非課税</li>
<li>一括受取りの場合は退職所得扱い、分割受取りの場合は、公的年金等の雑所得扱い</li>
<li>貸付制度なし</li>
<li>受給開始は10年以上加入で満60歳から</li>
</ul>
付加保険400円と併用する場合は、67,000円/月、 804,000円/年 がMAXになる。<br />
小規模企業共済と併用すると、 164万4千円 / 年 が共済掛金控除にできる。<br />
<br />
途中解約できないし貸付もないので、収入が安定していないタイミングでは厳しいカモ。<br />
<div>
<br /></div>
<h4>
口座開設・維持費が必要</h4>
最低でもiDeCoに加入する時に2,829円を、運用期間中は月額171円が必要。その他、運用会社によっては手数料がプラス。<br />
信託報酬は、0.1~2%くらい。<br />
<br />
<h4>
投資信託の知識が必要</h4>
金融商品は、投資信託と定期預金があり、運用会社によって利用可能な商品が変わる。<br />
通常の投資信託の商品よりも、信託報酬が少ない長期向きのものが用意されている感じだけども、自分のリスク許容量を考えて商品の割合を考える必要がある。<br />
元本割れしない定期預金もあるけど、手数料が必要なので、リスク取りたくない人は小規模企業共済の方が良い。<br />
<br />
<h4>
私の選択</h4>
<div>
<a href="https://site0.sbisec.co.jp/marble/insurance/dc401k/search/dc401ksearch.do" target="_blank">SBI証券のセレクトプラン</a> を資料請求してみた。</div>
<div>
あんまり詳しく無いので、信託報酬が少ないインデックスのもので放置にしたい。</div>
<div>
<a href="https://site0.sbisec.co.jp/marble/insurance/dc401k/detail/achievement.do?s_rflg=1&Param6=03319172&_scpr003=insurance:401ksearch:search_result" target="_blank">eMAXIS Slim 先進国株式インデックス</a> <span style="font-size: x-small;">信託報酬: 0.10989%以内</span></div>
<div>
<a href="https://site0.sbisec.co.jp/marble/insurance/dc401k/detail/achievement.do?s_rflg=1&Param6=03312175&_scpr003=insurance:401ksearch:search_result" target="_blank">eMAXIS Slim バランス(8資産均等型)</a> <span style="font-size: x-small;">信託報酬: 0.154%以内</span></div>
<div>
<a href="https://site0.sbisec.co.jp/marble/insurance/dc401k/detail/achievement.do?s_rflg=1&Param6=8931217C&_scpr003=insurance:401ksearch:search_result" target="_blank">SBI-SBI・全世界株式インデックス・ファンド</a> <span style="font-size: x-small;">信託報酬: 0.1102%程度</span></div>
<br />
とかどうかな。<br />
申し込みには時間がかかるみたいなので、来年からかな。<br />
<br />
<br />
<h3>
所得 2,400万の壁</h3>
<br />
令和2年度分(2020年1月1日~12月31年)から基礎控除額が10万円プラスされる<br />
<ul>
<li>所得税 基礎控除 38万円 → 48万円</li>
<li>住民税 基礎控除 33万円 → 43万円</li>
</ul>
ただし、合計所得が2,400万円を超えると、段階的に控除額が少なくなり、2,500万円以上になると控除額は0円になる。<br />
<br />
なので、<b>2,400万円の壁</b> がある。<br />
いまんとこ、超える可能性は全然ないけど、意識するぐらいになりたい。<br />
<br />
<br />
<h2>
メモ</h2>
<h3 id="taisyoku">
退職金控除</h3>
課税対象となる退職金は、<br />
(収入金額 − 退職所得控除額)× 1/2<br />
<br />
<br />
<table><tbody>
<tr><th>勤続年数(=A)</th><th>退職所得控除額</th></tr>
<tr><td>20年以下</td><td>40万円 × A</td></tr>
<tr><td></td><td>(80万円に満たない場合には、80万円)</td></tr>
<tr><td>20年超</td><td>800万円+70万円 × (A-20年)</td></tr>
</tbody></table>
<br />
<br />
<h4>
注意: 勤続年数が20年前後の場合</h4>
20年で計算方法が変わる・ 端数の月は繰り上げ される。<br />
240ヶ月 (= 20年) の場合は、40 × 20 = 800万円<br />
241ヶ月 (= 21年) の場合は、800 + 70 × (21 - 20) = 870万円<br />
1ヶ月違うだけで70万変わる<br />
<br />
<h4>
注意: 複数の退職金がある場合</h4>
同じ年に退職所得が2つ以上ある場合は、退職所得控除の勤続年数は、どちらか長い方の年数が適用される。<br />
共済とIDecoを同じ年に一括受取すると、損 or 得 両方のパターンがある。<br />
<br />
<a href="https://diamond.jp/articles/-/99709" target="_blank">退職金と個人型確定拠出年金を「同じ年に受け取る」のは要注意!</a><br />
<a href="https://freelance.station-t.com/tax_taishoku.html" target="_blank">退職所得と退職所得控除額</a><br />
<br />
<br />
<br />
<h3>
社会保険料控除と小規模企業共済等掛金控除の差</h3>
<br />
社会保険料控除は同一生計の親族分も申告者の控除対象に出来る一方で、小規模企業共済控除は掛金納付者本人の所得控除項目としてしか申告できない。<br />
なので、専業主婦の人の場合は社会保険料控除でないと意味がない。<br />
<br />Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-52668387521596411442019-11-04T15:06:00.004+09:002019-11-04T15:15:16.823+09:00RecipeNote アプリをリリースしましたレシピ記録アプリ <a href="https://apps.apple.com/app/id1456128363" target="_blank">RecipeNote をリリース</a>しました。<br />
iOS13以上、無料アプリです。(アプリ内課金で広告が消せます)<br />
ぜひ使ってみてくださいませ!<br />
あ、Flaskじゃなくて、個人で出したアプリになります。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_OqqAeKRfIhtChcVyRt6H360duquZOEOeo9AAHeHmU6akBwj2BAfhuBJd7ggvwkWFn8WP4knOhOTJY6Yl3MpAHvsagG4F8ZHxknk0ZFCpMYLcJCk3zaS69ChiqGY8AuFpoG9BE_StBFU/s1600/recipe.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="674" data-original-width="1000" height="267" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_OqqAeKRfIhtChcVyRt6H360duquZOEOeo9AAHeHmU6akBwj2BAfhuBJd7ggvwkWFn8WP4knOhOTJY6Yl3MpAHvsagG4F8ZHxknk0ZFCpMYLcJCk3zaS69ChiqGY8AuFpoG9BE_StBFU/s400/recipe.png" width="400" /></a></div>
<br />
<br />
<h3>
アプリでできること</h3>
<br />
<ul>
<li>レシピの登録</li>
<li>買い物リストの表示</li>
<li>食材のマーク付け</li>
<li>栄養成分の表示</li>
</ul>
<br />
このアプリを作った一番の理由は「買い物リスト」。<br />
必然的に、一番大切にしている機能も買い物リストになっています。<br />
<br />
<br />
<h3>
買い物リストで欲しかった機能</h3>
もう既にレシピサイトはいっぱいあるのでレシピ登録アプリは必要ないかなって思っていました。サイトをまたがってお気に入りのレシピのURLをまとめる機能や、分量をカスタマイズ...forkしたいとかはありますけど。<br />
<br />
だが! 材料を買おうとするときが面倒で。<br />
必要な材料のメモを取ること自体も、もちろん面倒なのですが...、<br />
順番がバラバラなメモだと、スーパーで行ったり来たりすることになったりする。<br />
目的の材料が売り切れだったり、他のものが安かったりすると作るものを変えたくなる。<br />
...あるあるですよね?<br />
<br />
で、実装した機能が以下。<br />
<br />
<ul>
<li>買い物リストの順番が、スーパーで並んでいる食材順に並んでほしい</li>
<li>食材の数は、複数のレシピの合計数を表示してほしい</li>
<li>買い物中に、作るレシピを変更して必要な食材を抽出しなおしたい</li>
</ul>
<br />
<br />
<br />
<h3>
食材のマーク付け</h3>
いざ料理を始めようとしたら、醤油とか、みりんとか、もう残りなかった!<br />
...ってことも、あるあるですよね?<br />
<br />
その対策として、食材ごとに ! や ♡ 、① などのマークを付ける機能を入れました。<br />
缶詰などのストック食材や、調味料の残量の目安にするために使えます。<br />
<br />
今回使用しないものでも、安売りしていたら買おう という、ゆるい買い物メモと考えてもらえればです。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKFfsNeuaNB3WYKFAO01nXK5uEz9UJyAPUUg4b4LumBXCoC-V4lMu3R7pcGEUA7Ok-1eMv0UrqrvoMO2cp49jSwoXvAnTvK_Pf2yJUdRuJ_gea-4gQ9EtHC3-HCZ9J6xrjwmci_cY8dSI/s1600/Screen+Shot+2019-11-01+at+20.21.04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="596" data-original-width="782" height="243" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKFfsNeuaNB3WYKFAO01nXK5uEz9UJyAPUUg4b4LumBXCoC-V4lMu3R7pcGEUA7Ok-1eMv0UrqrvoMO2cp49jSwoXvAnTvK_Pf2yJUdRuJ_gea-4gQ9EtHC3-HCZ9J6xrjwmci_cY8dSI/s320/Screen+Shot+2019-11-01+at+20.21.04.png" width="320" /></a></div>
<br />
<br />
<br />
<h3>
材料の分量の入力</h3>
これが最後まで悩んだトコロ..!<br />
汎用性を考えるなら、文字でのフリー入力が一番なんだけど、買い物リストには合計した値を表示したいので可能な限り数字として扱いたい。<br />
数字の扱いにしたいけど、1/2, 1/3 という表示ができるようにしたい。<br />
<br />
あれこれ考えてたけど最終的には、ドラムから選択したものは計算対象に。無いものはフリー入力で計算対象外にするようにしました。<br />
わかりやすく、使いやすいUIが...思いつきませんでしたよっ (;_;)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo0VziZpFuor7QIyPIJ5Gx76i2VEpHWenp2CiYQQjhF1V2ngoXPDUjyYy0Z9067KZWdSGBEklhTIgbVm3rhabA6Fb-gT9X148RPnD8ETrVceU5ebq7BuHp69s3oiHxYqfs9h1AktQ8FOc/s1600/IMG_56D18B3BD3F0-1.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="719" data-original-width="828" height="277" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo0VziZpFuor7QIyPIJ5Gx76i2VEpHWenp2CiYQQjhF1V2ngoXPDUjyYy0Z9067KZWdSGBEklhTIgbVm3rhabA6Fb-gT9X148RPnD8ETrVceU5ebq7BuHp69s3oiHxYqfs9h1AktQ8FOc/s320/IMG_56D18B3BD3F0-1.jpeg" width="320" /></a></div>
<br />
あまりクールではないけども、食材名・分量ともに選択で選べるようになっているので、手書きで買い物メモを作るよりは、このアプリを使うほうが早いはず!<br />
<br />
<br />
<h3>
栄養成分の表示</h3>
このアプリでは、レシピごと、ブックマークしたレシピの合計 で栄養成分が表示できます。<br />
表示されると、それなりに意識するようになるので、ちょっとうれしい機能。<br />
ですが、実は、せっかくなら付けてみようか。という軽い気持ちでいれたもの。<br />
軽い気持ちでしたが、実現させるために少し複雑になってしまいました。<br />
<br />
仕組み的にはこんな感じ<br />
<br />
<ol>
<li>食材の設定で、可食部100gあたりの栄養成分を登録(日本食品標準成分表から参照可能)</li>
<li>単位がgでないときはgに変換するためのパラメータ(密度)も登録</li>
<li>レシピの表示時には「廃棄率」を考慮したグラム数に変換して栄養成分を表示</li>
</ol>
<br />
例えば、「かぼちゃ 1/4個」 の場合、<br />
食材に 1個 = 1,200g、廃棄率 = 10% と登録されているので、<br />
1,200 * 1/4 * 0.9 = 270g 分の栄養成分の表示になります。<br />
<br />
例えば、「醤油 大さじ1」 の場合、<br />
食材に 1ml = 1.15g、廃棄率 = 0% と登録されているので、<br />
1.15 * 15 = 17.25g 分の栄養成分の表示になります。<br />
※大さじ1: 15ml<br />
<br />
よく使われそうな食材(約180個)は、デフォルト登録しているのですが、より正確な値にしたい場合は、実際に自分が使用しているものに合わせて修正してもらえたらデス。<br />
<br />
<br />
<h3>
まとめ</h3>
ということで、<br />
買い物メモを書く代わりとして、ゆるく使ってもらうのもOK。<br />
栄養成分をがっつり計算するために使ってもらうのもOK。<br />
<a href="https://apps.apple.com/app/id1456128363" target="_blank">RecipeNote</a> をぜひ使ってみてね!<br />
<br />
<br />
P.S.<br />
リリースして2日ほど経ったのだけど、App Storeの検索でまだ出てこない。<br />
いつ反映されるのだろう....<br />
<br />Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-28473388660343336722019-09-15T13:18:00.003+09:002019-09-15T13:31:44.175+09:00iOS 13, Are you ready?<a href="https://flaskapp.com/ja/" target="_blank">Flask</a> のアプリ、7本をiOS 13 / watchOS 6 対応をして準備完了しました!<br />
Zones, FitPort, Standland, Cube, Timesheet, Timelet, Coyomi<br />
<br />
OS正式リリースの前日、9月18日にリリース予定です。お楽しみに!<br />
<br />
対応、いやー大変でした。<br />
なにが大変だったかというと、なんかもう、いろいろ?<br />
<br />
<br />
<h2>
Localize Bug</h2>
いくつかあったのですが、最後まで様子見していたのが、テーブルセルのローカライズがされない問題。<br />
以下の場合に発生します。<br />
<ul>
<li>Storyboardの.strings ファイルを使ってローカライズしている</li>
<li>TableViewCellのStyleにBasicやRight Detailなどを利用している</li>
</ul>
<div>
結局最後のGMまでFixはされなかった。</div>
<div>
遭遇する人は多いと思ったのだが、Feedback AssistantでReportした内容をみると、</div>
<div>
<br /></div>
<blockquote class="tr_bq">
Recent Similar Reports: Less than 10</blockquote>
<div>
...って、10以下って少なくね!?</div>
<div>
<br />
<br /></div>
<h2>
Page Sheet</h2>
<div>
XCode 11でビルドして最初に気づくのが、ModalのデフォルトがPage Sheetになっていること。</div>
<div>
iOS 12時代の形式に戻すには、Full Screen系に選択しなおしすればOK。</div>
<div>
だけど、せっかくならPage Sheet使ってみたいなー と気軽に入れ始めたら、あれこれ引っ掛った。</div>
<div>
<ul>
<li>Modalの画面からさらにModalを出していた場合の対処</li>
<li>編集画面の場合は、変更有無をチェックして Swipe to Dismiss できない処理を追加</li>
<li>元画面が見えている扱いなので、viewWillAppear 系の呼ばれ形が変わる。たとえば、viewWillAppearで変更内容を一括して再更新している画面(手抜き処理)が元画面の場合、小画面で変更した内容が反映されない など</li>
<li>元画面がSceneKitの場合は、Renderingでの処理を止めてからNodeを操作するなどの考慮が必要</li>
</ul>
</div>
<div>
Page Sheetをデフォにするのは思い切ったなー と思うが、おかげで、Swipe to Dismiss する操作がみんな慣れているものになるのも早いと思う。<br />
<br /></div>
<div>
「Closeボタンを上に置くと操作しにくいから、下に置くか?」という迷いももう解決っす。</div>
<div>
あ、でも、Closeボタンはちゃんとあったほうが良いです。Voice Over/Voice Control のために。</div>
<div>
<br /></div>
<div>
Page Sheetと同じ動きだけど、もっと高さが小さいバージョンのものが欲しくなったので作成したりした。こういうやつ。</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9Vuky4_GxcZmRHY2-dJ4acBMPB4XQ4tHvsUy36CsuVSI0hQ7gdC5NY00pDLnoBuVYPjj5abc5ILwzHMe1BWZ21UCc8VFPiB7gzUpgZM6yD9C0lff3XOgL059UnAQCa0vSQ-AfWD7Hs0Y/s1600/IMG_47D5443EBBEB-1.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="739" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9Vuky4_GxcZmRHY2-dJ4acBMPB4XQ4tHvsUy36CsuVSI0hQ7gdC5NY00pDLnoBuVYPjj5abc5ILwzHMe1BWZ21UCc8VFPiB7gzUpgZM6yD9C0lff3XOgL059UnAQCa0vSQ-AfWD7Hs0Y/s320/IMG_47D5443EBBEB-1.jpeg" width="147" /></a></div>
<br /></div>
<div>
標準でできるといいのになぁ。<br />
<br />
<br />
<h2>
Dark Mode</h2>
</div>
<div>
<a href="https://blog.sorausagi.org/2019/06/ios13-dark-mode.html" target="_blank">前回のブログで対応方法を書いた</a>。<br />
<br />
実際に移行するときの手順は、以下のような感じになると思う。<br />
<br />
<ol>
<li>Storyboard、コードで描いている色を整理</li>
<li><a href="https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/color/" target="_blank">System Colors, Dynamic System Colors</a> に置き換え可能なものを検討する</li>
<li>整理したものをAsset の Color Setに定義</li>
<li>利用画像もLight/Dark用を用意 or TintColorで切替にする</li>
<li>Storyboard、コードの色設定をColor Setのものに変更する</li>
<li>cgColor を使っている所は、traitCollectionDidChange や tintColorDidChange などで変更に対応する</li>
</ol>
<br />
できるだけSystem Colorsを使っていきたい所だけど、限られた中から選ぶの結構迷います。<br />
そしてアプリ独自の色もLight/Darkで色を調整したくなってくるという...。<br />
<br />
UILabelなどUIKitのコンポーネントに設定したDynamic Colorは、Light/Darkのモード切替時に自動的に反映してくれるけど、CGLayerなどで利用したCGColorは自前で更新する必要があります。<br />
<br />
StoryboardのGlobal Tint Colorに、独自に作成したCustom Color Setを指定した場合、その色が他要素に使われていないとXCode再起動などで色設定が消えてしまうバグ?があります。<br />
<br />
前からある現象だけど、StoryboardでCustom Color Setを設定している箇所にコードから色を設定しても反映されない(viewDidLoad以降にStoryboardの設定で上書きされてしまう?)ことがあります。<br />
<br />
<br />
<h2>
Voice Control, Voice Over</h2>
</div>
<div>
Voice Control がiOS 13で追加になります!<br />
<br />
Voice Overよりも、Controlの方が対応が簡単と思うし、使いたい人も多いと思うので、Accessibilityの第一段階として取り組むのはいいと思った。<br />
<br />
Voice Overの場合は、読ませる順番、読ませる内容、スクロールの移動、ローター使った見出し移動 など注意すべき箇所は多いのですが、Voice Control の場合は、操作できるところを明確にするだけでも助かるはず。("Show Numbers" で番号を表示して使う)<br />
さらに、名前も整理しておくと、 "Tap [名前]" のように直接操作できるようになる。(何回も操作が必要なStepperなどでは名前がないと操作がツライ。)<br />
<br />
<br />
Accessibility系をやりながら思ったこととしては、<br />
まとめて読ませる括りのものは1つのViewにいれて、専用のクラスを設定するようにしておくと、やりやすいです。<br />
accessibility***系メソッド をoverrideして書けるので。<br />
<br />
<script src="https://gist.github.com/aqubi/8ea764537e10da9560270cb093a2a7de.js"></script>
</div>
<br />
他にも色々学んだことは多いのだけど、書くとめっちゃ長くなりそうなのでまた機会があれば。
<br />
<br />Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-6340332800497173842019-06-29T06:57:00.000+09:002019-06-30T04:35:37.296+09:00iOS13: Dark Modeの対応方法アプリのiOS 13対応 で、必ず通るのが Dark Mode対応。<br />
なぜなら、Opt-out だから。<br />
<br />
まだ iOS 13 beta2 なので、今後変わるかもしれないけど、今の知見を書いてみる。<br />
<br />
<h3>
Dark Mode にしない設定</h3>
XCode 11でビルドしたアプリを、iOS 13でみるとDark Mode対応になる。<br />
XCode 10以下でビルドしたものは、Dark Modeにはならない。(Light Mode)<br />
<br />
アプリ全体でModeを固定にしたい場合は、plistのUIUserInterfaceStyleで指定可能。<br />
特定の画面でModeを固定にしたい場合は、<a href="https://developer.apple.com/documentation/uikit/uiviewcontroller/3238087-overrideuserinterfacestyle" target="_blank">overrideUserInterfaceStyle</a> で指定可能。<br />
<br />
<br />
<h3>
Modeごとの色</h3>
<h4>
System Color</h4>
Light / Dark でよきに変わるシステムカラーが利用できる。<br />
<a href="https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/color/#system-colors" target="_blank">Human Interface Guidelines: System Color</a><br />
<br />
ラベル文字色、背景色などごとに、Primary, Secondary, Tertiary の色が用意されているので重要度に合わせて使う。<br />
<a href="https://developer.apple.com/documentation/uikit/uicolor/ui_element_colors" target="_blank">UI Element Colors</a><br />
<br />
Dark ModeのときのsystemBackgroundは基本的にはUIColor.black だが、Page SheetなどのModalのときは、少し薄い黒になることに注意。<br />
<br />
System ColorはiOS 13以上で利用可能なため、コード上で設定するにはiOS 13 以上である必要がある。<br />
<blockquote class="tr_bq">
if #available(iOS 13.0, *) {<br />
titleLabel.textColor = UIColor.label<br />
}</blockquote>
ただ、StoryboardにてSystem Colorを設定した場合は、iOS 12でも利用可能。<br />
<br />
<a href="https://noahgilmore.com/blog/dark-mode-uicolor-compatibility/" target="_blank">Backwards compatibility for iOS 13 system colors</a> は下位互換のための情報の良記事。<br />
<br />
<h4>
Custom Color</h4>
独自の色は、Asset CatalogでColors Set を指定して利用する。<br />
コードから利用したいときには、UIColor(named: "colorName") で。<br />
<br />
<br />
<h3>
Mode切替のタイミングの判定</h3>
<div>
Light / Dark は、システムによって動的に変わる場合がある。</div>
<div>
(Settings > Display & Brightness に Automatic の切替アリ)</div>
<div>
<br /></div>
<div>
UIViewやUILabelなどは自動的に切り替わるので特に考慮は必要ないが、cocoa 2D などでコードで色を指定しつつ描画しているところなどは、切替のタイミングを判定して描画し直す必要がある。</div>
<div>
<br /></div>
<div>
切替のタイミングは、<a href="https://developer.apple.com/documentation/uikit/uitraitenvironment/1623516-traitcollectiondidchange" target="_blank">traitCollectionDidChange</a>。</div>
<div>
<br /></div>
<div>
<blockquote class="tr_bq">
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {<br />
super.traitCollectionDidChange(previousTraitCollection)<br />
let userInterfaceStyle = traitCollection.userInterfaceStyle<br />
}</blockquote>
</div>
<br />
<a href="https://developer.apple.com/documentation/uikit/uiuserinterfacestyle" target="_blank">UIUserInterfaceStyle</a> のEnumに、unspecified, light, dark が定義されている。<br />
<br />
traitCollectionDidChangeはデバイスの回転などでも呼び出されることに注意。<br />
Mode切替の場合のみ処理したい場合には、hasDifferentColorAppearance を使って判定できる。<br />
<br />
<blockquote class="tr_bq">
let hasChanged = previousTraitCollection.hasDifferentColorAppearance(comparedTo: traitCollection)</blockquote>
<br />
Color Setの色から、現在のModeの色を取得するには、<a href="https://developer.apple.com/documentation/uikit/uicolor/3238042-resolvedcolor" target="_blank">resolvedColor(with:)</a> を使う。<br />
<blockquote class="tr_bq">
let color = UIColor(named: "MyColor")?.resolvedColor(with: traitCollection)</blockquote>
<br />
<br />Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-70459615533895718392019-05-10T02:44:00.001+09:002019-05-10T03:11:56.704+09:00iOSの令和元年が始まるiOS12.3で「令和」が対応されるみたい。<br />
(現時点で、iOS12.3はbeta 5)<br />
<br />
これ関連で、バグを仕込んでしまっていたようで、今日は修正をしていた。<br />
<br />
たとえば、<br />
平成の日付: 2019-04-09 17:04:38 +0000 から、その日の0:00を求めようとしたとき。<br />
<br />
let date1:Date = Date().addingTimeInterval(-3600 * 24 * 30) //平成の適当な日時<br />
print("date1:", date1)<br />
<br />
let cal = Calendar.current<br />
let comp = cal.dateComponents([.year, .month, .day], from: date1)<br />
let date2 = cal.date(from: comp)<br />
print("date2:", date2 ?? "nil")<br />
<br />
の結果は、<br />
<br />
date1: 2019-04-09 17:04:38 +0000<br />
date2: <b><span style="color: red;">2049</span></b>-04-09 15:00:00 +0000<br />
<br />
...と、30年先の日時になってしまう。<br />
もちろん、iPhoneのカレンダーが西暦の場合は大丈夫。和暦設定にしている時のみ。<br />
<br />
<br />
DateComponentを使った日時の計算には、Calendar(identifier: .gregorian) を使いましょう...<br />
<br />
<br />
P.S.<br />
0:00 の日時の算出には、<a href="https://developer.apple.com/documentation/foundation/calendar/2293783-startofday" target="_blank">CalendarのstartOfDay</a> が使えます。Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-51519151549596152002019-02-25T20:07:00.000+09:002019-02-25T20:07:14.226+09:00XCodeでアプリアップロード中に“negotiating connection…”になるXCode10 でアプリをアップロード中に、“negotiating connection…” で止まってしまう。<br />
<br />
Stack Overflowでも同じ現象になっている人がいる。<br />
<a href="https://stackoverflow.com/questions/54405893/xcode-10-app-upload-stuck-on-negotiating-connection" target="_blank">Xcode 10 app upload stuck on “negotiating connection…”</a><br />
<br />
Application Loaderを使えばうまくいく。<br />
<a href="https://stackoverflow.com/a/52770973/3832837" target="_blank">Application Loader/Xcode Stuck on 'Verifying Assets with the App Store"</a><br />
<br />
でも、Loaderを使うのは面倒だし、XCodeでやりたい。<br />
原因も気になる...<br />
<br />
Loaderを使う回避策にあるように、どうやら原因はネットワークにあるみたい。<br />
自宅のネットワーク使うとダメだけど、iPhoneのテザリングでやってみると成功した。<br />
<br />
自宅のネットワークの設定をナニカいじるといいのかなぁ。<br />
詳しい人教えてほしい...<br />
<br />Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-78690395452601034722019-02-11T19:36:00.000+09:002019-02-11T19:37:14.869+09:00iOS11のColorSetiOS11からAsset CatalogにColor Setを指定できるようになりました。<br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" data-original-height="718" data-original-width="1600" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiluU9TagdO1eUI3ECI7MMYm9vMT2JDQYZJcILivohDRRen-fF3lRX9vRS-vwC5zlWp7CGLhUCwyNWNSy8hJyVC8FsDUYbGZZ5LOE2DFXxWGRXh_GjjxxXCoN5UPUHZs2KzkeFpidxp4OQ/s640/Screen+Shot+2019-02-11+at+19.18.10.png" width="640" /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
この設定をすると、Storyboardとコードの両方で利用できるのでとても便利。<br />
<br />
Storyboard上では以下のように選択肢が現れます。<br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" data-original-height="640" data-original-width="542" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnxbxnUUyy0VtiftFSR30CnAQicJq8zSF3iImCUSi0wXKRe0hlN95OKMilVOnQRUJ2DHuMgdklj15gleLxyegyVVCq5wpVNZkElutXd8Hl-FkF_AjgFBoQr2n71gMKTF-T5T60nvSHbOw/s320/Screen+Shot+2019-02-11+at+19.19.50.png" width="271" /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
コード上では UIColor(named:"ColorName") で使えます。<br />
<br />
だが! 問題点が。<br />
<br />
StoryboardでColor Setの色をしていると、viewDidLoad() よりも後にその設定が反映されるみたい。(iOS12で確認)<br />
つまり、viewDidLoad() でコードから色の再設定していてもそれが反映されない。<br />
traitCollectionDidChange で設定してもダメなので、結構遅いタイミングの様子。<br />
<br />
なので、コードで色を再設定する箇所には、StoryboardでColor Setは使わない としたほうが良さげ。<br />
iOSのバグなのかな?と思うので、今後修正されるかもしれないが、お気をつけくださいー。<br />
<br />
<br />Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-78803688108688226142019-01-23T15:55:00.000+09:002019-01-23T15:55:13.057+09:00Hops - 木霊の旅 リリースしました!<div class="separator" style="clear: both; text-align: center;">
<a href="https://itunes.apple.com/jp/app/id1433717138?mt=8" target="_blank"><img border="0" data-original-height="340" data-original-width="500" height="217" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirUgnth1vSrLMw8hx2yNs5EFTIEzJ_rF_xJ-4gY-LL-L5-r1wyVoyDQ_ZWnDAoIj85VGzZJSH8VS-n-2VMzlDQWPTgleWf8gU5I87U8UZxDEY65RYy9KjyNBTqD7N7lPa_taDdzA1ffkY/s320/Hops.png" width="320" /></a><span id="goog_547453361"></span><a href="https://www.blogger.com/"></a><span id="goog_547453362"></span></div>
<br />
<a href="https://itunes.apple.com/jp/app/id1433717138?mt=8" target="_blank">Hops -木霊の旅</a> をリリースしました!<br />
日々を活動的に過ごすと、いろいろなエリアに行けたり、着せ替えができるようになります。<br />
<br />
<a href="https://itunes.apple.com/jp/app/id1033409631?mt=8" target="_blank">Standland</a> では、スタンド数 のみが対象でしたが、Hopsでは、歩数、階段数、カロリー など対象が増えています。<br />
Standlandでスタンドが習慣化できたら、次はHopsで動くことを習慣にしていこう! という目的のアプリです。<br />
<br />
ランニングしたり、ジムに行ったりしなくても、エスカレータじゃなく階段を使ったり、ひと駅あるいてみたり と、普段の生活でちょっと動くことを意識するだけで随分違う。<br />
<br />
私の経験談では、ダイエットしなきゃ!と頑張って運動して毎日体重測るけど、思ったより体重減らない...とイライラしたことがあるが、動くことを意識してゆるく生活したたら、いつのまにか体重減ってた ってことが結構ある。<br />
<br />
運動しなくちゃいけないんだけど、忙しくてジムにもいけないわーー という人、ぜひお使いくださいませ!<br />
<br />
<br />
<br />
<h3>
内部のお話</h3>
Standlandと同じく、<a href="https://developer.apple.com/documentation/scenekit" target="_blank">SceneKit</a> で3Dモデルが動いていますが、Standlandでは入れれなかった機能がいろいろ入っています。<br />
<br />
<br />
<h4>
DOF</h4>
DOF(被写界深度)が生きていて背景がぼやけて素敵になっています。<br />
これは重い処理なのですが、入れれるように頑張りました( @horiuni さんが )<br />
なので、全てののエリアを是非見て欲しいー!<br />
<br />
<br />
<h4>
キャラを動かせる</h4>
キャラを自分で動かせます。<br />
最初は歩くのが遅くてちょっとイラっとするかもしれないのですが、SPEED値を上げていくと早くなるので、ぜひ上げてみてください。<br />
歩くアニメーションですが...<br />
<br />
SPEED 0 (遅い)の時 はのっしのっし歩きます。<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dypLyPImQqgEXZUKDXrqKUK5AVILLSWbMdwbrIKeJY5W2CqCpoObuBKxeRydjDW8dYEiAjCINRcLLFoKbfrxA' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<br />
<br />
SPEEDが早くなっていくにつれ、前傾姿勢でバタバタ走ります。<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dzufMwEez7gospQzvCINgExdD51JSkud7yKRCwZslDF6wAvDdiU3g5p_JovbcQqAiMEnpiMqMqIy73cu9Ay2Q' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<br />
<br />
この実装には、遅い用、早い用のアニメーションを2つだけ用意し、iOS11 で追加された <a href="https://developer.apple.com/documentation/scenekit/scnanimationplayer" target="_blank">SCNAnimationPlayer</a> のblendFactorとspeedの値を調整してしています。<br />
<br />
歩く音も入れているのですが、これもAnimationPlayerのおかげでとても簡単。<br />
SCNAnimationのanimationEventsに音を鳴らす処理をいれておけば、Playerのspeed値に合わせてEventの発生タイミングも変わってくれるから。<br />
あー、AnimationPlayer ラブ❤<br />
<br />
<br />
他には、カメラをいくつか用意して切り替えしてみたり、カメラの Color Grading いれてみたり。<br />
SceneKitってiOS11で随分変わったので、Standlandでは入れれなかった事が結構あったのですw<br />
<br />
<br />
...ということで、ぜひ Hops をお試しください!<br />
そして、なにがバグがありましたら、Feedbackのメールを頂けるととても助かります m(_ _)m<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-1406907607467702152018-11-07T00:36:00.000+09:002018-11-07T00:36:45.858+09:00サマータイム関連のバグ ふたたびサマータイムに伴うバグを作っていたのを発見!<br />
うう、何回目だろう。気にしているつもりなんだけどなぁー。<br />
参考になる人がいるかもなので、共有しますっ<br />
<br />
<h3>
1. ○分後 を取得する</h3>
<br />
たとえば、30分後を取得したいとき。<br />
<br />
let date = dateGMT(year: 2018, month: 11, day: 4, hour: 8, minute: 30)<br />
print("日付:", date)<br />
let cal = Calendar(identifier: .gregorian)<br />
var comps = cal.dateComponents([.year, .month, .day, .hour, .minute], from: date)<br />
comps.minute! += 30<br />
print("30分後", cal.date(from: comps)!)<br />
<br />
とかくと、<br />
<br />
日付: 2018-11-04 08:30:00 +0000<br />
30分後 2018-11-04 09:00:00 +0000<br />
<br />
...となりますが、iPhoneのTime Zoneをサンフランシスコにしていると、<br />
<br />
日付: 2018-11-04 08:30:00 +0000<br />
30分後 2018-11-04 10:00:00 +0000<br />
<br />
になります。<br />
2018-11-04 2:00:00 PDT = 2018-11-04 09:00:00 GMT がサマータイム終了タイミングで、1時間進むためです。<br />
○分後 という絶対秒数を追加するには、素直にdate.addingTimeInterval(1800) と書けっつーことですな。<br />
<br />
※ PDT = Pacific Daylight Time = 太平洋 サマータイム時間 UTC-7<br />
PST = Pacific Standard Time = 太平洋 標準時間 UTC-8<br />
<br />
<br />
<h3>
2. カレンダーイベントの登録</h3>
<div>
カレンダー(EventKit)で、イベント(EKEvent)を登録する際、開始日時と終了日時でサマータイムの有無が変わる場合、注意が必要です。</div>
<div>
<br /></div>
<div>
たとえば、以下の日付のイベントを登録した場合。</div>
<div>
<br /></div>
<div>
開始日時: 2018-11-04 1:30:00 PDT = 2018-11-04 08:30:00 +0000</div>
<div>
終了日時: 2018-11-04 1:00:00 PST = 2018-11-04 09:00:00 +0000</div>
<div>
<br /></div>
<div>
<div>
let event = EKEvent(eventStore: eventStore)</div>
<div>
event.calendar = eventCalendar</div>
<div>
event.title = "Test"</div>
<div>
event.startDate = dateGMT(year: 2018, month: 11, day: 4, hour: 8, minute: 30)</div>
<div>
event.endDate = dateGMT(year: 2018, month: 11, day: 4, hour: 9, minute: 00)</div>
<div>
<br /></div>
<div>
do {</div>
<div>
try eventStore.save(event, span: .thisEvent)</div>
<div>
} catch {</div>
<div>
print(error)</div>
<div>
}</div>
</div>
<br />
iPhone端末のTime Zoneがサンフランシスコなど(US/Pacific)に設定されていると、以下の日付になってしまいます。<br />
<br />
開始日時: 2018-11-04 1:30:00 PDT = 2018-11-04 08:30:00 +0000<br />
終了日時: 2018-11-04 1:00:00 PDT = 2018-11-04 08:00:00 +0000<br />
<br />
つまり開始が終了よりも遅い時間に。<br />
ちゃんとDate型で指定しているのだから反応してよーーとは思うんですけどねぇw<br />
<br />
ちなみに、iCloudのカレンダーで上記の状態になります。<br />
同期しているGoogleカレンダーに登録すると、終了時刻が勝手に2時間後に置き換わるようです。<br />
開始 > 終了 というのが不正な状態なので、その場合は置き換わるようになっていそう。<br />
<br />
開始と終了日付のTime Zoneが別々に指定できたらよいのですが、iPhoneカレンダーは1つのTime Zone (サマータイム有無は現在の日時のものが有効?)の設定のみ。<br />
Googleカレンダーは別々にTime Zoneが設定できるものの、サマータイム有無について設定ができるわけではない。<br />
<br />
EKEventのtimeZoneプロパティに TimeZone(secondsFromGMT: 0) を設定すると正しい日時が登録ができます。<br />
が、Googleカレンダーの場合、詳細を見るとGMTでの登録なのがわかる。<br />
<br />
どうするのが一番良い方法なのかは分からず。<br />
iPhoneの設定 > カレンダーにある、「Time Zone Override」の設定によっても変わる予感も。<br />
ふむー。Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-27563728734219080572018-07-04T18:22:00.002+09:002018-07-04T18:40:35.295+09:00サーキットトレーニング先週からサーキットトレーニングを始めました。<br />
サーキットトレーニングとは、筋力系と有酸素系の運動を組み合わせたインターバルトレーニングのこと。<br />
<br />
私は<a href="http://www.alliance-jp.com/category02/index.html">milon</a> のマシンが置いてあるジムに通っている。<br />
筋力系6種類を1分間づつ、有酸素系2種類を4分間づつ、それらの間は30秒のインターバルになっていて、1周17分30秒でトレーニング。<br />
行う順番は決まってきて、並んでいるマシンを順々に移動していく感じ。<br />
<br />
<a href="http://www.alliance-jp.com/category02/index.html">milon</a> のマシンは、シートの位置や、負荷が記録されたカードをマシンに差し込むと、自動で準備してくれるのがすごく便利。<br />
ちなみに、心拍計はついていなく、Polarの心拍計とつなげることが出来るらしい。<br />
でも、そんなにバタバタ動かないし、時間も30分くらいなので Apple Watch で十分と思う。<br />
トレーニング記録は、<a href="https://itunes.apple.com/jp/app/id1220362669?mt=8">milon ME</a> というアプリでも見ることができる。<br />
まぁ私は <a href="https://itunes.apple.com/jp/app/id1139688415?mt=8">Zones</a> で記録するけれどもねw<br />
<br />
<br />
<h3>
やることが決まっているので考えることが少ない</h3>
これが、なにげにいい。<br />
通常のジムにいくと、<br />
空いてるところどこかな?...負荷はどれくらいだったっけ...何回やるかな...1回、2回...次はどれにしようか...<br />
と考えながら動くと思いますが、これが全くイラナイ。<br />
英語のPodcastも聞きながらもできる。<br />
<br />
<br />
<h3>
全部できてる安心感</h3>
筋力も持久力もまったくない私としては、全体的な体力ベースを上げていきたい。<br />
そういう人にとっては、一通り回れば全体的に鍛えられているはず!という安心感がある。<br />
<br />
<br />
<h3>
体力ないのがバレにくい</h3>
人によって負荷設定が違うが、それがまわりからは見えない。<br />
なので、体力がないために、滝汗をかいて息を切らしていても、「あー、高負荷でやってるんだろうな」って思ってもらえそうなw<br />
<br />
<br />
<h3>
心拍数・強度</h3>
筋力系マシンを早く動かして、ガシャコガシャコしてるお兄さんを昨日見た。<br />
HICT(高強度サーキットトレーニング)をしたかったのかな?と思うが、種類を選べないジムでのHICTは難しそうに思った。<br />
レッグカールで心拍数を80%以上にとか想像できない...。<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEvzznYuw_AJWYRzKMB_UwvataAt9kscYpPNtduZvtSOTT94ThyyH8JLWUn9QFqeI7mljchmkqzhgw1IutARUFiZdY_2NyFDXp2P4_J7-s21t2bvhwjXUQx19d03u8uSyw7R7Sk0TlLxU/s1600/IMG_2333AD7AA063-1.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="912" data-original-width="912" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEvzznYuw_AJWYRzKMB_UwvataAt9kscYpPNtduZvtSOTT94ThyyH8JLWUn9QFqeI7mljchmkqzhgw1IutARUFiZdY_2NyFDXp2P4_J7-s21t2bvhwjXUQx19d03u8uSyw7R7Sk0TlLxU/s320/IMG_2333AD7AA063-1.jpeg" width="320" /></a></div>
<br />
<br />
上記は私が3周回ってみた時の結果。<br />
心拍数が上がっているのは有酸素系をやっている箇所で、筋肉系では全然心拍数をあげられず、緑のゾーンまで落ちちゃっているという図。<br />
<br />
1周回れなかったらどうしよう?というビビリもあり、負荷は軽めでやっているので、これからゆっくりあげていって、全体が黄色のゾーン以上が保てるといいなぁーなんて考え中。<br />
<br />
心拍数がだんだん落ちにくくなっているのは、回復心拍数が良くない = 体力がない ということと思う。<br />
体力がついてきたら、きれいな連続した山になっていく...ハズ!<br />
<br />
<br />
<h3>
プロテイン</h3>
ちょうど、一日の食事で得られるたんぱく質、脂質、炭水化物をメモしてバランスを見ていたので、たんぱく質不足になりやすく、いざ摂取しようと思っても難しい のは感じていた。<br />
脂質や炭水化物を取るのは楽なんですけど、たんぱく質ってホント難しい。<br />
そして、運動をすると更に多くのたんぱく質が必要と言われたら、もう、効率よく取れるなにかに頼るしかないなーと。<br />
<br />
たんぱく質の1日の推奨量、<br />
運動していない人は 体重1kgあたり 0.8g だけど、<br />
運動し始めた人は 体重1kgあたり 1.7g って... 倍じゃん!?<br />
<br />
<br />
ドンキに行ってプロテインコーナーをぼんやり見ていたが、マッスルな感じのものは手がが出せず、<a href="https://www.dear-natura.com/product/detail/soy-milk-active">Dear Natura の ソイプロテイン</a> を購入してみた。<br />
プロテインの含有量は少なめとは思うけど、腎臓が弱く、普段の食事のバランスも取れてない初心者の私としては良いかなと。<br />
<br />
今まで意識して食べていた納豆のたんぱく質は、6.3g / 1食<br />
Dear Naturaでは一気に15gとれる。<br />
PFCバランスでみると、納豆 の27%から、Dear Naturaは74%にグーンとアップ。<br />
<br />
味も飲めるレベルだし泡立ち少なくて飲みやすい。最近のプロテイン、やるね。<br />
気になったのは、甘かったこと。甘い粉なので、ダニが発生しやすそう... 大きな袋でまとめて購入はちょっと怖い。<br />
あと、続けていくには値段が気になるトコロ。手軽さを考えると価値はアリか。<br />
<br />
<br />Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-77360065905919474702018-06-23T14:24:00.000+09:002018-06-23T15:06:40.806+09:00Flaskが2人であること6月は人と話す機会が多かった。<br />
「<a href="https://flaskapp.com/">Flask</a>という名前で2人で開発してます」 と自己紹介をするのですが、その時の自分の気持ちとしては、たった2人で頑張っているんです! というのを伝えたいがためなんですが、<br />
<br />
「2人は仲がいいのですね」<br />
「喧嘩はしないのですか?」<br />
「なぜ2人なのですか?」<br />
<br />
と聞かれることが多い。<br />
そういや、ベンチャー解散の理由はFounder同士の仲違い ってよく聞いたりするなぁと思い出した。仲違いせずにどうして続けていけるのだろう?という疑問が根底にある質問なのですね、多分。<br />
<br />
ぶっちゃけ、そういうことはあまり意識していなかった。<br />
1人よりも2人のほうが心強くてやっぱいいよね! と単純な思いで始めて、5年続いた私はラッキーなのだと思う。<br />
<br />
<br />
<h3>
仲違いしない ということ</h3>
いろんな所で言われていることと思うけど、複数のFounderって結婚に近くて、根底にある価値観が一致していないと難しいのかも。<br />
他人だから意見の相違があるのは当然で、話し合いで解決していくわけだけど、根底の価値観が違うと大変そうだ。<br />
<br />
お金に対する価値観 が一致しているのか? は大事と思う。<br />
お金って泥臭い所なので、あまり話しづらいけど、かなり大切。<br />
「一気にboostしてexitしたい」って人と、「大金持ちにならなくていいから、こだわったものをじっくり作りたい」って人はどう考えてもプロセスもゴールも違う。<br />
<br />
仲間を見つけようとしている人には、Passionだけでなく、お金とその時間軸、ライフスタイルバランス などの価値観があっているかどうか?も相談しあうと良さげ。<br />
<br />
ちなみにFlaskの場合は、最初にそういう話はしなかった。なんとなく、一致していそうだ...とは感じてはいたけど。<br />
後に、「こう思っているけど、一致してる?」ってドキドキしながら聞いた記憶があるw<br />
<br />
<br />
<h3>
1人ではない ということ</h3>
良いことも悪いことも意見してくれて、親身になってい一緒に考えてくれる という存在は、やっぱりとっても有り難い。<br />
1人だと、決めるのも作業も早いけど、孤独デス。<br />
友達に意見を聞くことはできるけど、「なるほど...」(でも、ココはアレだからやりたくないな..)って反論を心の中で殺しがち。<br />
意見を聞かせてもらっているってお願いしている立場だと、否定するようなことは言えないな...と、気を使っちゃうけど、仲間なら全部吐き出して、その場で議論ができる。そして、その議論の延長上に新しい発想が結構転がっている。<br />
<br />
リスクもメリットも同等に共有している仲間だからこそできる会話ってあると思う。<br />
それが心地いいと感じるのは、昔、孫請け開発していた時に、なにかを変えようとしても各関連会社のリスク配分が違うために話がまとまらない というイライラを見てきた経験があるからなんだろうな...。<br />
<br />
<br />
<h3>
2人である ということ</h3>
<div>
人数を増やさないのか? もよく聞かれるけれども、Flaskにとっての成功は、大きな会社にすることじゃない。それよりも、納得感をもって仕事できる方が幸せ。</div>
<div>
というか、3人、4人...と人数が増えてもうまくやっていける人が逆にうらやましい。</div>
<div>
<br /></div>
<div>
私は、言語化するのに時間がかかるタイプ。</div>
<div>
意見やアイデアを聞いて、なにか「モヤッ」があった時、その「モヤッ」が何なのか? は、1人でゆっくり考えないとうまく表せない。</div>
<div>
こういうタイプの私が、多数決ができる人数の中にいると、「みんなが一致しているのだから大丈夫なのだろう」と流されてしまう。</div>
<div>
「自分のせいで、みんなの時間を浪費したくない」と思ってしまうケチな要素もある。</div>
<div>
...だが、頑固でもあって、流されるのも嫌 という、あーー、めんどくさいヤツw</div>
<div>
<br /></div>
<div>
悩んで時間をかけた箇所って、思った以上に良いアイデアが生まれたりするので、これがまた楽しい。</div>
<div>
逆に、ほとんど議論せず作られたものって、当たり障りのない面白くないもの だったりしがちかも。</div>
<div>
<br /></div>
<div>
ということで、私は「ゆっくり考える時間をオクレ!」と気軽に言える人数感がBEST。</div>
<div>
BESTな人数や方法って、メンバーの性格によって千差万別なんだろうな。</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
2人であること を言語化したいと思って、このブログを書いてみたのだけども、自分がめんどくさいヤツということを再認識して少しオチたw</div>
<div>
<br /></div>
<div>
<br /></div>
Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-69805164065163045642018-06-16T12:28:00.000+09:002018-06-16T12:42:37.235+09:00WWDC 2018に行ってきた<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi49ZeGh-ybjpsT_YVylNtDTtoUoCIqGO1fCydVkWjB8D8vqsZbQGwrbKOc0IOY2DenUbmCMP_hEUqZV9IfvFToItMt5XGhT13NqgORsUUlG-IZBKAaoRmP9nN8zKWbEMy9stbeQBEGKEM/s1600/Screen+Shot+2018-06-16+at+10.12.30.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="624" data-original-width="1600" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi49ZeGh-ybjpsT_YVylNtDTtoUoCIqGO1fCydVkWjB8D8vqsZbQGwrbKOc0IOY2DenUbmCMP_hEUqZV9IfvFToItMt5XGhT13NqgORsUUlG-IZBKAaoRmP9nN8zKWbEMy9stbeQBEGKEM/s640/Screen+Shot+2018-06-16+at+10.12.30.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
WWDC 2018 に行ってきました。<br />
今年も、空が青い!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfUPfIJ67G6A2JQjjLrIS7ADDVkOX99ECrQalfdyUwktplponEDw_Z6NHkd2Gs8waOMxo3wZY3AQYk9da8vElhvrehjaN0dlhuNNqCT7pnugAr4y_6uEH7KWIhftiPRneNfZoqzCQRSrk/s1600/IMG_0883.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfUPfIJ67G6A2JQjjLrIS7ADDVkOX99ECrQalfdyUwktplponEDw_Z6NHkd2Gs8waOMxo3wZY3AQYk9da8vElhvrehjaN0dlhuNNqCT7pnugAr4y_6uEH7KWIhftiPRneNfZoqzCQRSrk/s320/IMG_0883.JPG" width="240" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu9ydR5PVRm13nZRVsg68R8jVKPfAc0Zj6dTu82Q9GpWscfl7OR5DJbIafSvLGffqJPH-UxEe1XbQQV-lIsc5gLch8jJdfLRvPh6NWs35uxcYv89x7L5BjWcVz8e9HXgzOZeZ7JJj3JEU/s1600/Screen+Shot+2018-06-16+at+10.10.06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="908" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu9ydR5PVRm13nZRVsg68R8jVKPfAc0Zj6dTu82Q9GpWscfl7OR5DJbIafSvLGffqJPH-UxEe1XbQQV-lIsc5gLch8jJdfLRvPh6NWs35uxcYv89x7L5BjWcVz8e9HXgzOZeZ7JJj3JEU/s320/Screen+Shot+2018-06-16+at+10.10.06.png" width="181" /></a></div>
<br />
街ナカには、Bird と Lime-S (電動スクーター)が、あらゆる所に乗り捨てられていていた。<br />
スピード結構でるし、手軽だし、かなり便利。<br />
サンノゼは歩道が結構広いので、乗り捨てられていても邪魔にならずに受け入れられているっぽい。<br />
<br />
今年は、WWDCの公式なSpecial Eventsとして、朝にみんなでRunとかBootcampがあったりなど。<br />
私は、Kayla Itsines のBootcamp に参戦してみた。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFxjAUbARUX5WP8CZpMroFtrI5n8S5VnPc-4uyCX0jHQYCrByji0tnyHQGotH1sWCWgsdPCe6t_6cOCTygCj7qDChQ1ZmJgydCHcNNmSXnKH_Fk7gVY4WEXUhAJBTyrELUeIflydCgo44/s1600/IMG_0929.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFxjAUbARUX5WP8CZpMroFtrI5n8S5VnPc-4uyCX0jHQYCrByji0tnyHQGotH1sWCWgsdPCe6t_6cOCTygCj7qDChQ1ZmJgydCHcNNmSXnKH_Fk7gVY4WEXUhAJBTyrELUeIflydCgo44/s400/IMG_0929.JPG" width="400" /></a></div>
<br />
参加できるのはWWDCの参加者なので、体力がないオタク な人も多いハズ!<br />
と思っていたが、なんか動ける人ばかりで場違い感ハンパなかった。<br />
スタイル良しのスマートなDeveloper。すげー憧れるー!<br />
<br />
<br />
さて、本題のWWDC。<br />
<br />
技術的には、<a href="https://developer.apple.com/videos/play/wwdc2018/602/">ARKit2</a>、<a href="https://developer.apple.com/documentation/sirikit#2979425">Siri Shortcuts</a> の発表があった。<br />
それらも楽しみではあるのだが、今回注目すべきことは、Apple が Developer に宣言した、以下の一言に集約される方針と思う。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbKMoplWlqoQ41gTk9gvp-Xye9_o-_AftOkmvdQNsBrTe9Uu_apwWuyaYbOxW9LRKv8SF5-gCbAT5rs5nXxKaHmHZi_wvSAURL80wLDa5uI1Sxn3i40955mtlqKr1SBFuJkQRF145Cgv8/s1600/Screen+Shot+2018-06-16+at+10.38.27.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="818" data-original-width="1600" height="326" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbKMoplWlqoQ41gTk9gvp-Xye9_o-_AftOkmvdQNsBrTe9Uu_apwWuyaYbOxW9LRKv8SF5-gCbAT5rs5nXxKaHmHZi_wvSAURL80wLDa5uI1Sxn3i40955mtlqKr1SBFuJkQRF145Cgv8/s640/Screen+Shot+2018-06-16+at+10.38.27.png" width="640" /></a></div>
<br />
<br />
広告収入が目的のアプリの場合、どれだけアプリを起動してもらえるか、長く滞在してもらえるか が重要かと思う。<br />
だが、今回発表された、Screen Timeではアプリ滞在時間を確認して、無駄に時間を浪費するのを防いだり、Siri Shortcuts でアプリを起動せずにやりたいことだけ指示する など、ある意味、反対方向の仕組みを投入してきた。<br />
<br />
以前、AppleはiAdという広告プラットフォームを提供していたが、2016年6月に終了し、それからは、サブスクリプション(定期購読)の押しが強くなった。<br />
iAdが終了したときには衝撃を受けたのだが、今思うと、こういう方針でいくのであれば当然な決断だったのだろう。<br />
<br />
Developerとしても、マネタイズを意識するあまりにユーザにとって「悪」なことはしてなかったか? を意識するよいきっかけなのかもしれない。<br />
<br />
Siri Shortcuts を勝手に深読みすると、VR/MRを見据えていると捉えることもできそうな。<br />
音声で指示するのって、とても大事な要素な気がするから。<br />
<a href="https://developer.apple.com/documentation/naturallanguage">Natural Language</a>や<a href="https://developer.apple.com/documentation/create_ml">Create ML</a>で、いろんな言語の情報を蓄積しておきたいって気持ちもありそうな感じ。<br />
サードパーティのDeveloperに、Siri Shortcutsで、そういうアプリの設計に慣れておいて欲しい という期待も含まれているかもしれない。<br />
<br />
<br />
あと、iOS12 で動作が軽くなるのがとても嬉しい!<br />
Twitterなどの反応をみるに、実感できるほど軽くなっているらしい。<br />
昨年末に旧機種の動作を故意に遅くしている疑惑が持ち上がったが、それに対する回答の一つだろうか。<br />
Developerとしては正直、ユーザーはどんどん新機種に移行して欲しい のだが、今後も切られるデバイスは少なくなっていくのかもしれない。<br />
<br />
ともあれ、WWDC楽しかったです!<br />
Appleさま、現地で仲良くしてくださったみなさま、ありがとうございました (_ _)<br />
<br />
<br />Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-55920869652978138262018-05-31T21:19:00.000+09:002018-05-31T21:19:35.536+09:00WWDC 2018の期待WWDC 2018 の開催が来週に迫ってきました!<br />
今年も現地に行って体感してきます。<br />
<br />
今年はどんな発表があるのでしょうか?<br />
新型iPad, Macbookなどのハード系の話が多く、ソフト系は安定・セキュリテイ強化が中心であまり進化がないのでは? という話がちらほら。<br />
でも、ソフト系のワクワクもあって欲しいな!だってWWDCなのですから!<br />
<br />
<br />
<h3>
期待は昨年と同様...</h3>
昨年、<a href="http://blog.sorausagi.org/2017/06/wwdc-2017.html">WWDC 2017の期待</a> という記事を書いたのですが、今年もあまり変わっていないカモ。<br />
・HomePodは、次はカナダ、フランス、ドイツの発売らしく日本はしばらく無さげ。<br />
・AirPowerは、待っているよ。早く発売して欲しい!(お土産にしてくれてもいいよw)<br />
・Apple Watchの血糖値測定、睡眠トラッカーは今年も期待してる!<br />
・Watch Faceのサードパーティへの開放はもう無いのかもな...。<br />
<br />
<br />
<h3>
ヘルスケア系</h3>
今回は、<a href="https://developer.apple.com/wwdc/special-events/">WWDCのスペシャルイベント</a>として、WatchのActivityの3つのリングを完成させる「Close Your Rings Challenge」や、「Kayla Itsines Bootcamp powered by SWEAT」「WWDC Run with Nike Run Club」というヘルス系のものが多くある。<br />
ヘルスケアに力入れている感が伝わってくるので、なんだか期待しちゃう!<br />
<br />
<br />
<h3>
OCR</h3>
iOSで使えるOCR、あまり進化がないもんなんだなと最近思ったので。<br />
MRと騒がれているのだから、もっと進化した何かがポンポン出てきてもいいんじゃないかしらーと素人目に思ってしまう今日このごろ。<br />
(難しいところは賢い人にまかせて、結果を使いたい派です...)<br />
<br />
Google Cloud Vision API だと賢くなっているのかもですが、Tesseract OCR iOS のようなローカルなものか、Apple提供の何か... でてくると嬉しい。<br />
<br />
<br />
<h3>
NFCのサードパーティ開放</h3>
これがきたら忙しくなる日本の開発者も多そう。<br />
<br />
<br />
<br />
ワクワクさせてほしい気持ちもあるけど、ちょっと落ち着いて溜まったバグを早く消化して欲しい気持ちもある。<br />
後者であれば、いろんなBest Practiceをお勉強する場になりそう。<br />
<br />
ともあれ、楽しんできます!<br />
<br />
<br />
<br />Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-15244099513426918092018-04-21T17:33:00.000+09:002018-04-21T17:33:25.619+09:00電子タバコをお試し中今年もWWDCでサンノゼに行くことになった!<br />
<br />
心配は、英語はもちろんなのだが、タバコが吸えないこともある。<br />
ホテルやバーも含め、室内では一切吸えないし、夜中にフラフラ外にでてタバコを吸いに行くのも怖いので....吸えない時間はかなり長く、ツライ。<br />
<br />
なので、タバコの量を減らすことも目的に、電子タバコを試し中です。<br />
<br />
<h2>
<a href="http://www.emili.jp/brand/">EMILI</a></h2>
<br />
2年前ぐらいに <a href="http://www.emili.jp/brand/">EMILI</a> を購入していた。<br />
<div>
<a href="https://www.amazon.co.jp/gp/product/B00XVPP9RU/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B00XVPP9RU&linkCode=as2&tag=aqubi-22&linkId=ddd9f1affe1b7ff8abcbd30abdf723f1" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=B00XVPP9RU&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=aqubi-22" /></a><img alt="" border="0" height="1" src="//ir-jp.amazon-adsystem.com/e/ir?t=aqubi-22&l=am2&o=9&a=B00XVPP9RU" style="border: none !important; margin: 0px !important;" width="1" /><br />
サイズも小さくて、2本あるので持ち運びもしやすくてよかったのだが、使わなくなってしまった。<br />
一番の理由は、ニコチン無しのリキッドで試したので、タバコからの完全移行はできなかったこと。<br />
リキッドが白く結晶化することがあるようで、カートリッジ部が透明なのもあり、それが目立ってしまうのがイマイチだった。<br />
<br />
<br />
<h2>
<a href="https://www.discoverglo.jp/">glo</a></h2>
<a href="https://www.amazon.co.jp/gp/product/B073S19C6Z/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B073S19C6Z&linkCode=as2&tag=aqubi-22&linkId=0a82b04003dec4d7bb868f7dae4d8c16" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=B073S19C6Z&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=aqubi-22" /></a><img alt="" border="0" height="1" src="//ir-jp.amazon-adsystem.com/e/ir?t=aqubi-22&l=am2&o=9&a=B073S19C6Z" style="border: none !important; margin: 0px !important;" width="1" />
<br />
<br />
<br />
IQOSはタバコ葉を直接加熱するが、gloはタバコのスティック全体を外側から加熱するタイプ。<br />
IQOSは頻繁にお手入れが必要で臭いもあるらしいので手を出さなかったのですが、gloはお手入れも楽。<br />
タバコのガツン感は無いけど、タバコを減らしていきたい人にはちょうどいいのかなというのが試した理由。<br />
ただ、私には、味がイマイチ合わず。なんか変な雑味がある。<br />
美味しさを求めてはいけないのはわかっているのだが、まずいと思って吸い続けるのもなぁ...<br />
<br />
<br />
<h2>
<a href="https://c-tec.style/">C-Tec</a></h2>
<br />
<a href="https://www.amazon.co.jp/gp/product/B06XFWG8JP/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B06XFWG8JP&linkCode=as2&tag=aqubi-22&linkId=047ab15ec768f6dd0970b2ad3831189d" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=B06XFWG8JP&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=aqubi-22" /></a><img alt="" border="0" height="1" src="//ir-jp.amazon-adsystem.com/e/ir?t=aqubi-22&l=am2&o=9&a=B06XFWG8JP" style="border: none !important; margin: 0px !important;" width="1" />
<br />
ビタミン入りの電子タバコ で、フレーバーにはニコチンは含まれてないタイプ。<br />
本体部分はPloomTECHと互換があるので、C-Tecのフレーバーを楽しみつつ、PloomTECHも試してみようという目的で購入。<br />
<br />
スターターキットにはいっていたエナジードリンク、クリスタルメンソールのフレーバーは美味しかった。<br />
追加でエスプレッソを試してみたが、これが甘いコーヒー牛乳みたいな味で、マズくて、びっくりしたw<br />
<br />
<br />
<br />
<h2>
<a href="https://www.ploom.jp/">PloomTECH</a></h2>
<a href="https://www.amazon.co.jp/gp/product/B074GQ1HBX/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B074GQ1HBX&linkCode=as2&tag=aqubi-22&linkId=cfee1f2af672902a9e89ce1a012e870f" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=B074GQ1HBX&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=aqubi-22" /></a><img alt="" border="0" height="1" src="//ir-jp.amazon-adsystem.com/e/ir?t=aqubi-22&l=am2&o=9&a=B074GQ1HBX" style="border: none !important; margin: 0px !important;" width="1" />
<br />
<br />
今は、PloomTECH をメインで使用中。<br />
タバコのガツンと感はほぼ無い。ペビースモーカーだった人は全く物足りないはず。<br />
ニコチン量を減らしたい、禁煙したいって人には良い製品と思う。<br />
味はgloに比べたら断然美味しい。<br />
<br />
C-TecやPloomTECHのような使い捨てカートリッジという仕組みもイイ。EMILIのリキッド充填式のカートリッジが不満点が解消された。口につけるものだからなぁ うんうん。<br />
デメリットとしては、ずーっと吸い続けてしまうトコロ。<br />
<br />
PloomTECHはタバコ葉部分と、リキッド部分が別れているので、同時に使い切れないこともある。<br />
それもあり、リキッドを別途購入して、カートリッジ再生もたまにしている。<br />
リキッドのフレーバーは、青りんご味とか試したけど、やっぱりメンソールがイイ。<br />
<br />
<a href="https://www.amazon.co.jp/gp/product/B074BVK5X1/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B074BVK5X1&linkCode=as2&tag=aqubi-22&linkId=d159ef843bde9c1bf3d099dc2e4aed55" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=B074BVK5X1&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=aqubi-22" /></a><img alt="" border="0" height="1" src="//ir-jp.amazon-adsystem.com/e/ir?t=aqubi-22&l=am2&o=9&a=B074BVK5X1" style="border: none !important; margin: 0px !important;" width="1" />
<br />
<br />
今使っているのは、XLVAPORのXLメンソール。<br />
名前からして凄くキツイメンソールかとおもいきや、そうでもなく、普通に吸えるので次回は特大100ml版を買う予定。<br />
<br />
カートリッジ部分は再生できるといっても、消耗品なので、たまに補充している。<br />
<br />
<br />
<a href="https://www.amazon.co.jp/gp/product/B0761PXNFK/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B0761PXNFK&linkCode=as2&tag=aqubi-22&linkId=2ad551531276ea0ae9f9be2d2edaeaed" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=B0761PXNFK&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=aqubi-22" /></a><img alt="" border="0" height="1" src="//ir-jp.amazon-adsystem.com/e/ir?t=aqubi-22&l=am2&o=9&a=B0761PXNFK" style="border: none !important; margin: 0px !important;" width="1" />
<br />
<br />
BLIESTのカートリッジ(5本 980円)は、PloomTECHのタバコ部分をつけることができる。<br />
<br />
移行してから2ヶ月ちょいほどだが、まだニコチンゼロだとちょっとツライ。<br />
でも随分ニコチン量は減っているように思う。<br />
グリセリン(VG)、プロピレングリコール(PG)の吸入量はめっちゃ増えてるけどね!<br />
<br />
<br />
<br /></div>
Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-14202128297295002522018-03-25T23:58:00.000+09:002018-03-25T23:59:47.489+09:00iOSアプリのアクセサビリティ対応しないとと思いつつも、後回しになってしまう アクセサビリティ対応。<br />
先日、ユーザさんにフィードバックを頂いて、「う、ごめんなさい」と思いつつ具体的に調べてみた。<br />
<br />
iOSアプリで対応が必要なのは、<a href="https://www.apple.com/jp/accessibility/iphone/vision/">VoiceOver</a> という読み上げ機能。<br />
ある程度デフォルトで組み込まれているので、意識せずアプリを作成していても、VoiceOverが動作する。<br />
良い意味でも悪い意味でも、iOSアプリはアクセサビリティ対応が標準という位置づけ。<br />
そのため、知らずに恥ずかしい状態でアプリをリリースしている可能性がある。<br />
<br />
<a href="https://developer.apple.com/jp/documentation/iPhoneAccessibility.pdf">iOSアクセシビリティプログラミングガイド</a> に日本語のドキュメントがある。<br />
プログラミングガイドとなっているが、どんなラベル、ヒントなどを入れると良いのか?という記述もあり、プログラマー以外でもとても参考になると思う。<br />
<br />
(ただドキュメントは少し古いようで、Accessibility Inspector の表示方法が違っていて、XCode のメニュー Open Developer Tool - Accessibility Inspector で可能。)<br />
<br />
基本的なことは、そのガイドを理解できるので、ここでは、実際に対応を試してみて、気がついたところを書いてみる。<br />
<br />
<br />
<h3>
VoiceOver対応のコスト</h3>
VoiceOver対応にかかる工数・コストは、一概にこれぐらいというのはない。<br />
UIデザインに依存していて、なにも対応しなくてOKな場合あるし、そもそもVoiceOverでは操作が無理という場合もある。<br />
<br />
つまり、アプリのUIを考える前に、VoiceOverについて理解しておくとGood。<br />
<br />
<br />
<h3>
画像Onlyボタン</h3>
<div>
ラベル、ボタンはデフォルトでアクセサビリティがONになっていて、読み上げ対象になる。</div>
<div>
特に指定が無い場合は、表示されている文字が読み上げられるのだが、画像のみのボタンの場合は「画像のアセット名」が読み上げられてしまうようだ。</div>
<div>
これはなんとも恥ずかしい。適当に書いたコードを見られてしまったような恥ずかしさ。<br />
<br /></div>
<div>
画像のみのボタンは、Accessibility Label に文字を入れておくようにしよう。<br />
StoryboardのIdentity Inspector で設定できる。<br />
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbQvTBjy96trwKdWfl23-MwU4iKKArB6Vs1PpLSysMFmlND3kPqfC4W2jalawMHacksmsiRNJBASpmlpPHy0_TLDTxYTZQIqepM-hBbeVIQFiv-GLcipkq8GCto_6IAsjt_cDSvi1xKMs/s1600/Screen+Shot+2018-03-25+at+17.46.02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="218" data-original-width="674" height="103" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbQvTBjy96trwKdWfl23-MwU4iKKArB6Vs1PpLSysMFmlND3kPqfC4W2jalawMHacksmsiRNJBASpmlpPHy0_TLDTxYTZQIqepM-hBbeVIQFiv-GLcipkq8GCto_6IAsjt_cDSvi1xKMs/s320/Screen+Shot+2018-03-25+at+17.46.02.png" width="320" /></a></div>
<br /></div>
<div>
<br />
<h3>
正しいTraitsを</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEtl8gdS-yKEAGtzUGm6xeBHt_FtmWk4GxvnyCyKQfJ0m9uGM8rMh1M0vqXHefnvZUAPbs7Tytk9VDserv8W1O1DjcfhCTu-iHnHezMAPw3npAZHeJiNQP_5-XBBlMyLmqi6tj0ZQC_LA/s1600/Screen+Shot+2018-03-25+at+17.52.41.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="518" data-original-width="506" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEtl8gdS-yKEAGtzUGm6xeBHt_FtmWk4GxvnyCyKQfJ0m9uGM8rMh1M0vqXHefnvZUAPbs7Tytk9VDserv8W1O1DjcfhCTu-iHnHezMAPw3npAZHeJiNQP_5-XBBlMyLmqi6tj0ZQC_LA/s320/Screen+Shot+2018-03-25+at+17.52.41.png" width="312" /></a></div>
<div>
<br /></div>
TraitsにButtonが設定されていたら「○○ Button」、Headerが設定されていたら「○○ Heading」と読み上げてくれる。<br />
特にボタンかどうか?は操作する側にとっては大事な情報なはず。<br />
Traitsの設定はここをポチッと変えるだの簡単なものなので普段から意識して設定するのがいいと思う。<br />
<br />
<br />
<h3>
段組みレイアウト</h3>
読み上げの順番は、左上から右下になる。(コードでカスタマイズ可能)<br />
あ、右から読む言語だと逆かもですが。<br />
普通であれば、問題ないのですが、段組みレイアウトの場合は困ったことになる。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7SVxr5lwSou7NfQsK0fhYcVg7dfoTQJ2F-ybKLRy1-HQSe7EriJgOiQOLaiay1SL3hkE_4dVExPWW7sNGCFBN2N5p141JlAs6F-ZvK-xxvmx_38qL7cf41K7CIqKZ6CyuC2P76CosWUQ/s1600/IMG_C9062F5C1837-1.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="356" data-original-width="1125" height="101" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7SVxr5lwSou7NfQsK0fhYcVg7dfoTQJ2F-ybKLRy1-HQSe7EriJgOiQOLaiay1SL3hkE_4dVExPWW7sNGCFBN2N5p141JlAs6F-ZvK-xxvmx_38qL7cf41K7CIqKZ6CyuC2P76CosWUQ/s320/IMG_C9062F5C1837-1.jpeg" width="320" /></a></div>
<br />
この場合、<br />
「ワークアウト」→「平均」→「ベスト」→「100」→「8」→ ....<br />
と読み上げてしまうことに。<br />
この解決には、段組ごとのViewをAccessibilityをONにして、<br />
「ワークアウト, 100件」→「平均, 8分」→「ベスト, 53分」<br />
という文字をViewのAccessibilityのLabelに設定する必要がある。<br />
<br />
Appleのカレンダーアプリでも、AccessibilityのLabelがカスタマイズされている様子。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG47EIjhg5TthK-H1om_v8rG7wSGEweSbI56HTgbaGPvTHj3ByuPu2nq2VgbM0f3GCB5Ak_DrWj-0Nvwiurv40zB8Gxkz67aEUjeTuLtZkbwJiAv33RYbnsNI_EuO92wzRrbdyQdRcsM4/s1600/IMG_3C71BAD44BDC-1.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="484" data-original-width="1125" height="137" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG47EIjhg5TthK-H1om_v8rG7wSGEweSbI56HTgbaGPvTHj3ByuPu2nq2VgbM0f3GCB5Ak_DrWj-0Nvwiurv40zB8Gxkz67aEUjeTuLtZkbwJiAv33RYbnsNI_EuO92wzRrbdyQdRcsM4/s320/IMG_3C71BAD44BDC-1.jpeg" width="320" /></a></div>
「9」をタップすると、「2018年3月9日 金曜日, 1件のイベント ボタン」と読み上げする。<br />
このようなレイアウトは、多くの場合カスタマイズが必要になりそう。<br />
<br />
<br class="Apple-interchange-newline" />
<h3>
Table Cellは自動的に</h3>
Table Cellの場合、Cell の単位で自動的にAccessibleになる。便利!<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSA8BQEStyguTagJRVGKIBmHFZ8XP97G6KLWQvgyTpGOrbdjSQhE_REFHvBF1mpsygKkqeZW2hBLCbJDv0-J5pAjxHShIBw_O0dTN-jPKBaEpmx1VsV0c0isHvWcgxjvyQta3PDjR1ZWg/s1600/IMG_1CEECA037C50-1.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="638" data-original-width="1125" height="181" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSA8BQEStyguTagJRVGKIBmHFZ8XP97G6KLWQvgyTpGOrbdjSQhE_REFHvBF1mpsygKkqeZW2hBLCbJDv0-J5pAjxHShIBw_O0dTN-jPKBaEpmx1VsV0c0isHvWcgxjvyQta3PDjR1ZWg/s320/IMG_1CEECA037C50-1.jpeg" width="320" /></a></div>
<br />
上記の場合、セルのAccessibility Labelに以下の文字が自動的に設定される。<br />
<br />
1行目: 「水泳」<br />
2行目: 「場所, プール」<br />
3行目: 「プールの長さ, 25m」<br />
<br />
カスタムCellの場合もOK。<br />
さらに、Disclosure Indicator ( 右の > ) が設定されていれば、Traitsが自動的にButtonになる。<br />
<br />
<br />
<h3>
単位の表記</h3>
<div>
「10 min」は「Ten minutes」、「1 min」は「One minute」(単数形) で読み上げてくれる。</div>
<div>
ただ、「10, min」は、「Ten, min」になる。</div>
<div>
カンマがあると、読み上げ時に区切って発音してくれる効果があるが、このような違いもでてくる。</div>
<div>
<br /></div>
<div>
値と単位とで、別のLabelにすることをよくしていた。</div>
<div>
「単位は少し小さいフォントにしたい」 というデザインの要望があった時でも、Storyboardだけで対応しやすいから。</div>
<div>
<br /></div>
<div>
しかし、その対応はイマイチだったようだ。</div>
<div>
強い要望がない限りは、値と単位は同じフォント・サイズで、1つのラベルで表示するのがよさそう。</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<h3>
イマイチだったUI</h3>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3MtuRqdOsffqL4nCCxeaPiqXY9ZdC-F5NKnOd8wj4rcdrei2VrTBMWF9FYow4KkNSmAQNNKIBOOPqYDvkUQ9FtKAShM4-6ZqCtx1byB6C9xjfrIqZp3DPFv2EBYLdUrZFBufBrFpDN28/s1600/IMG_9F4F9FCD91E3-1.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="822" data-original-width="1125" height="233" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3MtuRqdOsffqL4nCCxeaPiqXY9ZdC-F5NKnOd8wj4rcdrei2VrTBMWF9FYow4KkNSmAQNNKIBOOPqYDvkUQ9FtKAShM4-6ZqCtx1byB6C9xjfrIqZp3DPFv2EBYLdUrZFBufBrFpDN28/s320/IMG_9F4F9FCD91E3-1.jpeg" width="320" /></a></div>
<div>
<br /></div>
<div>
タップ中は、その箇所の情報が表示され、指を離すと、もとに戻るというUI。</div>
<div>
キャンセル・戻る ようなボタンを用意する必要がないので好きだったのだが、アクセサビリティはイマイチだった。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOkNa_dC-Ph7dAkpqi820HU7gnNITeTAarSnhnHHGvikkZCIJ4NCucSV32QBDN-vepv4Z7bcewvggZjooUOtg3scARO0Sutk6iheH-l9OOdt48LDitf-9-oEHPUx_uVCk2TrMvDRkiAGc/s1600/IMG_1B1E4106BAA8-1.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="338" data-original-width="415" height="162" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOkNa_dC-Ph7dAkpqi820HU7gnNITeTAarSnhnHHGvikkZCIJ4NCucSV32QBDN-vepv4Z7bcewvggZjooUOtg3scARO0Sutk6iheH-l9OOdt48LDitf-9-oEHPUx_uVCk2TrMvDRkiAGc/s200/IMG_1B1E4106BAA8-1.jpeg" width="200" /></a></div>
<div>
<br /></div>
<div>
マイナスとプラスを1つのボタンになっていて、タップした位置によって判断しているUI。</div>
<div>
指を離さなくても、増減を変えられたり、増加量を変えたり出来ると思い作成したが、アクセサビリティはイマイチだった。</div>
<br />
<br />
<br />
<br />
<br />
<br /></div>
Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.comtag:blogger.com,1999:blog-7793912485391197584.post-22552945331957568042018-03-06T15:09:00.000+09:002018-03-06T15:09:53.241+09:00CloudKit(3): Subscription<a href="http://blog.sorausagi.org/2018/03/cloudkit1-databaserecord.html">CloudKitシリーズ</a>第三弾、Subscription。<br />
Subscriptionとはデータが変更されたタイミングをPushで受け取ることが出来る仕組み。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIaw2VLapoHwU3aVWieAaV0KbBiGYqgLf2G7XP8bPiuH2zX77pj3ofKd_wewnQICPeHOtLdPssmYVqIouQyink0TqIPhnJVdY2PALCIM1a4TsGZCU-jKMNWkvBqo04St2lvSSlJZiHj0w/s1600/subscriptions_2x.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="866" data-original-width="1226" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIaw2VLapoHwU3aVWieAaV0KbBiGYqgLf2G7XP8bPiuH2zX77pj3ofKd_wewnQICPeHOtLdPssmYVqIouQyink0TqIPhnJVdY2PALCIM1a4TsGZCU-jKMNWkvBqo04St2lvSSlJZiHj0w/s400/subscriptions_2x.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://developer.apple.com/jp/documentation/DataManagement/Conceptual/CloudKitQuickStart/SubscribingtoRecordChanges/SubscribingtoRecordChanges.html#//apple_ref/doc/uid/TP40014987-CH8-SW1">CloudKitクイックスタート</a> より</div>
<br />
実はCloudKitは、Record Zoneの種類によって利用出来るSubscriptionが違う。<br />
Subscriptionを使わない場合でも、ここを理解すること、Record Zoneの設計方法が少し見えてくるはず。<br />
<br />
<br />
<h3>
Subscriptionの種類</h3>
<div>
Subscriptionには以下の3種類がある。<br />
<br /></div>
<table>
<tbody>
<tr><th>Subscription</th><th>対応する差分取得Operation</th></tr>
<tr><td>CKDatabaseSubscription</td><td>CKFetchDatabaseChangesOperation</td></tr>
<tr><td>CKRecordZoneSubscription</td><td>CKFetchRecordZoneChangesOperation</td></tr>
<tr><td>CKQuerySubscription</td><td>CKFetchNotificationChangesOperation</td></tr>
</tbody>
</table>
<div>
<a href="http://blog.sorausagi.org/2018/03/cloudkit1-databaserecord.html">第一回: CloudKit(1): DatabaseとRecord</a> で説明したように、Record Zone には Default と Custom, Shared の3つの種類がある。それらのRecord ZoneごとのSubscription利用可・不可をマトリックスにすると以下になる。</div>
<br />
<table>
<tbody>
<tr><th></th><th>Public DB</th><th colspan="2">Private DB</th><th>Shared DB</th></tr>
<tr><th></th><th>Default Zone</th><th>Default Zone</th><th>Custom Zone</th><th>Shared Zone</th></tr>
<tr><td>CKDatabaseSubscription</td><td>×</td><td>×</td><td>○</td><td>○</td></tr>
<tr><td>CKRecordZoneSubscription</td><td>×</td><td>×</td><td>○</td><td>×</td></tr>
<tr><td>CKQuerySubscription</td><td>○</td><td>○</td><td>○</td><td>×</td></tr>
</tbody>
</table>
<br />
<a href="http://blog.sorausagi.org/2018/03/cloudkit2-operation.html">前回</a>の差分の取得のところで、さらっと 「Default Zone以外」と書いた。<br />
じゃぁDefault Zone では差分取得ができないのか?<br />
Default Zoneで差分を取得するには、CKQuerySubscription を利用できる....のだが....<br />
<a href="https://developer.apple.com/documentation/cloudkit/ckfetchnotificationchangesoperation">CKFetchNotificationChangesOperation</a> が iOS11 で deprecated になってしまった。<br />
代わりにCKDatabaseSubscription, CKFetchDatabaseChangesOperation, CKFetchRecordZoneChangesOperation を使えとなっていますが、これらはDefault Zoneでは使えない。<br />
詳しい調査はしていませんが、もし方法がないのであれば、Default Zoneでの差分取得はできなくなった(?)<br />
関連: <a href="https://forums.developer.apple.com/thread/79461">Apple Developer Forum: Notifications in iOS 11</a><br />
<br />
ほかにも、<a href="https://developer.apple.com/documentation/cloudkit/ckfetchrecordchangesoperation">CKFetchRecordChangesOperation</a> がiOS10で deprecated になっているのをみると、Tokenを使ったRecord差分取得は、 CKFetchRecordZoneChangesOperation のみに限定...言い換えると、「Default Zone 以外で全件対象のみ可能」とする方向なのかもしれない?<br />
(あくまで個人の感想)<br />
<br />
以上の情報から、<br />
Private DBでデータ量が多いものは特に、Custom Zone にしておくのが無難と思った。Customは選択肢が多いので状況に合わせていろいろ選択しやすい。<br />
<a href="https://developer.apple.com/videos/play/wwdc2014/231/">2014年のWWDC: Advanced CloudKit</a> で、Custom ZoneはAtomic Commits ができるよ とも言っているし、なんか、ほかにも色々ありそうだ。<br />
そして、可能な限り、Custom Zone は複数に分けておくとよさそう。<br />
(Zoneが違うRecordを一気に更新することはできないので注意)<br />
<br />
Default Zoneを使う場合は、一回のQueryが適切な件数になるようUIやIndexをうまく設計する というところだろうか。<br />
さらに、Public DBの場合は、競合がなるべく起こらないような設計が大事そうだ。<br />
<br />
ちなみに、Record Zoneの変更があると、DatabaseSubscriptionにも通知が届く。<br />
そのため、Record Zoneの変更トリガーはCKDatabaseSubscription か CKRecordZoneSubscription のどちらかを登録していればOK。<br />
アプリ利用中にRecord Zoneが増減するのであれば、CKDatabaseSubscription を使い、CKRecordZoneSubscriptionは使わない という選択もアリ。<br />
<br />
<br />
<h3>
Subscriptionの登録</h3>
3つのSubscription、ともに、CK***Subscriptionを作成し、CKModifySubscriptionsOperation で登録していく。<br />
<br />
DatabaseSubscriptionの登録例<br />
<script src="https://gist.github.com/aqubi/d45e350ab3d2dfa43469c487ee20053c.js?file=DatabaseSubscription.swift"></script>
CKRecordZoneSubscriptionはZoneIDを、CKQuerySubscriptionは対象のRecord Type, NSPredicate(条件),タイミング(作成、変更、削除時)などを指定できる。
<br />
<br />
<br />
<h3>
通知を受ける</h3>
通常のPush通知と同様、registerForRemoteNotifications しておいて、UIApplicationのdidReceiveRemoteNotification にて取得する。<br />
<br />
通知設定の登録
<script src="https://gist.github.com/aqubi/d45e350ab3d2dfa43469c487ee20053c.js?file=RegisterForRemoteNotifications.swift"></script>
通知の受信
<script src="https://gist.github.com/aqubi/d45e350ab3d2dfa43469c487ee20053c.js?file=DidReceiveRemoteNotification.swift"></script>
<br />
Database, RecordZone のSubscriptionの受けには、<a href="http://blog.sorausagi.org/2018/03/cloudkit2-operation.html">前回の記事</a>で書いた、Tokenを使った差分の取得をすれば良い。(※1)<br />
CKQueryNotificationは、対象のRecordIDが取得できるが、通知が必ず届くとは保証されないので、そのRecordを最新にすれば全て最新の状態になるとは言えない。<br />
だが、前述したように、通知の差分を取得するためのCKFetchNotificationChangesOperationがdeprecatedになったので、差分の取得をせずCKQueryOperationで検索かけて最新になるようするのが良さそうだ。<br />
<br />
<br />
<h3>
終わりに</h3>
SubscriptionはCloudKitを理解するための大きな山場だと思う。<br />
当初、私はCustom Zoneを、「Defaultではない自由に作れるZone」 というイメージしか持っていなかったので混乱した。こんなに機能が違うのかと。<br />
この記事の内容をざっくり理解してから、ドキュメントやサンプルコードをみると理解し易いのではないかと思う。<br />
<br />
<br />
次回はShareについて書く予定!<br />
<br />
<br />
※1<br />
以下は、CKDatabaseSubscriptionで通知を受けた時、Record Zoneも一緒に反映する例としてもう少し詳しく書いたもの。長いので文中からは削除したがせっかくなのでペタリ。<br />
<br />
<script src="https://gist.github.com/aqubi/d45e350ab3d2dfa43469c487ee20053c.js?file=FetchDatabaseChanges_detail.swift"></script>
<br />
<br />
<br />
<br />Hideko Ogawahttp://www.blogger.com/profile/02007721538597371919noreply@blogger.com