2019年9月15日日曜日

iOS 13, Are you ready?

Flask のアプリ、7本をiOS 13 / watchOS 6 対応をして準備完了しました!
Zones, FitPort, Standland, Cube, Timesheet, Timelet, Coyomi

OS正式リリースの前日、9月18日にリリース予定です。お楽しみに!

対応、いやー大変でした。
なにが大変だったかというと、なんかもう、いろいろ?


Localize Bug

いくつかあったのですが、最後まで様子見していたのが、テーブルセルのローカライズがされない問題。
以下の場合に発生します。
  • Storyboardの.strings ファイルを使ってローカライズしている
  • TableViewCellのStyleにBasicやRight Detailなどを利用している
結局最後のGMまでFixはされなかった。
遭遇する人は多いと思ったのだが、Feedback AssistantでReportした内容をみると、

Recent Similar Reports: Less than 10
...って、10以下って少なくね!?


Page Sheet

XCode 11でビルドして最初に気づくのが、ModalのデフォルトがPage Sheetになっていること。
iOS 12時代の形式に戻すには、Full Screen系に選択しなおしすればOK。
だけど、せっかくならPage Sheet使ってみたいなー と気軽に入れ始めたら、あれこれ引っ掛った。
  • Modalの画面からさらにModalを出していた場合の対処
  • 編集画面の場合は、変更有無をチェックして Swipe to Dismiss できない処理を追加
  • 元画面が見えている扱いなので、viewWillAppear 系の呼ばれ形が変わる。たとえば、viewWillAppearで変更内容を一括して再更新している画面(手抜き処理)が元画面の場合、小画面で変更した内容が反映されない など
  • 元画面がSceneKitの場合は、Renderingでの処理を止めてからNodeを操作するなどの考慮が必要
Page Sheetをデフォにするのは思い切ったなー と思うが、おかげで、Swipe to Dismiss する操作がみんな慣れているものになるのも早いと思う。

「Closeボタンを上に置くと操作しにくいから、下に置くか?」という迷いももう解決っす。
あ、でも、Closeボタンはちゃんとあったほうが良いです。Voice Over/Voice Control のために。

Page Sheetと同じ動きだけど、もっと高さが小さいバージョンのものが欲しくなったので作成したりした。こういうやつ。

標準でできるといいのになぁ。


Dark Mode

前回のブログで対応方法を書いた

実際に移行するときの手順は、以下のような感じになると思う。

  1. Storyboard、コードで描いている色を整理
  2. System Colors, Dynamic System Colors に置き換え可能なものを検討する
  3. 整理したものをAsset の Color Setに定義
  4. 利用画像もLight/Dark用を用意 or TintColorで切替にする
  5. Storyboard、コードの色設定をColor Setのものに変更する
  6. cgColor を使っている所は、traitCollectionDidChange や tintColorDidChange などで変更に対応する

できるだけSystem Colorsを使っていきたい所だけど、限られた中から選ぶの結構迷います。
そしてアプリ独自の色もLight/Darkで色を調整したくなってくるという...。

UILabelなどUIKitのコンポーネントに設定したDynamic Colorは、Light/Darkのモード切替時に自動的に反映してくれるけど、CGLayerなどで利用したCGColorは自前で更新する必要があります。

StoryboardのGlobal Tint Colorに、独自に作成したCustom Color Setを指定した場合、その色が他要素に使われていないとXCode再起動などで色設定が消えてしまうバグ?があります。

前からある現象だけど、StoryboardでCustom Color Setを設定している箇所にコードから色を設定しても反映されない(viewDidLoad以降にStoryboardの設定で上書きされてしまう?)ことがあります。


Voice Control, Voice Over

Voice Control がiOS 13で追加になります!

Voice Overよりも、Controlの方が対応が簡単と思うし、使いたい人も多いと思うので、Accessibilityの第一段階として取り組むのはいいと思った。

Voice Overの場合は、読ませる順番、読ませる内容、スクロールの移動、ローター使った見出し移動 など注意すべき箇所は多いのですが、Voice Control の場合は、操作できるところを明確にするだけでも助かるはず。("Show Numbers" で番号を表示して使う)
さらに、名前も整理しておくと、 "Tap [名前]" のように直接操作できるようになる。(何回も操作が必要なStepperなどでは名前がないと操作がツライ。)


Accessibility系をやりながら思ったこととしては、
まとめて読ませる括りのものは1つのViewにいれて、専用のクラスを設定するようにしておくと、やりやすいです。
accessibility***系メソッド をoverrideして書けるので。


他にも色々学んだことは多いのだけど、書くとめっちゃ長くなりそうなのでまた機会があれば。

• • •

2019年6月29日土曜日

iOS13: Dark Modeの対応方法

アプリのiOS 13対応 で、必ず通るのが Dark Mode対応。
なぜなら、Opt-out だから。

まだ iOS 13 beta2 なので、今後変わるかもしれないけど、今の知見を書いてみる。

Dark Mode にしない設定

XCode 11でビルドしたアプリを、iOS 13でみるとDark Mode対応になる。
XCode 10以下でビルドしたものは、Dark Modeにはならない。(Light Mode)

アプリ全体でModeを固定にしたい場合は、plistのUIUserInterfaceStyleで指定可能。
特定の画面でModeを固定にしたい場合は、overrideUserInterfaceStyle で指定可能。


Modeごとの色

System Color

Light / Dark でよきに変わるシステムカラーが利用できる。
Human Interface Guidelines: System Color

ラベル文字色、背景色などごとに、Primary, Secondary, Tertiary の色が用意されているので重要度に合わせて使う。
UI Element Colors

Dark ModeのときのsystemBackgroundは基本的にはUIColor.black だが、Page SheetなどのModalのときは、少し薄い黒になることに注意。

System ColorはiOS 13以上で利用可能なため、コード上で設定するにはiOS 13 以上である必要がある。
if #available(iOS 13.0, *)  {
    titleLabel.textColor = UIColor.label
}
ただ、StoryboardにてSystem Colorを設定した場合は、iOS 12でも利用可能。

Backwards compatibility for iOS 13 system colors は下位互換のための情報の良記事。

Custom Color

独自の色は、Asset CatalogでColors Set を指定して利用する。
コードから利用したいときには、UIColor(named: "colorName")  で。


Mode切替のタイミングの判定

Light / Dark は、システムによって動的に変わる場合がある。
(Settings > Display & Brightness に Automatic の切替アリ)

UIViewやUILabelなどは自動的に切り替わるので特に考慮は必要ないが、cocoa 2D などでコードで色を指定しつつ描画しているところなどは、切替のタイミングを判定して描画し直す必要がある。

切替のタイミングは、traitCollectionDidChange

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    let userInterfaceStyle = traitCollection.userInterfaceStyle
}

UIUserInterfaceStyle のEnumに、unspecified, light, dark が定義されている。

traitCollectionDidChangeはデバイスの回転などでも呼び出されることに注意。
Mode切替の場合のみ処理したい場合には、hasDifferentColorAppearance を使って判定できる。

let hasChanged = previousTraitCollection.hasDifferentColorAppearance(comparedTo: traitCollection)

Color Setの色から、現在のModeの色を取得するには、resolvedColor(with:) を使う。
let color = UIColor(named: "MyColor")?.resolvedColor(with: traitCollection)


• • •

2019年5月10日金曜日

iOSの令和元年が始まる

iOS12.3で「令和」が対応されるみたい。
(現時点で、iOS12.3はbeta 5)

これ関連で、バグを仕込んでしまっていたようで、今日は修正をしていた。

たとえば、
平成の日付: 2019-04-09 17:04:38 +0000 から、その日の0:00を求めようとしたとき。

let date1:Date = Date().addingTimeInterval(-3600 * 24 * 30) //平成の適当な日時
print("date1:", date1)

let cal = Calendar.current
let comp = cal.dateComponents([.year, .month, .day], from: date1)
let date2 = cal.date(from: comp)
print("date2:", date2 ?? "nil")

の結果は、

date1: 2019-04-09 17:04:38 +0000
date2: 2049-04-09 15:00:00 +0000

...と、30年先の日時になってしまう。
もちろん、iPhoneのカレンダーが西暦の場合は大丈夫。和暦設定にしている時のみ。


DateComponentを使った日時の計算には、Calendar(identifier: .gregorian) を使いましょう...


P.S.
0:00 の日時の算出には、CalendarのstartOfDay が使えます。
• • •

2019年2月25日月曜日

XCodeでアプリアップロード中に“negotiating connection…”になる

XCode10 でアプリをアップロード中に、“negotiating connection…” で止まってしまう。

Stack Overflowでも同じ現象になっている人がいる。
Xcode 10 app upload stuck on “negotiating connection…”

Application Loaderを使えばうまくいく。
Application Loader/Xcode Stuck on 'Verifying Assets with the App Store"

でも、Loaderを使うのは面倒だし、XCodeでやりたい。
原因も気になる...

Loaderを使う回避策にあるように、どうやら原因はネットワークにあるみたい。
自宅のネットワーク使うとダメだけど、iPhoneのテザリングでやってみると成功した。

自宅のネットワークの設定をナニカいじるといいのかなぁ。
詳しい人教えてほしい...

• • •

2019年2月11日月曜日

iOS11のColorSet

iOS11からAsset CatalogにColor Setを指定できるようになりました。

この設定をすると、Storyboardとコードの両方で利用できるのでとても便利。

Storyboard上では以下のように選択肢が現れます。

コード上では UIColor(named:"ColorName") で使えます。

だが! 問題点が。

StoryboardでColor Setの色をしていると、viewDidLoad() よりも後にその設定が反映されるみたい。(iOS12で確認)
つまり、viewDidLoad() でコードから色の再設定していてもそれが反映されない。
traitCollectionDidChange で設定してもダメなので、結構遅いタイミングの様子。

なので、コードで色を再設定する箇所には、StoryboardでColor Setは使わない としたほうが良さげ。
iOSのバグなのかな?と思うので、今後修正されるかもしれないが、お気をつけくださいー。


• • •

2019年1月23日水曜日

Hops - 木霊の旅 リリースしました!


Hops -木霊の旅 をリリースしました!
日々を活動的に過ごすと、いろいろなエリアに行けたり、着せ替えができるようになります。

Standland では、スタンド数 のみが対象でしたが、Hopsでは、歩数、階段数、カロリー など対象が増えています。
Standlandでスタンドが習慣化できたら、次はHopsで動くことを習慣にしていこう! という目的のアプリです。

ランニングしたり、ジムに行ったりしなくても、エスカレータじゃなく階段を使ったり、ひと駅あるいてみたり と、普段の生活でちょっと動くことを意識するだけで随分違う。

私の経験談では、ダイエットしなきゃ!と頑張って運動して毎日体重測るけど、思ったより体重減らない...とイライラしたことがあるが、動くことを意識してゆるく生活したたら、いつのまにか体重減ってた ってことが結構ある。

運動しなくちゃいけないんだけど、忙しくてジムにもいけないわーー という人、ぜひお使いくださいませ!



内部のお話

Standlandと同じく、SceneKit で3Dモデルが動いていますが、Standlandでは入れれなかった機能がいろいろ入っています。


DOF

DOF(被写界深度)が生きていて背景がぼやけて素敵になっています。
これは重い処理なのですが、入れれるように頑張りました( @horiuni さんが )
なので、全てののエリアを是非見て欲しいー!


キャラを動かせる

キャラを自分で動かせます。
最初は歩くのが遅くてちょっとイラっとするかもしれないのですが、SPEED値を上げていくと早くなるので、ぜひ上げてみてください。
歩くアニメーションですが...

SPEED 0 (遅い)の時 はのっしのっし歩きます。


SPEEDが早くなっていくにつれ、前傾姿勢でバタバタ走ります。


この実装には、遅い用、早い用のアニメーションを2つだけ用意し、iOS11 で追加された SCNAnimationPlayer のblendFactorとspeedの値を調整してしています。

歩く音も入れているのですが、これもAnimationPlayerのおかげでとても簡単。
SCNAnimationのanimationEventsに音を鳴らす処理をいれておけば、Playerのspeed値に合わせてEventの発生タイミングも変わってくれるから。
あー、AnimationPlayer ラブ❤


他には、カメラをいくつか用意して切り替えしてみたり、カメラの Color Grading いれてみたり。
SceneKitってiOS11で随分変わったので、Standlandでは入れれなかった事が結構あったのですw


...ということで、ぜひ Hops をお試しください!
そして、なにがバグがありましたら、Feedbackのメールを頂けるととても助かります m(_ _)m







• • •