MapKitの地図をGoogleMap風にカスタマイズする
簡単に現在地の周辺や特定の場所を表示したりするだけならGoogle Map SDKを使えば良さそうなんですが、
アノテーションを充実させたり、検索機能が必要だったりするとMapKitを使う方がベターだったりします。
(知ってる限りではGoogle Mapでの検索はPlace APIで課金が発生する)
とはいえUberみたいなイケてる地図を表示したいという要求がデザイナーから来ることも無きにしも非ず。
そういう場合は、後述する方法でMapKitのメリットを享受しながら見た目だけGoogle Map風に変更する、のが一つの手かと思います。
方法
MapKitの地図はオーバーレイの画像をMKTileOverlay
で指定することができるようになっているのでそれを加工します。
MKTileOverlay - MapKit | Apple Developer Documentation
私は今回調べるまで聞いたこともなかったんですが、タイルオーバーレイというのは地図のタイル(小さい単位の区域)を表示する際にタイルのデータを(サーバから)取得して地図の上に表示する仕組みのようです。
タイルのデータの取得先は自分でホストしたり以下のようなプロバイダーからAPIで取得したり、といった感じ。
Tile servers - OpenStreetMap Wiki
Google Maps APIs Styling Wizard
このタイルオーバーレイの仕組みを利用してGoogle Map風のタイルを取得するSDKがこちら👏
Googleが提供しているGoogle Maps APIs Styling Wizardを利用してタイルデザインのJSONファイルをまずは自分で作成しSDKに渡します。
SDKはそのJSONファイルのパースして、Googleのタイルサーバへとリクエスト、取得したタイルの表示までしてくれるようです。
Snazzy Maps
Styling Wizardを利用して自分好みのタイルデザインを作ることも可能ですが、
クールでセクシーなデザインがまとまっているサイトがあるので、そちらから気に入ったものを選ぶこともできます🤩
参考
色々と調べる中で以下のブログを見つけ、まさにこれだ!となりました。感謝。
Xcode 10でビルドしたアプリがiOS 9.0, 9.1, 9.2 でクラッシュしまくる件について
先日ようやっとiOS 12とXcode 10リリース後初のiOSアプリリリースをキメたんですが、
その後最新バージョンでクラッシュが急増する事態に。。。
クラッシュログを確認するとiOS 9でしか発生していない模様。
不思議だな〜と思いつつコード追ってみても原因がよく分からない。
諦めてググってみたところどうやら同様のクラッシュ事件でstackoverflowが盛り上がってる。
質問やそれに対するコメントをざっくりまとめてみると、
- Xcode 10 GMでビルドしたアプリがiOS 9でクラッシュするぜ
- Appleがバグと認定してる(バグチケットの作成を促している)
- iOS 9.3未満で発生する
- 何年もコードと画像を変更してなかったアプリでXcode10にした途端
[UIImage imageNamed:]
でクラッシュする - Xcode 9でビルドしたら正常に動作する
well done,but It‘s unpractical for us.I think it is the xcasset's problem always.Xcode 10 release note and wwdc said xcassets has been optimized,it is a joke
hahaha
Swift 4.2 対応したばっかだしXcode 9に戻すのは気が引ける&iOS 9ユーザ多くないし静観するか〜と思っていた矢先、朗報。
Xcode 10.1 beta 2 Release Notes | Apple Developer Documentation
Resolves an issue that affected app compatibility with iOS 9.0, 9.1 and 9.2. Apps containing asset catalogs built with Xcode 10 whose deployment target was set to iOS 9.0, 9.1 or 9.2 would produce content incompatible with the runtimes of those iOS versions. Rebuilding the application with Xcode 10.1 resolves this issue. (44535967)
アセットカタログを含むデプロイターゲットiOS 9.0, 9.1, 9.2アプリがXcode 10でビルドされると、ランタイムと互換性のないコンテンツが生成される。Xcode 10.1で解決する
めでたし、めでたし。
モバイルアプリエンジニアのポートフォリオサイト「Project Showcase BETA」を試してみた
先日メールボックスにこのようなメールが。
Hey Toru,
I was searching for mobile developers by diving into the Swift stargazers on Github and came across to your profile. I see that you are a productive developer, especially CleanArchitectureChat is a great example. I believe you may find it useful to have a portfolio website to showcase your projects which I can help with.
スターゲイザーでは決してないのでどんなBotで引っかかったんやとは思いつつ、
How? I'm a founder of a startup that develops an online portfolio creator, called Project Showcase. It is especially designed and built for mobile developers. If you have any interest on mobile application development or if you have any application in the Play Store or App Store, you can exhibit them in your portfolio. It's so easy to use, you should give it a try.
Project Showcaseというサービスの宣伝でした。アプリエンジニアのポートフォリオって今までありそうでなかった気がするので気になって登録・利用してみたので紹介です。
管理画面はこんな感じ。
アプリエンジニア専用ということはなさそうですが、AppStoreとPlayStoreからアプリデータを取得してプロジェクトとして登録できる機能が中心となっているので、アプリエンジニアにとってはぽちぽちとするだけで今まで自分が作ったアプリがずらっと並んで見応えあるサイトになると思います。
ただ現状はアプリ検索に制限があります。
AppStoreに関してはiTunesの検索APIを利用してるのですが"country"パラメータをクエリに含んでいないためデフォルトのUSがアプリの配信対象に入ってないと検索に引っかかってくれません。
PlayStoreに関してはGoogleがAPIを提供していないようで、Project Showcaseチームが自分たちでホストしてるAPIを利用してるようです。なので中のロジックは皆目検討つきませんが、こちらも日本で配信してるアプリは検索結果に出てきてくれませんでした。
まだBETAなのでこれからの改善や機能追加に期待ですね。
こちらが私のポートフォリオです。
iOS 12で劇的に変わるPush通知の全貌
今更ですがWWDC2018のkeynoteを仕事と銘打って業務中に見まくっています。
WWDC 2018 - Videos - Apple Developer
数ある新機能の中でもiOS 12で劇的に変わりかつ影響範囲が大きい機能といえば「Push通知」ではないでしょうか。
今回はそんなiOS 12のPush通知についてまとめてみます。
- Provisional Authorization
- Grouped Notification
- Customize in App
他にもCritical Alertや通知のUI周りのトピックなどありますが今回は割愛します。
Provisional Authorization
今回紹介する3つの新機能の中でも目玉機能かと個人的には思っています。
今までPush通知の送信許可をユーザに要求する方法といえば、アプリを初めて開いた途端にダイアログを表示して要求したり、何かしらPush通知の内容紹介をしてから要求したりといったケースが一般的でした。
この今までの方法では実際にどんな通知が送られてくるか分からないのにユーザが判断を迫られるというある意味無謀な要求をしていました。
ところがiOS 12ではとうとうこの旧態依然とした機能にメスが入りました。
Provisional Authorizationはユーザにダイアログで許可を要求するのではなく、1通目のPush通知を勝手に送信してその時点で今後も通知を受け取りたいかどうか判断してもらうことができるようになる機能です。
この方法ならばユーザが実際に通知を見てから判断するためとても理にかなっています。
もしかしたらPush通知の認可率も今までに比べて向上するかもしれませんね。
実装方法
UNUserNotificationCenterのrequestAuthorization(options:)
のオプションに.provisinal
を追加するだけです。
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound, .provisional])
Grouped Notification
Push通知がグルーピングされて表示されるようになります。
Push通知のペイロードに任意のデータとしてthread-id
が追加され、グルーピングはこのID単位で行われます。
thread-idを指定しない場合はアプリ単位でグルーピングが実行されます。
ユースケースとしては例えば重要な通知がグルーピングされて隠れないようにするために別のthread-idを指定したり、通知の種類ごと(メッセージの受信といいね等)にthread-idを分けたりでしょうか。
ただ注意点として、たとえthread-id
を指定して通知を送信したとしても、ユーザのiOS設定で「通知のグループ化:App別」になっている場合はアプリ単位でグルーピングされてしまいます。デフォルト設定は「自動」になっているみたいです。
実装方法
前述した通り、Push通知のペイロードにthread-id
パラメータを指定することで実現できます。
Customize in App
iOSの設定アプリもしくは実際の通知からアプリ内の通知設定画面を開けるようになります。
例えば通知の種類がいくつかありそれぞれに対してON/OFFを選択できるようなサービスにおいて、OFFにするための画面(iOS設定アプリや実際の通知)にアプリ内設定画面への導線を置くことで全ての通知をOFFにされるのを避けられることが期待されます。
実装方法
keynoteではDelegateメソッドさえ実装していればあとはOSが勝手に導線を作ると言っていますが、嘘ですlol
まずはUNUserNotificationCenterのrequestAuthorization(options:)
のオプションに. providesAppNotificationSettings
を追加します。
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound, .providesAppNotificationSettings])
そしてUNUserNotificationCenterDelegateのuserNotificationCenter(_:openSettingsFor:)
を実装して該当のアプリ画面を表示します。
Cloud Firestore iOS SDKをCarthageで組み込むとクラッシュするあなたへ
何も変えずにCarthageからCocoapodsに変更したら動いたのでやっぱ何かおかしい
— 無職に至りたい (@toru_furuya) August 20, 2018
コード
SDKの組み込みはCocoaPodsかCarthageかの違いだけで、あとは全て公式ドキュメントの通りに実装していきました。
Get started with Cloud Firestore | Firebase
import Firebase FirebaseApp.configure() let db = Firestore.firestore() // Add a new document with a generated ID var ref: DocumentReference? = nil ref = db.collection("users").addDocument(data: [ // Crash here!!! "first": "Ada", "last": "Lovelace", "born": 1815 ]) { err in if let err = err { print("Error adding document: \(err)") } else { print("Document added with ID: \(ref!.documentID)") } }
ところがaddDocument()
で実際にDBへ書き込みを行う時点でクラッシュが発生してしまいました。writeではなくreadだったらどうかと思い別のAPIも試しましたが同じ結果でした。エラーログにも特にヒントとなるようなログは見つけられませんでした。
原因
FireStoreのSDKはリソースバンドルを含んでいて、そのバンドルをアプリに組み込む必要があるようです。Firebase iOS SDKのgithubレポジトリのCarthage.mdにちゃんと書いてありました。ビルド設定を色々調べたりリンクするライブラリが足りないんじゃないかと悩んで1時間ほど無駄にしたのが情けない。
firebase-ios-sdk/Carthage.md at master · firebase/firebase-ios-sdk · GitHub
If you're including a Firebase component that has resources, copy its bundles into the Xcode project and make sure they're added to the
Copy Bundle Resources
Build Phase :
- For Firestore:
-./Carthage/Build/iOS/gRPC.framework/gRPCCertificates.bundle
私と同じようなズボラな方の役に立てれば幸いです。
SideMenuライブラリでツールバーの見た目を変更できない原因と解決方法
問題
アプリ側のステータスバーの見た目とSideMenuで表示するメニュー側のステータスバーの見た目を変えるために、以下のような実装を行なった。
import SideMenu let menuLeftNavigationController = UISideMenuNavigationController(rootViewController: MenuViewController()) SideMenuManager.default.menuLeftNavigationController = menuLeftNavigationController SideMenuManager.default.menuWidth = 280 SideMenuManager.default.menuPresentMode = .viewSlideInOut
class MenuViewController: UIViewController { override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } }
しかしMenuViewControllerのpreferredStatusBarStyle
は実行されず、期待した動作にならなかった。
原因
SideMenuのコードを読んでみると、SideMenuManagerにNavigationControllerをセットしたタイミングで、そのNavigationControllerのmodalPresentationStyle
が.overFullScreen
に変更されてしまっていた。
fileprivate func setupNavigationController(_ forMenu: UISideMenuNavigationController?, leftSide: Bool) { guard let forMenu = forMenu else { return } forMenu.transitioningDelegate = transition forMenu.modalPresentationStyle = .overFullScreen forMenu.leftSide = leftSide ...
公式ドキュメントによると、ViewControllerをpresent(_:animated:completion:)
で表示する時、ステータスバーの見た目のコントロールは表示する側から表示される側に移る。ただし表示される側のmodalPresentationStyle
が.fullScreen
の時だけね🤪
When you present a view controller by calling the present(_:animated:completion:) method, status bar appearance control is transferred from the presenting to the presented view controller only if the presented controller's modalPresentationStyle value is UIModalPresentationStyle.fullScreen.
modalPresentationCapturesStatusBarAppearance - UIViewController | Apple Developer Documentation
解決法
SideMenuのNavigationControllerのmodalPresentationCapturesStatusBarAppearance
をtrueに設定する。
// modalPresentationStyle become .overFullScreen as set to menuLeftNavigationController. // Set this property true in order to make sure that status bar appearance control // is transferred from the presenting to the presented view controller. menuLeftNavigationController.modalPresentationCapturesStatusBarAppearance = true
こうすることでMenuViewControllerのmodalPresentationStyle
の値に関わらずoverrideしたpreferredStatusBarStyle
が実行されるようになり期待した動作になる。
Travis CIのxcode9.4イメージにbundlerがプリインストールされてない模様
Travis CIのosx_image: xcode9.4
がリリースされたので試してみました。
✨Xcode 9.4 is here! 🚀Set ‘osx_image: xcode9.4’ in your .yml file and you’re off to the races. As always, if you have any questions or something doesn’t work as expected, we can be reached at support@travis-ci.com Read more here: https://t.co/kxZyIa8iJw
— Travis CI (@travisci) 2018年6月15日
しかしbefore_install
でエラー発生。どうやらbundlerが見つかってない模様です。osx_image: xcode9.3
までは正常に動作していたのですが、9.4にしただけでビルドがこけるようになってしまいました。
$ sudo bundle install /Users/travis/.rvm/rubies/ruby-2.4.3/lib/ruby/2.4.0/rubygems.rb:271:in `find_spec_for_exe': can't find gem bundler (>= 0.a) (Gem::GemNotFoundException) from /Users/travis/.rvm/rubies/ruby-2.4.3/lib/ruby/2.4.0/rubygems.rb:299:in `activate_bin_path' from /Users/travis/.rvm/gems/ruby-2.4.3/bin/bundle:23:in `<main>' from /Users/travis/.rvm/gems/ruby-2.4.3/bin/ruby_executable_hooks:15:in `eval' from /Users/travis/.rvm/gems/ruby-2.4.3/bin/ruby_executable_hooks:15:in `<main>' The command "sudo bundle install" failed and exited with 1 during .
公式ドキュメントのプリインストールされてるGem一覧には変わらずbundlerも含まれています。
The OS X Build Environment - Travis CI
- bundler
- rake
- cocoapods
ということでGithubにissue作りました。どんなカンバセーションがされるでしょうか。
追記
時間がかかりましたが、Travisのissueで返答がありました。
root
ユーザではbundlerが使えなかったみたいです。ということでsudo bundle install
からbundle install
に変更すればokでした。
osx_image: xcode9.4 doesn't have bundler · Issue #9759 · travis-ci/travis-ci · GitHub