- 投稿日:2020-03-22T20:47:41+09:00
Flutterでflutter_app_badgerを使い、アプリのホームアイコンにバッジを表示する
Flutterでアプリ開発をしている村松龍之介と申します。
(仕事ではiOSアプリのネイティブアプリ開発を行っています)今回は、FlutterアプリにiPhoneやiPadではお馴染みのアイコンバッジを付けるためにパッケージを導入しましたので備忘録です。
flutter_app_badgerパッケージを導入する
簡単にアイコンバッジを付けられるパッケージがありますので、導入します。
flutter_app_badger | Flutter Packagepubspec.yamlを編集
dependencies: # 〜〜省略〜〜 flutter_app_badger: ^1.1.2 # 導入時点で最新のバージョンを指定でOKだと思います。iOS
iOSでバッジを表示するためには権限が必要なので以下を
info.plist
に追記します。Android StudioやVS Codeで
info.plist
を開いて編集する場合<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <!-- ここから下を追加 --> <key>UIBackgroundModes</key> <array> <string>remote-notification</string> </array> <!-- ここまで --> </dict> </plist>Xcodeで
info.plist
を(Property Listとして)開いて編集する場合
Required background modes
を追加して、その一要素としてApp downloads content in response to push notifications
を追加します。Android
On Android, no official API exists to show a badge in the launcher. But some devices (Samsung, HTC...) support the feature. Thanks to the Shortcut Badger library , ~ 16 launchers are supported.
(翻訳)Androidには、ランチャーにバッジを表示する公式のAPIはありません。ただし、一部のデバイス(Samsung、HTC ...)はこの機能をサポートしています。 Shortcut Badgerライブラリの おかげで、 最大 16個のランチャーがサポートされます。Androidの場合は、対応する機種が限られますが、特にやらなきゃいけないこともないようです。
ちなみにPixel 3 Xlではバッジは表示されませんでした。コード実装
バッジの表示・数字の更新
実装は思いのほか簡単です。
intを引数にして以下の関数を呼び出すことでバッジを表示できます。FlutterAppBadger.updateBadgeCount(1);上記の例では「1」を渡しているので、ホーム画面のアイコンに❶というようにバッジが表示されます。
doubleの場合はintに変換してから引数に渡しましょう。
0以下の数値を渡すことでバッジが表示されないことを確認しました。
マイナスの数値を渡してもバッジが表示されません。バッジをサポートしている環境か調べる
Androidでは一部のデバイスしか対応していないこともあり、あらまじめバッジ機能をサポートしているか調べた方が良いですね。
FlutterAppBadger.isAppBadgeSupported();上記の関数を実行することで、非同期で真偽値(bool)が返却されます。
上記の実装をメソッドにするなら以下のような感じでしょうか?
/// 1以上の数値を渡すことでホーム画面のアイコンにバッジを表示する void setIconBadge({int number}) async { // バッジ表示機能に対応している場合のみ、バッジの数字を更新する if (await FlutterAppBadger.isAppBadgeSupported()) { FlutterAppBadger.updateBadgeCount(number ?? 0); // <-引数の`number`が`null`だった場合は`0` } }iOSの場合、許可を得る必要がありますが、バッジの初回更新時に表示してくれます。
バッジを非表示にしたいとき
0以下の数値で更新することもできますが、意図的にバッジを非表示にしたいときは以下の関数でバッジが消した方が良さそうです。
FlutterAppBadger.removeBadge();呼び出す場所
基本的に好きな場所で呼び出して良いかと思います。
僕の場合は、アプリのメイン画面で有給休暇の残日数を計算しており、バッジでその残日数を表示させたかったので、計算結果を引数に入れて使用しました。蛇足
ご覧いただきありがとうございました!
蛇足ですが、Flutterアプリをリリースできたので良かったらインストールしてみてもらえると嬉しいです?♂️
iOS: 「レストル-有給休暇管理」をApp Storeで
Android: レストル-有給休暇管理 - Google Play のアプリ
- 投稿日:2020-03-22T20:03:10+09:00
「画面遷移で画面が浮く」を解決
開発環境
Xcode: Version 11.3.1
記事記入時: 2020/03/22解決したい問題
・以前までは,画面遷移がうまくできていたのに!
・動画等,教材通りにならない!↑のように画面遷移を実装した際に,
遷移後の画面が浮いたみたいになってる......ViewController.swiftoverride func viewWillAppear(_ animated: Bool) { ~ ~ }が正常に作動しない.
解決方法
画面遷移では
・「control」+ドラッグ
・Present Modally
で実装する場合について書いていこうと思います!この際に,Transitionを指定してやることで解決できました.
まずは,storyboard上のsegueを選択します.
そして,右の野球ベースみたいなところを選択すると,
PresentationがSame As Destinationになってるかと思います.
このデフォルト設定を Full Screen にしてやることで無事解決しました!すると!
そして,,,
ViewController.swiftoverride func viewWillAppear(_ animated: Bool) { ~ ~ }が作動しない問題も,Presentationがデフォルトだと画面が遷移してない状態なので,作動していなかったのです!
PresentationをFull Screenにすることでこの問題も無事解決しました!
これで無事画面遷移を実装できましたね!
- 投稿日:2020-03-22T20:03:10+09:00
「画面遷移で画面が浮く」を解決(swift_xcode)
開発環境
Xcode: Version 11.3.1
記事記入時: 2020/03/22解決したい問題
・以前のバージョンまでは,画面遷移がうまくできていたのに!
・動画・記事等,教材通りにならない!↑のように画面遷移を実装した際に,
遷移後の画面が浮いたみたいになってる......ViewController.swiftoverride func viewWillAppear(_ animated: Bool) { //code記述 }が正常に作動しない.
解決方法
画面遷移では
・「control」+ドラッグ
・Present Modally
で実装する場合について書いていこうと思います!この際に,Transitionを指定してやることで解決できました.
まずは,storyboard上のsegueを選択します.
そして,右の野球ベースみたいなところを選択すると,
PresentationがSame As Destinationになってるかと思います.
このデフォルト設定を Full Screen にしてやることで無事解決しました!すると!
見事,画面遷移後もスクリーンがきれいになりました!
そして,,,
ViewController.swiftoverride func viewWillAppear(_ animated: Bool) { //機能 }が作動しない問題も,Presentationがデフォルトだと画面が遷移してない状態なので,作動していなかったのです!
PresentationをFull Screenにすることでこの問題も無事解決しました!
これで無事画面遷移を実装できましたね!
- 投稿日:2020-03-22T19:04:40+09:00
Swiftで簡単なコードを書いてみた(初心者向け)
はじめに
アプリ開発に最近興味を持ち始めSwiftについて勉強したことのアウトプットとして書きました
初心者向けの簡単な文法や記述方法について触れていますSwiftって?
誰もが圧倒的に優れたアプリケーションを作れる、パワフルなオープンソースの言語です(Appleサイトより)
主に下記アプリの基幹言語として使用されています
・iPhoneアプリ
・OSXアプリ
・Apple Watchアプリ
・tvOSアプリ環境構築
WindowsやLinuxでもSwiftは動かすことは出来ますが、やはりMacを使用するのが適しています
また、実際に開発を行うのは「XCode」というソフトを使用します詳しくは下記サイトで環境構築をしてみてください
XcodeとSwiftを使ってアプリ開発を体験してみよう実装
Xcodeをインストール後、以下の画面が表示されるので、今回はplaygroudを使用していきます
playgroudは名の通り、遊び場のように作ってはすぐに実装の確認をすることが出来ます
Single Viewを選択し適当な名前を付けます
初期の起動時に、自動的にHello Worldを出力するソースがあるので、とりあえず実行してみました
実装の確認を同一の画面で確認出来ることが分かると思います
簡単な記述方法
それでは簡単なコードをSwiftで記述していきます
1.文字の出力
print("Hello Swift") //実行結果 //Hello Swiftと記述することでテキスト出力します(改行あり)
Java等に比べると、シンプルに記述可能です2.if文
var num = 1 if num < 10 { print("10より小さい値です") }else{ print("10より大きい値です") } //実行結果 //10より小さい値ですvarで変数を定義し、if文で判定を行っています
ちなみに、変数numにカーソルを当てQuick Helpというツールを使うと自動的に変数の型を明示してくれます。これも便利ですね
3.for文
for n in 1...5 { print(n) } //実行結果 //1 //2 //3 //4 //51から5までの繰り返しを記述します
こちらも独特な書き方ですが、分かりやすいです4.while文
var cnt = 0 var sum = 0 while cnt < 5{ cnt += 1 sum += cnt } print("cnt:\(cnt)") print("sum:\(sum)") //実行結果 //cnt:5 //sum:15終わりに
ここまで読んで頂きありがとうございました
今回は簡単なSwiftの記述方法に触れましたが、他の言語と比べ書き方が相違する所はありますが、簡略して書けるのではと思います
これからもSwiftについて勉強していこうと思います
- 投稿日:2020-03-22T10:50:11+09:00
[iOS] [Xcode] WKWebViewで位置情報を取得するコンテンツをloadする
前提環境
- Xcode 11.3
- Swift 5.1
info.plistの設定
謎の挙動
許諾アラートで「OK」をtapして、WKWebViewをいったん閉じて、再度WKWebViewを開いてもまた許諾アラートが表示されます。
2回目の「OK」で記憶されて、3回目は表示されなくなるようです。
この挙動の原因と回避方法は謎です。。。どなたかご存知でしたら教えてください。注意点
Xcode 11.3で新規作成したプロジェクトでは、コンテンツが位置情報を取得しようとした際にコンソールに以下のログが出力されてクラッシュします。
*** Terminating app due to uncaught exception 'NSObjectNotAvailableException', reason: 'UIAlertView is deprecated and unavailable for UIScene based applications, please use UIAlertController!'許諾アラートが表示されるタイミングで、Xcode 11で新規にプロジェクトを作成した時のデフォルトである「scene baseアプリケーション」の場合にクラッシュしてしまうようです。
許諾アラートはアプリ側で実装している訳ではないので、どうやらSDKのバグっぽい雰囲気です。
Xcode 11.3現在では、window baseアプリケーションにするしかなさそうです。1.SceneDelegate.swiftをファイルごと削除
2.AppDelegate.swiftを修正
import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? // この行を追加 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } // ここから下を削除 // // MARK: UISceneSession Lifecycle // // func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { // // Called when a new scene session is being created. // // Use this method to select a configuration to create the new scene with. // return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) // } // // func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) { // // Called when the user discards a scene session. // // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. // // Use this method to release any resources that were specific to the discarded scenes, as they will not return. // } }3.info.plistから"Application Scene Manifestを削除
この件については、Xcodeがバージョンアップされたら再確認しようと思います。
- 投稿日:2020-03-22T09:11:25+09:00
プロジェクトにfastlane?を導入する際の手順をまとめてみた
本記事の目的
本記事はfastlaneの使い方や詳細を說明するものではなく、fastlaneの導入手順をまとめたものです。
fastlane・match・pemの導入にあたって記事を転々とすることが度々あったのでまとめてみました。
(※詳しいことは公式ドキュメントや参考になる記事を掲載させて頂いているのでそちらからご確認ください。)本記事でわかること
以下の手順をまとめました
fastlaneの初期設定→fastlane match・pemの組み込み→基本的なfastlaneの使い方細かい事は以下です。
- プッシュ通知の証明書周りの自動生成
- 証明書とプロビジョニングファイルの自動生成とチームでの共有
- ipaファイルの作成とAppleStoreへのデプロイ自動化初期設定
Gemfileを作成しよう
cocoapodsのバージョン管理にも便利なGemfileを用いてfastlaneをインストールします。
Gemfileとは?って人はこちらのわかりやすい記事よりディレクトリはプロジェクトがある階層です
bundle initこれでGemfileが生成されます。
そしてGemfileを修正しますGemfileLearn more or give us feedback # frozen_string_literal: true source "https://rubygems.org" # git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } # この行を追加 gem 'fastlane' # gem "rails"そしてインストールする
bundle install --path vendor/bundleこれで準備が整いました。
fastlaneを導入
ディレクトリは変わらず
bundle exec fastlane initこれで、/fastlaneができたので移動します
中には、AppfileとFastfileが作成されています。
ファイルの說明や詳しいことを知りたい人はこちらの記事を!次に、Dev Portal と App Store Connect の両方に新しい iOS アプリを作成する必要があるので、以下のコマンドを使用します。
bundle exec fastlane produce -a アプリのBundleID(プロジェクトをXcodeでひらいいて確認できます)他にもFastlaneでlaneを使用する方法もあるのですが、今回は直接作成しました。
これが成功したら、Appfileを開いて編集して保存します。
app_identifier("アプリのBundleID") apple_id("AppleDeveloperに登録してあるメールアドレス")Push通知の証明書周り
push通知を実装する場合に必要なAPNs証明書を周りもfastlaneで解決していきます
(関係ない人は飛ばしてオッケーです)
まず、そもそもAPNs証明書を手に入れるまでの工程を知らない人は下記のサイトなどをみてみてください。
色々ポチポチする場所やわかりにくい用語が多いと気づくはずです。(記事自体はめっちゃわかりやすいです!)
https://qiita.com/natsumo/items/d5cc1d0be427ca3af1cbこれをfastlane pemで解決していきます。
gem install pemインストールを終えたら、以下のコマンドを
pem -a [app_identifier] -u [ Apple ID]これが完了したら
fastlaneのディレクトリ内に「~.p12」ファイルができています!
また、Devcenterにいけば証明書もできていますし、IDとも紐付いているのが確認できると思います!!!!!!このp12ファイルをプッシュ通知配信用サーバー、例えばFirebaseなどに配置してあげれば完成です。
ほかにもたくさんのオプションがあるようなので是非用途に合わせて使ってみて下さい。
https://docs.fastlane.tools/actions/pem/fastlane matchで証明書の作成と管理を行う
次に、リリースの際やチーム開発において複雑な作業である
- コード署名証明書の作成・更新・共有
- プロビジョニングプロファイルの更新
を fastlane match で解決していきたいと思います。こちらの記事が大変わかりやすかったので参考にさせて頂きました
fastlane match を使用して iOS の証明書管理を行うXcode プロジェクト設定とプライベートリポジトリを作成
証明書作成に入る前に、
Xcode プロジェクト設定「 General > Automatically manage signing 」を無効にしておきます。また、Gitでプライベートリポジトリーを作成しURLを取得しておいてください。
プライベートリポジトリ名は「プロジェクト名_Certificate」みたいな感じで良いと思います。fastlane matchの導入
初期設定を行います
fastlane match init実行すると以下の質問があるので
1のgitを選択し、gitのURLを聞かれるので先程作成したプライベートリポジトリのURLを打ってください。それが終ると、Matchfileが作成されるので以下の用に修正して下さい。
Matchfileapp_identifier("アプリのBundleID") username("AppleDeveloperに登録してあるメールアドレス") # Your Apple Developer Portal usernameそしてそれが完了したら、証明書とプロビジョニングファイルを作成します。
以下のコマンドをうつと//以下のうち該当するものを使用してください fastlane match development fastlane match adhoc fastlane match appstoreGit リポジトリへのパスフレーズが聞かれるので、パスワードを作成しメモしておきます
それが終われば、後は自動的に作成されリポジトリにもプッシュされています!!!!
これで面倒な作業をせずに証明書周辺を終えることができました。リポジトリから証明書を取得したい場合などの方法はこちらを参考にしていただけますと可能です
fastlane match を使用して iOS の証明書管理を行うAppleStoreへのデプロイ
次は、ipaファイルの作成・スクリーンショットの作成・AppleStoreへのデプロイなどを自動化させていきます。
といっても私がゼロから説明するよりも大変参考になる記事があるのでそちらを参照して下さい。Applestoreにコネクトする際に認証エラーが起こった際には環境変数を設定して下さい
- https://qiita.com/koringo2/items/5ba4ba7b4bc0d8557bc0
- https://qiita.com/uhooi/items/b317c3a9af92f86f5c3b
slackとの連携
fastlaneでデプロイしたあとにSlackに通知がいくようにすると便利なのでそれの設定方法も記載します
まずは下記サイトを参考にwebhookのURLを取得して下さい
slackのIncoming webhookが新しくなっていたのでまとめてみた
https://qiita.com/kshibata101/items/0e13c420080a993c5d16URLを取得ができたら環境変数を設定しておきます
//envの一覧を確認する printenvターミナルexport SLACK_URL="webhookのURL".env.defaultにSLACK_URLの定義が追加されているか一覧で確認する。
そしてFastfileにlaneを追加します。なにをしているのかは見ればわかるはずです。
Fastfileafter_all do |lane, options| slack( default_payloads: [], message: "#{lane} #{options} All OK!", ) end error do |lane, exception, options| slack( message: exception.message, success: false ) endおわりに
ということでfastlaneの導入手順をまとめてみました。
CI/CD系の環境構築は最初に組み込むべきですね、、、!
- 投稿日:2020-03-22T02:28:35+09:00
【個人開発】個人の予算を管理するiOSアプリを作った
はじめに
先日、個人の予算を管理するアプリ「クイック予算」をリリースした。
この記事ではこのアプリを作ったきっかけや、どのように開発したのかを書こうかなと。開発のきっかけ
普段iOSアプリを開発しているのに、そういえば自分でアプリを作成してリリースしたことがなかったのでまず作ってみたかったのがきっかけ。
ただ、どうしてもネタが見つからずそこで嫁さんにどういうアプリが欲しいのかをヒアリングして出てきたのが今回の予算を管理するアプリ。具体的な要望をまとめると以下の2点のみ
- 年間単位で予算を組んで、その予算内で支出を抑えたい
- 既存のよくあるアプリは月間で収支を記録するので向いてなかった
- 自分以外の人にも予算の状況を共有したい
- そもそも家計簿アプリなどでは自分の家計簿を他の人と共有することを、そこまで前提としていない
そのほかにも自分でも有名な家計簿アプリをレビューなどを見ていて、みんな意外と口座との自動連携などの高度な機能を使いこなせていない人がいることを知ってシンプルな予算内でおさめられるようなアプリを作った。
余談
実は以前にテスト管理ツールを作っていた時の反省があって。反省内容というのはニッチなサービスだとターゲット層にそもそも届けるのが個人開発レベルだと難しい(法人だとしても難しい)
そのため、そもそもの対象範囲は大きくただし機能を特化して作ろうと。企画する
具体的には以下の順番で進めていきました
- アプリの価値を考える
- ターゲットを決める
- ネーミングを決める
- ペーパープロトタイピングを行う
アプリの価値を考える
個人的にはこのフェーズが一番大切かな。要するに一言でこのアプリは何ということを伝えられることが重要。前回、テスト管理サービスを作って思ったが、そもそも大多数の人にはダラダラ興味のないことを説明されるのが嫌いだったりする。
個人であれ企業が作ったアプリであれ訪れた時に結局このアプリではどんなことができるのが伝わらないと、離脱の原因に繋がった。また、作っていくうちにあれこれも機能を足したり、実は優先順位が低い作業に熱中しがちになるので、そんな時に最初に価値を設定していれば優先順位をつけやすくなる。
このアプリでは、
「特定の支出に対しての管理・共有が簡単にできる」
ということを価値に設定しました。かなり普通だけど結局奇抜なコンセプトを作ったとしても伝えるはすごく難しい!
そのため、普遍的であり多くの人が必要な価値を設定した。ターゲットを決める
年齢・性別・シチュエーションを想像して決める。最近、仕事で携わるサービスではそこまで明確にターゲットを絞り込んでいるわけではないが、初期のアプリではターゲットを設定していた方が何かと便利。
例えば、情報設計だったり配色を考えたりする時はターゲットを設定していた方が決めやすくなる。つまりターゲットを設定することで統一感が出る。
ネーミングを決める
この作業が結果的に一番大変だった。僕たちの業界ではついついカッコいい名前や造語を付けたくなるが、今回のようなツール系アプリはどストレートに何ができるのかを伝える方が重要。
そこで嫁さんに対して色々とネーミングを提案して、やっとこさ最終的にOKが出たのがこの「クイック予算」というネーミング。何もひねりがないし、一瞬でこれ予算を管理するアプリだと分かるようにしたのが狙い
ペーパープロトタイピングを行う
あらかじめ必要な機能を箇条書きでまとめておく。
その上でがしがしペーパープロトタイピング行っていく。自分がやったペーパープロトタイピングの一部は以下の画像。最終的なアプリとは微妙にディテールは違うがたたき台としてはかなり使える。この段階をすっとばしていきなりデザインツールでプロトタイピングを行う人もいるが、自分は部屋でやるより外でやりたいためペーパーでやることが多い。
デザインを考える
デザインは本職ではないが自分でソフトを使って作るようにしている。ついついエンジニアだとMaterial Designやそういうのを使いがちだが、自分は下手でも自分で作ろうとしている。
結局、ターゲットに合うのを作るには自分で行った方が良かったりする。
自分の場合は、「Adobe Xd」を使っている。非常に軽いし画像の切り出しもアプリ用に切り出してくれるので便利。ソフトはSketchやFigmaなど他にも沢山あるが正直どれでもいい。
アーキテクチャについて
FlutterやReact Nativeなどのクロスプラットフォームで開発できるし魅力的だったが、ネイティブでの開発を選んだ。
個人的な意見だがiOSとAndroidを新規サービスとして同時に出す必要性をそこまで感じない。クロスプラットフォームだとしてもiOSとAndoroidの両方の動作確認をしないといけないし手続きも面倒だ。
仕事で色々なサービスを担当してきたがWEBだけしか展開していないからサービスが成功しなかったということもない。色々な人からAndroid版も出さないのという意見をもらってから着手しても遅くはないと考えている。ネイティブの実装では以下の構成にした
- UIKitとAutoLayoutを使用
- SwiftUIじゃないのかと思われるかもしれないが、iOS12以上を対象にしたかったこととあくまでアプリをきっちり作ることを目的にしていたのでUIKitとAutoLayoutの組み合わせで構築した。
- RxSwift・ReSwift(Redux)
- SwiftUIとCombineの組み合わせが今後主流になる。その際には
Single source of truth
の世界が当たり前になると考えてReSwiftを導入した。ただ、ReSwiftの書き方を使うとViewWillAppearへの依存になるので、RxSwiftでWrapしてStoreとのバインドは行った。RxSwiftにした理由は使い慣れていただけ。- VIPPER
- この記事を参考にしながら実装した。最初は個人開発のプロジェクトでは少し過剰だったのかなと感じたが、後半戦になるとどこに何の処理を書いているのかがはっきりしていたのでかなり使いやすかった。
とくに同じViewControllerで作成・更新の処理を分ける時に、Presenterを切り替えて実装したら非常に見通しの良いコードにすることが出来た。- Realm
- 後々のことを考えるとFirestoreのローカルキャッシュで保存しても良かったが、使い慣れているRealmを初期の実装では導入した。ただ、RealmのオブジェクトをドメインやView側にも展開するとRealmの使用をやめたい時にリファクタリングが大変なので、使う境界は厳密に定めた。
- Firebase
- Firebase Analyticsだけ今回は使用した。一つだけ悩んだところは、FirebaseのProjectを一つだけ作って その中のアプリで環境を分けるのかと、そもそも環境ごとにプロジェクトを分けるのかという点。後にFirestoreを使うことも考えるとプロジェクトを分けていたほうが無難だったので分けることを選択をした。
まとめ
休日や年末年始のまとまった時間で一気に進めるようにした。平日などは細かく作成しておいたタスクを消化することでコツコツ続けた。
自分でサービスを作ったのは2回目だったが1回目よりもかなりサクサク進んだ。これは自分のモチベーションの持っていき方や進め方について慣れの部分が大きい。個人サービスをいくつも作れる人は流用できるコードやプロジェクトの進め方について経験があるから量産できるんだなと知った。iOSでは不安のあった証明書周りやリリースの手続きを経験できて良かった。