2017年10月26日木曜日

Swift と Objective-C どっち選ぶ?

なぜ多くの開発者が今なお Swift よりも Objective-C を好むのか の記事を読んだ。

私は、言語にあまりこだわりがある方ではなく、使えればなんでもいいやタイプ。
そんな私でさえ、「あー、そうよなー」 と共感してしまった所があった。

WWDCのセッションでは、ほぼSwiftで書かかれているなど、Swift押しなのかなーと思う反面、Swift発表から結構経った今でもなお、上にのっかっているライブラリの位置から抜ききれていないのが悶々とする。

Swiftは、コードの文字量が減るし、GenericsやEnum, Extensionなどのおかげでスッキリと見やすいコードを書きやすい。
見やすいコードは凄く大事。複数の人数で開発していたらさらに。
多少のコンパイル速度や、実行速度を落としてでも、見やすいコードの方が優先順位は高いと思う。(便利なフレームワークを使うとか もその一例デスヨネ)

でも、一人でコードを書いている&修正している場合、ぶっちゃけ動けばOKなのだから、見やすいコード の優先度を下げても問題ない訳で。
受託案件であれば、Swiftバージョンの互換性問題を考えると、委託者の立場からするとObjective−Cで作ってくれた方が有り難いかもしれないし。

「これからのiOSアプリはSwiftで書くべし」 と人に言われたことがあるけど、私はそこまで断定して言えないなぁ。

そうはいいつつ、Flaskのアプリは3年前からSwiftです。Swift発表の直後から使い始めたので、長い方と思う。受託じゃないからできる技ですねw

速度に関しては、そこまでシビアなモノを作っていないし、デバイス性能が上がればカバーできることも多いので、そのためにObjective-Cを選択することは無いのだけど...

アプリにSwiftライブラリを含める必要がある

のが、一番ツライ。

ここでいうSwiftライブラリとは、libswiftCore.dylib など のような、これがないとそもそもSwiftが動かない必須のやつです。
Swiftのバージョンが上がるとどんどんサイズも大きくなっていく代物。

XCodeでビルドした際に作成される ○○.app の中を見ると、このSwiftライブラリ類の合計は、
  • iPhoneアプリでは35MB
  • Apple Watchアプリでは12MB
ぐらい占める。

が、これで驚く無かれ(?)
App Storeに向けたビルドとして出力すると、
  • iPhoneアプリでは100MB
  • Apple Watchアプリでは36MB
ぐらいに膨れ上がる。

Apple Watchアプリは50MBのサイズ制限があるのに、半分以上持っていかれるとか、ほんと切実すぎる。
(最近、制限が75MBにアップされたかも?)

これらのサイズは、どうやらコード内のスペースとかも含まれているサイズらしく、実際に配布される時は少なくなるようなのですが、iTCへアップロード時のWatchアプリのLimitのチェックはこれを使っている様子。


どっちの言語でも書くのは問題ないけど、後にObjective-C ←→ Swift に移行するのは、やりたくない。
とすると、これから作成するアプリであっても、ボリュームがありそうなWatch appはObjective-Cで書くのがいいか? と考えてしまう。

今後、Swiftライブラリをアプリに含めなくても良くなる (= Objective-Cと同等レベルの言語として格上げされる) 予定があるのか? ないのか? をホント、知りたい。
公表してくれると嬉しいが、オトナの事情もあるだろうし難しいんだろうな....。


• • •

2017年10月16日月曜日

iPhoneX対応

Flaskのアプリ達をiPhoneXの対応を着々と進めています。

iPhoneX向けレイアウトの条件


iPhoneX向けのレイアウトになる条件は、

  • XCode9(iOS11)でビルドしたアプリ
  • LaunchScreenがiPhoneXの対象になっている

ことらしい。
なので、XCode8(iOS10)でビルドしたアプリは、多分SafeArea部分が黒く塗りつぶされる...ハズ。
試せないので想像と期待ですが。

LaunchScreenは、Storyboardと画像Assetのどちらかを使うかを選べます。
Storyboardを使っていた場合は、対象になります。
画像Assetの場合は、iPhoneX用の画像を用意したら対象になります。


対応時に引っかかった所


Insets

画面の縦や横のサイズが変わってもピッタリとレイアウトされるようにコードからコンポーネントのサイズを変更したりしていた所の修正がいくつか必要だった。
手抜きでUIScreen.main.boundsの端末サイズから計算してたとことか、bottomLayoutGuideの量を考慮し忘れとかなど。

Insetsについては、Qiitaに記事を書いてみました。
iOS11のInsetsとLayout
誰かの助けになれば幸いデス。

Status Bar

Status Barを表示していなかったアプリも、iPhoneXだと表示したくなる。
だって、その領域が絶対にあるんですもの...!

なので、Status Bar有りに変えたアプリがいくつかあります。
ただ、やっぱり、iPhone8だと無しにしたい...というものもあって、切り分けたものもあります。
綺麗に切り分ける方法はないっぽいので、SafeArea.topがコレ以上だったら...というハードコーディングした。気持ち悪いけども、まぁしょうがないかなと。


画面下部にピッタリ置いたボタン


手が届きやすいので、画面下部にボタンをよく配置していたのですが、iPhoneXだと下にスペースができちゃうので、イマイチになってしまう。


この場合、ボタンの形状から考え直さないとなんともならなくて、左右にスペース開けて浮いた感じにしてみたり、角丸にしてみたり...とデザインの変更も。

そもそもの話として、iPhoneXは縦長なので画面下部が押しにくそうなのが悩ましい。
ぷにコンみたいなのが正解なのか。もう、ボタン無しUIへと時代は変わっていくのか...?!


Pushアニメーション時のズレ

NavigationBarが不透明だったり、Under Top Barのチェックをしていない時、UITableViewがズレてしまうという、よく話されている問題。
https://stackoverflow.com/questions/45573829/
バグであって、修正されると信じたいなぁ。このために回避のコードを入れたくない。

もう一つ、Pushアニメーション時に、TabBarが上に動いてしまうという問題がiPhoneXのみであって、これはBug Reportを書いた。

Push時のアニメーション関連は、まだ不安定な感じ。




iPhoneX対応は、制約を正しいGuideにコツコツとつなぎ直していく単純作業かと思いきや、デザイン合わないからどうしよう.... という悩みがでてくる。
iPhoneXはマイノリティだから とは思うものの、iPhoneXをメイン端末として使いたい私としては、えこひいき的に考えてしまう(笑)


あとは無事に実機をゲットできればよいのですがーー。




• • •

2017年10月2日月曜日

UIActivityViewControllerには罠がある

UIActivityViewController は画像やテキスト、URLなどを他アプリへ渡す仕組み。
Twitter, FacebookなどのSNSにシェアしてもらうときに使える。

実装はとても簡単。シェアしたいものを配列にして渡す。

let image:UIImage = ...
let shareItems:[Any] = [image,  "Hi!"]
let controller = UIActivityViewController(activityItems: shareItems, applicationActivities: nil)
present(controller, animated: true, completion: nil)

これで、以下のようなシートが表示される。


手軽なのでよく使っているのだが、罠がある。

1. 画像をシェアするときには、Usage Descriptionが必要


「Save Image」ボタンで、写真appに画像を保存できるのだが、その際にPhoto LibraryのUsage Descriptionが無いとクラッシュします。
写真appにアクセスしていないアプリだと見落としがちなので注意。

iOS10までは、Privacy - Photo Library Usage Description で読み込み/保存の両方ができましたが、iOS11からは書き込み時にはPrivacy - Photo Library Additions Usage Descriptionが必要です

Usage Descriptionは、Extension側で管理してよ と強く思います...!
「Save Image」はデフォルトで入っているものですが、3rd party appでもそうなのかどうかは試してないので不明。
どんなExtensionが使われるかはユーザ依存なので、アプリ本体側としては全部テストはできないから妥協が必要だが、ユーザー目線からみるとアプリのバグと見えるのでツライところ。

2. シェアアイテムが全て使われるとはかぎらない

アプリ本体側は、Image, Text, URLなど、シェアしたいアイテム を渡すが、それをどう使われるかはExtension次第。

たとえば、Facebookの場合、ImageとTextの両方を渡すと、Imageのみになる。
(現在の v143.0ではそうなるが、少し前のバージョンだとImageも認識されなかった)

FacebookはそもそもアプリからデフォルトのTextを入れてはダメというポリシーがあるようなので、Textは渡せない(渡さない)と考えたほうが吉。
ちなみに、Hashtag (ex. #Standland) はいけるようだ。

3. Extensionのアプリバージョンによって挙動がかわる

まぁ当たり前ではあるのですが、そういうものです。
言い換えると、実装したタイミングでは動いていたのに、今みたら動いていない...ということがあるということ。

iOS11のリリース直後はTwitterで画像のシェアができなくなった。
すぐTwitterのアプリをアップデートしてくれたので今はiOS11でできるようになったが、iOS10だと画像シェアできないようだ。 (Twitter v7.8)


4. iOS10のTwitter, Facebookはアプリ有無によって挙動がかわる

iOS10以前には、iPhone本体でTwitter, Facebookのアカウント管理機能があった(SocialFramework)。
そのため、アプリをインストールしていなくてもActivityViewControllerには表示され、シェアが可能。(これはiOS11で消滅)
つまり、iOS10で動作確認する際は、アプリインストール有無で挙動が変わるということを知っておくのが大事。



いろいろ気をつける注意するべき点はあるものの、UIActivityViewController + Extensionの仕組みはとてもいいものだと思う。

これがなければ、アプリに「他アプリへの連携機能」を付けてもらうしか無い。
マイナーアプリの場合は、連携機能を期待するのも難しいであろうし。

その代わり、使う方(本体アプリ)も、使われる方(Extension)も、正しい理解と実装をして、新しいOSにも対応し続けていかないといけない。

もし私が受託開発を請け負っている身だったら、あまり理解してもらえないようなお客さんの場合は、使うのはためらうかも...。



• • •