20220402のiOSに関する記事は7件です。

大学の非公式アプリを一カ月で作ってみた(九州大学の過去問と学生証)

はじめに 皆さんは、少し前に話題になった九州大学アプリをご存知でしょうか? 本アプリはTwitterなどのSNSで拡散されるなどして、AppStoreにて97位を記録いたしました。1 また、現在のインストール数は、九大生人口の20%を超えております。2 今回は、制作時に得た知見を共有することで、皆さんのお力になれたらと思います。 また、皆さんからいろんなアドバイスをいただきたいとも思っているので、ぜひよろしくお願いします。 自己紹介 省略? アプリ概要 主な機能は3つ クラウド過去問 デジタル学生証 ニュース を実装しています。 また、PVとして以下の動画(18秒ほど)を制作しているので、見て頂けるとわかり良いかと思います。 制作背景 コロナ禍で繋がりにくさを感じる学生が、情報過少で悩むことを無くしたい との思いから、制作することになりました。 実際コロナ禍になって、多くの人が鬱や不登校になっていると言われています。中でも大学生(低学年)は、「実家を離れて異郷の地でチャレンジする」人が多いために、相対的に該当者が多いようなことを考察しました。 本学(九州大学)においても状況は例外でなく、救済を意図としたメンタルヘルス予約アプリ 3 4の開発・リリースを外注するなど、大学としても対応をおこなっていたことを知りました。 また、僕の経験談にはなりますが、コロナ禍になってからというもの、可愛がっている後輩らから落ち込んでいるなどの相談を受けたり、友人づてに鬱になった学生らの噂を何度か聞くなど、身の回りでも、そういった学生がいることを知りました。その度に、何かできることはないかな、と感じてはおりました。そんな中、僕の大学一番の親友も、ついに不登校になってしまいまして5それがきっかけで、もう本当に危機感と救命心で心がいっぱいになりました。卒論や就活の最中でしたが、本アプリの着想を始めました。 技術選定 こんな状況だったため、とにかく早くリリースに漕ぎ着けようと思い、以下のような技術を選びました。 Flutter Firebase Pub.dev外部パッケージの多用 なぜFlutterを選んだかを述べます。 私自身、普段はUnityを利用してゲームを制作しているのですが、ツールアプリ&時短を考慮して、宣言的UIかつクロスプラットフォームを候補にした結果、 Flutter React Native Bubble.io が挙がり、それぞれの特徴を調べたところ「情報多そう、バグ少なそう」という2点に目が行き、Flutterを利用することにしました。 機能案 アプリのサブタイトル「過去問と学生証をスマホで」の通りメインの機能は、 クラウド過去問 デジタル学生証 の二つであり、おまけとして ニュース を実装しています。 なぜ上記三つの機能を実装したのかを、時系列順に説明します。 ニュース Flutterを初利用する上で、練習がてらにプログラムしたのが、ニュース機能です。これは、公式ページをスクレイピングするだけで実装できるので、練習にちょうど良かったです。 当初は、⚡️公式ページよりも早く表示できるということをウリに差別化していました。(実際、先んじてデータをスクレイピングしておいたり、スクレイピングの際に簡素なデータのみを抽出することで高速化を図っていました。ただ、利便性重視のアップデートを行うことでその速さはほとんど軽微なものになりましたが。) 利用技術と使い方 pub.dev のパッケージを利用することで、制作しました。動作はYahoo!ニュースに近いです。 クラウド過去問 外せないと思った機能は、クラウド過去問です。 周りの状況から鑑みるに不登校や鬱になった学生の共通点として 真面目 頼るのが苦手 完璧主義 がみて取れました。逆に、いわゆるウェイ系(飲み会好き)やサボリ系(適当主義)、リア充(彼氏彼女持ち)は該当することが少ないようでした。 そう言うわけで、彼らを救うために、 情報の提供 コミュニティの提供 価値観変更の促し などを考えましたが、その中でも新規アプリとして提供できる純度の高いものは、情報の提供になるのではないかと仮説しました。念の為、友人へLINEやTwitterで「上記3種のアイデアのどれが有用だと思うか」を尋ねた結果、ほとんど私と同じで「作るなら過去問のアプリだろう」とのことでした。 実際に、過去問の機能(有志によるアップロードと、無償で可能なダウンロード)を実装した初版をリリース後、学内のいろんな人にビラを配ったり触ってもらいつつ、所感を述べてもらったりインストール率を確認することで、需要の度合いを確認してみました。(計500名ほど)すると、次のことがわかりました。 ⭕️ 大学1,2年生はかなりの確率でインストールしてくれる。 ❌ 大学3,4年生、大学院生はほとんどインストールしない。 考えたら当たり前のことでしたが、実際に経験するとショックな出来事でした。やはり下級生は過去問で困っている人が多いようで、ベータ版にも関わらず、砂漠でオアシスを見つけたかの如く「ありがとうございます!!完成したら絶対使います!」と言っていただく機会が多かったです。 反対に上級生は、そもそも過去問が必要な学年ではないという前提もありますので、「後輩を救うためにアップロードしてほしいです!」という文言でビラを配りましたが、あまり共感を得られませんでした。彼らの意見として「アップロードに対してのインセンティブがないとやらないな」とか「自分はもう、過去問を利用する年齢じゃないので使わない。」などが多く寄せられました。また、そもそもビラを受け取ってくれない人も多く、ここに、コロナ禍を経験した層としていない層の大きな隔たりを見て取れました。 もちろん、上級生であっても即インストールして頂ける方も少なからず居て、彼らはコロナ禍の後輩の現状を知っている人だったり、共感性の高い人だったりしました。ですが、多くの上級生は、コロナ禍の後輩の現状を知らない方が多いようでした。 そこで、上級生がインストールするメリットを感じられる機能を追加することにしました。 利用技術と使い方 Firebase Strage Firebase Authentication UIはGoogle Driveに近いです。 デジタル学生証 「学生証がアプリになった」というパワーワードが上級生のインストールにつながるだろう、とのことで学生証機能を実装しました。 最初は、学生証のICをスマホのFelicaで反映できないかと考えましたが、どうやら本学の学生証は、富士通?の独自IC技術を取り入れているようで、スマホに入れられる形式ではありませんでした。そこで、いわゆる学生番号(バーコード形式)のみをスマホに反映することにしました。同時に、大学事務室や学内図書館に掛け合って、このバーコードシステムを学内利用できないか掛け合うご相談をいたしました。結果、大人の事情で難しいだろうということで、現在は未だ「使い道のない学生証システム?」です。この点は、大学公認サークル6と連携しまして、着実に新ルール提案からしていこうか、という話になっております。 ただ、本アプリの目的は、学生証システムではなく、あくまで「過去問など、情報提供によってコロナ禍の後輩を救うこと」であり、本筋と外れていますから、優先順位は高くありません。 利用技術 pub.dev のパッケージを利用することで、制作しました。学生番号を入力するか、スマホカメラにて学生証を読み取ると使えるようになります。UIはPayPayに近いです。 信頼性 信頼性については、以下の2点の対応を行いました。ただ、開発よりもこの部分にかなりの時間を費やすことになりましたし、私の知識不足から未だ上手い対処ができておりません。ぜひ皆さんにアドバイスしていただきたいです? プログラム的な信頼性 開発元の信頼性 プログラム的な信頼性というのは、「勝手に情報が抜き取られているのではないか」という点の対処です。結論、本アプリは個人情報を抜き取ったり、どこかにストックしたりということはありません。 一番気になるのは、学生証を読み取る機能の部分だと思いますが、こちらはスマホ内での計算とストレージにのみ頼っており、この際情報が外部に通信されることは一切ありません。 ただ、これを証明するいい案が思いつかず、、、皆さまどういった案があるでしょうか?? また、開発元の信頼性というのは、「開発者は信頼できるのか」ということですが、ユーザーのアドバイスによると、個人でやっている限り懐疑心は高いのでは、とのことだったので、色々な学内団体に掛け合い、大学公認サークル6と連携することになりました。また、アプリ内で収益を得ないということも、間接的に信頼につながるだろうとの意見もありましたので、無広告・アフィリエイト無しにしました。また、過去問用のサーバー費を私が負担することで、赤字前提で、後輩を救うために運営しているということが伝わればと思っています。ただ、こちらも上手い伝え方が分からないのでいい伝え方があれば、是非とも教えていただきたいです?‍♀️ 許可等 アプリに関する許可等については、事務室など色々な場に掛け合うことで対応中ですが、こちらは本当に難しいです。大人の方には、かなり誠意的に相談に乗って頂いているので、有難い限りです。ただ、大人の事情がどうしてもありまして、ご相談の結果、連携する大学公認サークル6にて対応することにしました。 お忙しい中、ご相談用の会議を開いていただいた事務室の方や、色々な大人の方にはこの場を借りて感謝申し上げます。?‍♀️ 最後に AppStore、Google Playにて公開しておりますので、ぜひダウンロードして頂けると嬉しいです。 改善点やレビュー等、お待ちしております。 日本国内の教育カテゴリーにて、2022/02/03 現在 ↩ 九大人口を18,000人とした時に、AppStore,GooglePlay両者の総インストール数が3600を超えるため。2022/03/31 現在 ↩ https://www.kyushu-u.ac.jp/ja/topics/view/1677 ↩ https://apps.apple.com/app/id1562248417 ↩ 現在は復帰して無事卒業しました? ↩ 九州大学起業部と2022/03より。 ↩ ↩2 ↩3
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

九州大学のアプリを一カ月で作ってみた。

はじめに 皆さんは、少し前に話題になった九州大学アプリをご存知でしょうか? 本アプリはTwitterなどのSNSで拡散されるなどして、AppStoreにて94位を記録いたしました。1 また、現在のインストール数は、九大生人口の20%を超えております。2 今回は、制作時に得た知見を共有することで、皆さんのお力になれたらと思います。 また、皆さんからいろんなアドバイスをいただきたいとも思っているので、ぜひよろしくお願いします。 自己紹介 省略? アプリの概要 主な機能は3つ クラウド過去問 デジタル学生証 ニュース を実装しています。 また、PVとして以下の動画(18秒ほど)を制作しているので、見て頂けるとわかり良いかと思います。 制作背景 コロナ禍で繋がりにくさを感じる学生が、情報過少で悩むことを無くしたい との思いから、制作することになりました。 実際コロナ禍になって、多くの人が鬱や不登校になっていると言われています。中でも大学生(低学年)は、「実家を離れて異郷の地でチャレンジする」人が多いために、相対的に該当者が多いようなことを考察しました。 本学(九州大学)においても状況は例外でなく、救済を意図としたメンタルヘルス予約アプリ 3 4の開発・リリースを外注するなど、大学としても対応をおこなっていたことを知りました。 また、僕の経験談にはなりますが、コロナ禍になってからというもの、可愛がっている後輩らから落ち込んでいるなどの相談を受けたり、友人づてに鬱になった学生らの噂を何度か聞くなど、身の回りでも、そういった学生がいることを知りました。その度に、何かできることはないかな、と感じてはおりました。そんな中、僕の大学一番の親友も、ついに不登校になってしまいまして5それがきっかけで、もう本当に危機感と救命心で心がいっぱいになりました。卒論や就活の最中でしたが、本アプリの着想を始めました。 技術選定 こんな状況だったため、とにかく早くリリースに漕ぎ着けようと思い、以下のような技術を選びました。 Flutter Firebase Pub.dev外部パッケージの多用 なぜFlutterを選んだかを述べます。 私自身、普段はUnityを利用してゲームを制作しているのですが、ツールアプリ&時短を考慮して、宣言的UIかつクロスプラットフォームを候補にした結果、 Flutter React Native Bubble.io が挙がり、それぞれの特徴を調べたところ「情報多そう、バグ少なそう」という2点に目が行き、Flutterを利用することにしました。 3つの機能 アプリのサブタイトル「過去問と学生証をスマホで」の通りメインの機能は、 クラウド過去問 デジタル学生証 の二つであり、おまけとして ニュース を実装しています。 なぜ上記三つの機能を実装したのかを、時系列順に説明します。 ①ニュース 開発背景 Flutterを初利用する上で、練習がてらにプログラムしたのが、ニュース機能です。 これは、公式ページをスクレイピングするだけで実装できるので、練習にちょうど良かったです。 当初は、⚡️公式ページよりも早く表示できるということをウリに差別化していました。(実際、先んじてデータをスクレイピングしておいたり、スクレイピングの際に簡素なデータのみを抽出することで高速化を図っていました。ただ、利便性重視のアップデートを行うことでその速さはほとんど軽微なものになりましたが。) 使用技術 pub.dev のパッケージを利用することで、制作しました。 使い方 動作はYahoo!ニュースに近いです。 ②クラウド過去問 開発背景 外せないと思った機能は、クラウド過去問です。 周りの状況から鑑みるに不登校や鬱になった学生の共通点として 真面目 頼るのが苦手 完璧主義 がみて取れました。逆に、いわゆるウェイ系(飲み会好き)やサボリ系(適当主義)、リア充(彼氏彼女持ち)は該当することが少ないようでした。 そう言うわけで、彼らを救うために、 情報の提供 コミュニティの提供 価値観変更の促し などを考えましたが、その中でも新規アプリとして提供できる純度の高いものは、情報の提供になるのではないかと仮説しました。念の為、友人へLINEやTwitterで「上記3種のアイデアのどれが有用だと思うか」を尋ねた結果、ほとんど私と同じで「作るなら過去問のアプリだろう」とのことでした。 実際に、過去問の機能(有志によるアップロードと、無償で可能なダウンロード)を実装した初版をリリース後、学内のいろんな人にビラを配ったり触ってもらいつつ、所感を述べてもらったりインストール率を確認することで、需要の度合いを確認してみました。(計500名ほど)すると、次のことがわかりました。 ⭕️ 大学1,2年生はかなりの確率でインストールしてくれる。 ❌ 大学3,4年生、大学院生はほとんどインストールしない。 考えたら当たり前のことでしたが、実際に経験するとショックな出来事でした。やはり下級生は過去問で困っている人が多いようで、ベータ版にも関わらず、砂漠でオアシスを見つけたかの如く「ありがとうございます!!完成したら絶対使います!」と言っていただく機会が多かったです。 反対に上級生は、そもそも過去問が必要な学年ではないという前提もありますので、「後輩を救うためにアップロードしてほしいです!」という文言でビラを配りましたが、あまり共感を得られませんでした。彼らの意見として「アップロードに対してのインセンティブがないとやらないな」とか「自分はもう、過去問を利用する年齢じゃないので使わない。」などが多く寄せられました。また、そもそもビラを受け取ってくれない人も多く、ここに、コロナ禍を経験した層としていない層の大きな隔たりを見て取れました。 もちろん、上級生であっても即インストールして頂ける方も少なからず居て、彼らはコロナ禍の後輩の現状を知っている人だったり、共感性の高い人だったりしました。ですが、多くの上級生は、コロナ禍の後輩の現状を知らない方が多いようでした。 そこで、上級生がインストールするメリットを感じられる機能を追加することにしました。 使用技術 Firebase Strage Firebase Authentication 使い方 UIはGoogle Driveに近いです。 ③デジタル学生証 開発背景 「学生証がアプリになった」というパワーワードが上級生のインストールにつながるだろう、とのことで学生証機能を実装しました。 最初は、学生証のICをスマホのFelicaで反映できないかと考えましたが、どうやら本学の学生証は、富士通?の独自IC技術を取り入れているようで、スマホに入れられる形式ではありませんでした。そこで、いわゆる学生番号(バーコード形式)のみをスマホに反映することにしました。同時に、大学事務室や学内図書館に掛け合って、このバーコードシステムを学内利用できないか掛け合うご相談をいたしました。結果、大人の事情で難しいだろうということで、現在は未だ「使い道のない学生証システム?」です。この点は、大学公認サークル6と連携しまして、着実に新ルール提案からしていこうか、という話になっております。 ただ、本アプリの目的は、学生証システムではなく、あくまで「過去問など、情報提供によってコロナ禍の後輩を救うこと」であり、本筋と外れていますから、優先順位は高くありません。 使用技術 pub.dev のパッケージを利用することで、制作しました。学生番号を入力するか、スマホカメラにて学生証を読み取ると使えるようになります。 使い方 UIはPayPayに近いです。 信頼性を高める。 信頼性については、以下の2点の対応を行いました。ただ、開発よりもこの部分にかなりの時間を費やすことになりましたし、私の知識不足から未だ上手い対処ができておりません。ぜひ皆さんにアドバイスしていただきたいです? プログラム的な信頼性 開発元の信頼性 プログラム的な信頼性というのは、「勝手に情報が抜き取られているのではないか」という点の対処です。結論、本アプリは個人情報を抜き取ったり、どこかにストックしたりということはありません。 一番気になるのは、学生証を読み取る機能の部分だと思いますが、こちらはスマホ内での計算とストレージにのみ頼っており、この際情報が外部に通信されることは一切ありません。 ただ、これを証明するいい案が思いつかず、、、皆さまどういった案があるでしょうか?? また、開発元の信頼性というのは、「開発者は信頼できるのか」ということですが、ユーザーのアドバイスによると、個人でやっている限り懐疑心は高いのでは、とのことだったので、色々な学内団体に掛け合い、大学公認サークル6と連携することになりました。また、アプリ内で収益を得ないということも、間接的に信頼につながるだろうとの意見もありましたので、無広告・アフィリエイト無しにしました。また、過去問用のサーバー費を私が負担することで、赤字前提で、後輩を救うために運営しているということが伝わればと思っています。ただ、こちらも上手い伝え方が分からないのでいい伝え方があれば、是非とも教えていただきたいです?‍♀️ 許可を得る。 アプリに関する許可等については、事務室など色々な場に掛け合うことで対応中ですが、こちらは本当に難しいです。大人の方には、かなり誠意的に相談に乗って頂いているので、有難い限りです。ただ、大人の事情がどうしてもありまして、ご相談の結果、連携する大学公認サークル6にて対応することにしました。 お忙しい中、ご相談用の会議を開いていただいた事務室の方や、色々な大人の方にはこの場を借りて感謝申し上げます。?‍♀️ 最後に AppStore、Google Playにて公開しておりますので、ぜひダウンロードして頂けると嬉しいです。 改善点やレビュー等、お待ちしております。 日本国内の教育カテゴリーにて、2022/02/03 現在 ↩ 九大人口を18,000人とした時に、AppStore,GooglePlay両者の総インストール数が3600を超えるため。2022/03/31 現在 ↩ https://www.kyushu-u.ac.jp/ja/topics/view/1677 ↩ https://apps.apple.com/app/id1562248417 ↩ 現在は復帰して無事卒業しました? ↩ 九州大学起業部と2022/03より。 ↩ ↩2 ↩3
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

九州大学の非公式アプリを一カ月で作ってみた。

はじめに 皆さんは、少し前に話題になった九州大学アプリをご存知でしょうか? 本アプリはTwitterなどのSNSで拡散されるなどして、AppStoreにて94位を記録いたしました。1 また、現在のインストール数は、九大生人口の20%を超えております。2 今回は、制作時に得た知見を共有することで、皆さんのお力になれたらと思います。 また、皆さんからいろんなアドバイスをいただきたいとも思っているので、ぜひよろしくお願いします。 自己紹介 省略? アプリの概要 主な機能は3つ クラウド過去問 デジタル学生証 ニュース を実装しています。 また、PVとして以下の動画(18秒ほど)を制作しているので、見て頂けるとわかり良いかと思います。 制作背景 コロナ禍で繋がりにくさを感じる学生が、情報過少で悩むことを無くしたい との思いから、制作することになりました。 実際コロナ禍になって、多くの人が鬱や不登校になっていると言われています。中でも大学生(低学年)は、「実家を離れて異郷の地でチャレンジする」人が多いために、相対的に該当者が多いようなことを考察しました。 本学(九州大学)においても状況は例外でなく、救済を意図としたメンタルヘルス予約アプリ 3 4の開発・リリースを外注するなど、大学としても対応をおこなっていたことを知りました。 また、僕の経験談にはなりますが、コロナ禍になってからというもの、可愛がっている後輩らから落ち込んでいるなどの相談を受けたり、友人づてに鬱になった学生らの噂を何度か聞くなど、身の回りでも、そういった学生がいることを知りました。その度に、何かできることはないかな、と感じてはおりました。そんな中、僕の大学一番の親友も、ついに不登校になってしまいまして5それがきっかけで、もう本当に危機感と救命心で心がいっぱいになりました。卒論や就活の最中でしたが、本アプリの着想を始めました。 技術選定 こんな状況だったため、とにかく早くリリースに漕ぎ着けようと思い、以下のような技術を選びました。 Flutter Firebase Pub.dev外部パッケージの多用 なぜFlutterを選んだかを述べます。 私自身、普段はUnityを利用してゲームを制作しているのですが、ツールアプリ&時短を考慮して、宣言的UIかつクロスプラットフォームを候補にした結果、 Flutter React Native Bubble.io が挙がり、それぞれの特徴を調べたところ「情報多そう、バグ少なそう」という2点に目が行き、Flutterを利用することにしました。 3つの機能 アプリのサブタイトル「過去問と学生証をスマホで」の通りメインの機能は、 クラウド過去問 デジタル学生証 の二つであり、おまけとして ニュース を実装しています。 なぜ上記三つの機能を実装したのかを、時系列順に説明します。 ①ニュース 開発背景 Flutterを初利用する上で、練習がてらにプログラムしたのが、ニュース機能です。 これは、公式ページをスクレイピングするだけで実装できるので、練習にちょうど良かったです。 当初は、⚡️公式ページよりも早く表示できるということをウリに差別化していました。(実際、先んじてデータをスクレイピングしておいたり、スクレイピングの際に簡素なデータのみを抽出することで高速化を図っていました。ただ、利便性重視のアップデートを行うことでその速さはほとんど軽微なものになりましたが。) 使用技術 pub.dev のパッケージを利用することで、制作しました。 使い方 動作はYahoo!ニュースに近いです。 ②クラウド過去問 開発背景 外せないと思った機能は、クラウド過去問です。 周りの状況から鑑みるに不登校や鬱になった学生の共通点として 真面目 頼るのが苦手 完璧主義 がみて取れました。逆に、いわゆるウェイ系(飲み会好き)やサボリ系(適当主義)、リア充(彼氏彼女持ち)は該当することが少ないようでした。 そう言うわけで、彼らを救うために、 情報の提供 コミュニティの提供 価値観変更の促し などを考えましたが、その中でも新規アプリとして提供できる純度の高いものは、情報の提供になるのではないかと仮説しました。念の為、友人へLINEやTwitterで「上記3種のアイデアのどれが有用だと思うか」を尋ねた結果、ほとんど私と同じで「作るなら過去問のアプリだろう」とのことでした。 実際に、過去問の機能(有志によるアップロードと、無償で可能なダウンロード)を実装した初版をリリース後、学内のいろんな人にビラを配ったり触ってもらいつつ、所感を述べてもらったりインストール率を確認することで、需要の度合いを確認してみました。(計500名ほど)すると、次のことがわかりました。 ⭕️ 大学1,2年生はかなりの確率でインストールしてくれる。 ❌ 大学3,4年生、大学院生はほとんどインストールしない。 考えたら当たり前のことでしたが、実際に経験するとショックな出来事でした。やはり下級生は過去問で困っている人が多いようで、ベータ版にも関わらず、砂漠でオアシスを見つけたかの如く「ありがとうございます!!完成したら絶対使います!」と言っていただく機会が多かったです。 反対に上級生は、そもそも過去問が必要な学年ではないという前提もありますので、「後輩を救うためにアップロードしてほしいです!」という文言でビラを配りましたが、あまり共感を得られませんでした。彼らの意見として「アップロードに対してのインセンティブがないとやらないな」とか「自分はもう、過去問を利用する年齢じゃないので使わない。」などが多く寄せられました。また、そもそもビラを受け取ってくれない人も多く、ここに、コロナ禍を経験した層としていない層の大きな隔たりを見て取れました。 もちろん、上級生であっても即インストールして頂ける方も少なからず居て、彼らはコロナ禍の後輩の現状を知っている人だったり、共感性の高い人だったりしました。ですが、多くの上級生は、コロナ禍の後輩の現状を知らない方が多いようでした。 そこで、上級生がインストールするメリットを感じられる機能を追加することにしました。 使用技術 Firebase Strage Firebase Authentication 使い方 UIはGoogle Driveに近いです。 ③デジタル学生証 開発背景 「学生証がアプリになった」というパワーワードが上級生のインストールにつながるだろう、とのことで学生証機能を実装しました。 最初は、学生証のICをスマホのFelicaで反映できないかと考えましたが、どうやら本学の学生証は、富士通?の独自IC技術を取り入れているようで、スマホに入れられる形式ではありませんでした。そこで、いわゆる学生番号(バーコード形式)のみをスマホに反映することにしました。同時に、大学事務室や学内図書館に掛け合って、このバーコードシステムを学内利用できないか掛け合うご相談をいたしました。結果、大人の事情で難しいだろうということで、現在は未だ「使い道のない学生証システム?」です。この点は、大学公認サークル6と連携しまして、着実に新ルール提案からしていこうか、という話になっております。 ただ、本アプリの目的は、学生証システムではなく、あくまで「過去問など、情報提供によってコロナ禍の後輩を救うこと」であり、本筋と外れていますから、優先順位は高くありません。 使用技術 pub.dev のパッケージを利用することで、制作しました。学生番号を入力するか、スマホカメラにて学生証を読み取ると使えるようになります。 使い方 UIはPayPayに近いです。 信頼性を高める。 信頼性については、以下の2点の対応を行いました。ただ、開発よりもこの部分にかなりの時間を費やすことになりましたし、私の知識不足から未だ上手い対処ができておりません。ぜひ皆さんにアドバイスしていただきたいです? プログラム的な信頼性 開発元の信頼性 プログラム的な信頼性というのは、「勝手に情報が抜き取られているのではないか」という点の対処です。結論、本アプリは個人情報を抜き取ったり、どこかにストックしたりということはありません。 一番気になるのは、学生証を読み取る機能の部分だと思いますが、こちらはスマホ内での計算とストレージにのみ頼っており、この際情報が外部に通信されることは一切ありません。 ただ、これを証明するいい案が思いつかず、、、皆さまどういった案があるでしょうか?? また、開発元の信頼性というのは、「開発者は信頼できるのか」ということですが、ユーザーのアドバイスによると、個人でやっている限り懐疑心は高いのでは、とのことだったので、色々な学内団体に掛け合い、大学公認サークル6と連携することになりました。また、アプリ内で収益を得ないということも、間接的に信頼につながるだろうとの意見もありましたので、無広告・アフィリエイト無しにしました。また、過去問用のサーバー費を私が負担することで、赤字前提で、後輩を救うために運営しているということが伝わればと思っています。ただ、こちらも上手い伝え方が分からないのでいい伝え方があれば、是非とも教えていただきたいです?‍♀️ 許可を得る。 アプリに関する許可等については、事務室など色々な場に掛け合うことで対応中ですが、こちらは本当に難しいです。大人の方には、かなり誠意的に相談に乗って頂いているので、有難い限りです。ただ、大人の事情がどうしてもありまして、ご相談の結果、連携する大学公認サークル6にて対応することにしました。 お忙しい中、ご相談用の会議を開いていただいた事務室の方や、色々な大人の方にはこの場を借りて感謝申し上げます。?‍♀️ 最後に AppStore、Google Playにて公開しておりますので、ぜひダウンロードして頂けると嬉しいです。 改善点やレビュー等、お待ちしております。 日本国内の教育カテゴリーにて、2022/02/03 現在 ↩ 九大人口を18,000人とした時に、AppStore,GooglePlay両者の総インストール数が3600を超えるため。2022/03/31 現在 ↩ https://www.kyushu-u.ac.jp/ja/topics/view/1677 ↩ https://apps.apple.com/app/id1562248417 ↩ 現在は復帰して無事卒業しました? ↩ 九州大学起業部と2022/03より。 ↩ ↩2 ↩3
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【非同期処理】UITableViewが`Index out of range`でクラッシュする回避策

環境 ・Swift 5.5.2 ・Xcode 13.2.1 発生したエラー ※一部コードを省略しています ViewController.Swift override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.users = [] db.fetchUsers { [weak self] result in guard let self = self else { return } switch result { case .success(let users): self.users = users case .failure(let error): print(error.localizeddescription) } } } extension ViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! UITableViewCell cell.configure(user: users[indexPath.row]) //この行で`index out of range`が発生する return cell } } extension ViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { print("indexpath.row: \(users[indexPath.row])") //タップした時にこの行で`index out of range`が発生する } } 原因 非同期でデータを受け取る前(配列がまだ空)にcellForRowAtやdidSelectRowAtが呼ばれて、存在しない要素にアクセスしたため。 回避策 下記のように、配列が空の時は早期リターンでアクセスしないようにすることで回避できます。 ViewController.Swift func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! UITableViewCell guard users.count > 0 else { return cell } //このコードを追加 cell.configure(user: users[indexPath.row]) return cell }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【iOS】画面遷移をした後にキーボードを自動的に表示させる方法

はじめに キーボードを起動するためにテキストフィールドを毎回タップするのがめんどくさいなぁと感じたため、画面が開いたときにキーボードが自動的に表示される方が便利と思いました。そのため、画面遷移をした後にキーボードを自動的に表示させる方法を書いていきます。 やり方 これを実現するには簡単で、新しいメソッドをViewController内に以下のコードを追加します。 override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) textField.becomeFirstResponder() } 詳細説明 override func viewWillAppear(_ animated: Bool) {とは? 画面に表示される直前に呼ばれるメソッドです。初期表示に必要なviewDidLoad()とは異なり、毎回呼び出されます。 UIViewControllerのライフサイクルについての詳細は以下の記事をご参照ください textField.becomeFirstResponder() UITextFieldはファーストレスポンダにすることによりキーボードを表示することができます。逆にファーストレスポンダをやめるとキーボードを非表示にすることができます。 そのため、textField.becomeFirstResponder()とすることにより、画面を読み込むたびにキーボードを表示することができます。 「ファーストレスポンダ」とは? iOSでは「レスポンダチェーン」と呼ばれる仕組みが用意されています。一連のレスポンダオブジェクトの連なりで、イベントを処理できるオブジェクトを決定するために使用されます。 レスポンダオブジェクトは基本的にView階層のかいに位置されるオブジェクトから順に評価されるため、最初にイベントを受け取るレスポンダオブジェクトを「ファーストレスポンダ」と呼びます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【iOS】画面遷移時にキーボードを表示させる方法

はじめに キーボードを起動するためにテキストフィールドを毎回タップするのがめんどくさいなぁと感じたため、画面が開いたときにキーボードが自動的に表示される方が便利と思いました。そのため、画面遷移をした後にキーボードを自動的に表示させる方法を書いていきます。 また、これは画面遷移が完全に終わる前にキーボードを事前に表示しておく方法です。画面遷移が完全に終了した後の処理はこの後出てくるviewWillAppearをviewDidAppearにすると可能です。 やり方 これを実現するには簡単で、新しいメソッドをViewController内に以下のコードを追加します。 override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) textField.becomeFirstResponder() } 詳細説明 override func viewWillAppear(_ animated: Bool) {とは? 画面に表示される直前に呼ばれるメソッドです。初期表示に必要なviewDidLoad()とは異なり、毎回呼び出されます。 UIViewControllerのライフサイクルについての詳細は以下の記事をご参照ください textField.becomeFirstResponder() UITextFieldはファーストレスポンダにすることによりキーボードを表示することができます。逆にファーストレスポンダをやめるとキーボードを非表示にすることができます。 そのため、textField.becomeFirstResponder()とすることにより、画面を読み込むたびにキーボードを表示することができます。 「ファーストレスポンダ」とは? iOSでは「レスポンダチェーン」と呼ばれる仕組みが用意されています。一連のレスポンダオブジェクトの連なりで、イベントを処理できるオブジェクトを決定するために使用されます。 レスポンダオブジェクトは基本的にView階層のかいに位置されるオブジェクトから順に評価されるため、最初にイベントを受け取るレスポンダオブジェクトを「ファーストレスポンダ」と呼びます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コードから学ぶRxSwiftを用いたMVVMアーキテクチャ

参考 iOSアプリ設計パターン入門 サンプルアプリ MVVMSample MVVM × RxSwift MVVMは、Cocoa MVCアーキテクチャと同様Presentation Domain Separationの概念を根底としており、 アプリケーションのUI(Presentation) と UIとは無関係な処理(Domain) を分離することを目的としている。 例として、以下の機能を有するアプリケーションを作成する。 テキストフィールド(UITextField)に数字を入力するとラベル(UILabel)に即時反映される ボタン(UIButton)をタップすると、1〜100の範囲内の乱数が生成され、ラベル(UILabel)に反映される 2.のアクションによってラベルの値に変更が生じた場合はテキストフィールド(UITextField)の入力値も変更される ここで、MVVMアーキテクチャにおけるModel・View・ViewModelの役割は、以下の通りである。 レイヤー 役割 Model UIとは無関係のビジネスロジック View UIコンポーネントの描画 ⇅ (View と ViewModelでデータバインディング) ViewModel UIに関係するプレゼンテーションロジック Model Modelは、UIに関係しないビジネスロジックを定義する。 このとき、Modelをプロトコル化することでロジックを疎結合にしながら、テスト可能な設計にすることができる。(=Dependency Injection) また、RxSwiftで提供されているObservable型で返却することで、他のObservableオブジェクトと合成しやすくする。 protocol ModelProtocol { func generateRandomInt(from x: Int, to y: Int) -> Observable<Int> } final class Model: ModelProtocol { /// 乱数を生成する /// - parameter from: 最小値 /// - parameter to: 最大値 /// - returns `x`以上`y`以下の整数値をもつイベントを発行する`Observable` func generateRandomInt(from x: Int, to y: Int) -> Observable<Int> { return Observable.just(Int.random(in: x...y)) } } ViewModel ViewModelは、UIに関係するモデルデータを定義する。 ViewのUIコンポーネントのObservableオブジェクトを購読し、加工した値をもつイベントをViewModelのObservableプロパティから発行する。 また、Modelの処理を呼び出し、Modelによって返却されたObservableオブジェクトのイベントを契機としてViewModelのObservableプロパティの値を更新する。 final class ViewModel { // UIコンポーネントに表示するデータはObservableオブジェクトにしておく。 let numBehaviorRelay: BehaviorRelay<String> = BehaviorRelay(value: "0") let buttonPublishSubject: PublishSubject<Void> = PublishSubject<Void>() // ViewModelはModelの処理を呼び出すため、プロパティとして保持しておく。 // このとき、Modelのプロトコルに型定義しておくことで、ModelProtocolに準拠したあらゆるModelオブジェクトをスタブにできるようにしておく(=Dependency Injection)。 // → Modelの処理をViewModelの初期化時でのみ呼び出す場合は、不要なプロパティとなるのを避けるためプロパティとして設定しないのが望ましい。 private let model: ModelProtocol // データバインディングの必要性がなくなったタイミングでView(UIコンポーネント)のObservableオブジェクトの監視を停止するため、 // DisposeBagインスタンスを保持しておく。 private let disposeBag: DisposeBag = DisposeBag() // 初期化時にイベントを発火するUIコンポーネントのObservableを利用するため、パラメータに設定しておく。 // → UIコンポーネントのObservableオブジェクトをViewModelのObservableプロパティに合わせるよう加工する。 init(textFieldObservable: Observable<String?>, buttonObservable: Observable<Void>, model: ModelProtocol) { self.model = model // UIコンポーネント(View)のObservableを購読し、値を加工してViewModelのObservableオブジェクトのイベントとして発火させる。 // → subscribe(onNext:onError:onCompleted:onDisposed:)メソッドでクロージャを用いる際は、 // クロージャからViewModelインスタンスへの参照を弱参照にすることで循環参照を避ける。 disposeBag.insert( // Viewのテキストフィールド(UITextField)が発火するイベントの購読 textFieldObservable.subscribe(onNext: { [weak self] (numText: String?) -> Void in guard let self = self else { return } guard let numText = numText else { return } // テキストフィールド(UITextField)に値が入力されていない場合はViewModelの値を更新しない if numText == "" { return } self.numBehaviorRelay.accept(numText) }), // Viewのボタン(UIButton)が発火するイベントの購読 buttonPublishSubject.flatMap { () -> Observable<Int> in return self.model.generateRandomInt(from: 1, to: 100) }.subscribe(onNext: { [weak self] (num: Int) -> Void in guard let self = self else { return } self.numBehaviorRelay.accept(String(num)) }) ) } } View MVVMアーキテクチャでは、UIViewControllerはViewに属する。 UIViewController(のサブクラス)は、各UIコンポーネントとViewModelインスタンスを保持し、 ViewModelのObservable(=Subject・Relayを含む)プロパティ ⇄ 各UIコンポーネント の単方向(ViewModel → View)または双方向のデータバインディングを行う。 class ViewController: UIViewController { @IBOutlet private weak var label: UILabel! @IBOutlet private weak var textField: UITextField! @IBOutlet private weak var button: UIButton! // UIコンポーネントへの入力イベントをViewModelに伝搬させるため、 // ViewModelのObservableプロパティにはイベントリスナとなるUIコンポーネントのObservableインスタンスを格納する。 // ここで、ViewModelの初期化はviewDidLoad()メソッドが呼ばれる前に実行されないようlazyプロパティを付与しておく。 // また、ViewModelはModelのメソッドを使用するため、Modelインスタンスを生成して格納する。 private lazy var viewModel: ViewModel = ViewModel( textFieldObservable: textField.rx.text.asObservable(), buttonObservable: button.rx.tap.asObservable(), model: Model() ) // データバインディングの必要性がなくなったタイミングでViewModelのObservableオブジェクトの監視を停止するため、 // DisposeBagインスタンスを保持しておく。 private let disposeBag: DisposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() disposeBag.insert( // ViewModelのObservableプロパティ → Viewのラベル(UILabel) のデータバインディング(≒購読) viewModel.numBehaviorRelay.bind(to: label.rx.text), // ViewModelのObservableプロパティ → Viewのテキストフィールド(UITextField) のデータバインディング(≒購読) viewModel.numBehaviorRelay.bind(to: textField.rx.text), // Viewのボタン(UIButton) → ViewModelのObservableプロパティ のデータバインディング(≒購読) button.rx.tap.bind(to: viewModel.buttonPublishSubject) ) } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む