[個人アプリ開発記]スクショ・画面録画がバレるトークアプリ

##はじめに
こんにちは。先日2つ目となる[アプリ](https://apps.apple.com/jp/app/簡単チャット/id1521045947)をリリースしましたので、その機能や流れについて書こうと思います。一つ目については[こちら](https://qiita.com/Hyperbolic_____/items/8e8057398bddf8ac078e)。ちなみにリジェクトは4回されました。匿名投稿ができるアプリが審査を通るために持たせなければならない機能についても書いています。
##アプリの紹介
機能としてはLINEのようなトークアプリなのですが、友達追加やアカウント登録という概念をなくし、ルーム名とパスワードさえお互い分かっていれば誰とでも話すことができるようにしました。
<img width="200" alt="IMG_0344.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/8abb69c8-ae43-365b-aaf1-b8b1d1042beb.png"> <img width="200" alt="IMG_0347.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/6a7c8b17-bf1e-4cd3-f3bd-cb02bd7afe06.png"> 
トーク画面にはスクショ・画面録画を行うとメッセージが自動送信される仕組みになっています。
<img width="200" alt="IMG_0351.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/face73b9-69f2-3ddb-c57c-e8fd8a0106ad.png">   <img width="200" alt="IMG_0390.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/15b3d16d-d387-a68d-eb87-084c3fad0409.png">
審査を通るために追加した処理ですが、不適切な内容を投稿するユーザーをブロックすることや通報することもできます。

<img width="200" alt="Simulator Screen Shot - iPhone SE (2nd generation) - 2020-07-08 at 02.40.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/5718b8eb-9c12-0c4c-4fb1-754d852bca66.png"> <img width="200" alt="Simulator Screen Shot - iPhone SE (2nd generation) - 2020-07-08 at 02.30.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/7249442b-7850-2a55-c0ee-806cad52fa46.png">
報告された内容は開発者の元に届き、不適切な利用が確認された場合はユーザーの利用を停止させることもできます。
<img width="400" alt="スクリーンショット 2020-07-08 2.32.10.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/1dc1b1f2-5289-4902-e374-7ccd0bb98958.jpeg">

##アプリを作ろうと思った理由
**インスタでストーリをスクショすると相手にバレる？**みたいな噂を聞き、そもそもスクショを検出することは可能なのか？と思ったことがきっかけです。[この記事](https://qiita.com/takashings/items/3fad553fc97375ec7d9f)で可能であることを知り、LINEなどのトークアプリに実装したら面白そうだなと思ったのが制作を始めた理由です。その上で、LINEなど既存のトークアプリと差別化を図るために、メールアドレスや電話番号による**会員登録不要**、**ルーム名&パスワード入力**によるチャットルームの製作・参加機能を取り入れることにしました。

##使用ライブラリ
Firebase
MessageKit
SVProgressHUD
##苦労したところ
###App Storeの審査がなかなか通らない
匿名投稿機能を持つアプリが審査をパスするためには**利用規約への同意**、**不適切な投稿の通報&ブロック機能**、**危険なユーザーの利用停止機能**、**管理者と直接コンタクトを取る手段の提供**などの機能を持っている必要があります。以下は最初に出したリジェクトの一部です。

A method for filtering objectionable content
A mechanism for users to flag objectionable content
A mechanism for users to block abusive users
A mechanism for users to immediately remove posts from the feed
Developer must act on objectionable content reports within 24 hours by removing the content and ejecting the user who provided the offending content
Developer must provide contact information in the app itself, giving users the ability to report inappropriate activity

トーク機能よりもユーザーがブロックした内容を**非表示**にする機能や利用停止機能をつけるのに苦労しました。FireStoreから削除してしまうとブロックしていない他のユーザーの画面からも消えてしまうので、削除ではなく非表示にする必要があります。
###Cloud FireStoreの利用
Cloud Firestore(以下Firestore)とはFirebaseが提供しているデータベースの一つです。FirebaseはデータベースとしてRealtime Databse(古いほう)とFirestore(新しい方)の二つを提供しているのですが、どうやらFirebaseが推奨しているのはFirestoreの方っぽい。[参考](https://firebase.google.com/docs/database/rtdb-vs-firestore?hl=ja)一応Realtime Databaseも使ってみたのですが、ブラウザ上でのデザインから管理しやすそうという印象を受けたのでFirestoreを利用することにしました。が、ネット上の記事はほとんどRealtime Databaseで書かれたものであったため製作において苦労しました。
Cloud Firestoreで具体的にどう使ったのかは後述します。


###NotificationCenterの管理
スクショ・画面録画の検出はNotificationCenterによって実装しています。また、別のアプリからマルチタスク画面(ホームボタンを2回押す)を利用してスクリーンショットを撮られると検出できません。それを防ぐためにNotificationCenterを利用しホームボタンを押すことでトーク画面から別の画面へ遷移するようにしました。NotificationCenterが望まないタイミングで発火することがあり、処理に苦労しました。

###ルーム名・パスワードの入力欄
ルーム名やパスワードに文字数の制限がないと、ユーザー同士に意図しない接触が発生してしまいます。ルーム名は1文字以上、パスワードには10文字以上という制限を加え、それらの自動作成ボタンを作ることで安全性と利便性を向上させました。**ルーム名のTextFieldに文字が入力されており、かつパスワードのTextFieldに文字数が10文字以上入力されている時のみ(①)ボタンを押せるように、またそれぞれの自動作成ボタンを押されたときに押されていない方のTextFieldに①の条件が満たされている時のみボタンを押せるようにする**という複雑な処理を実装するのに苦労しました。


##技術を得るために
###Qiitaでのアウトプット
調べればわかることでも、何度もそのサイトに訪れることは結構ストレスを感じます。例外的に自分の記事は何度訪れてもストレスを感じないので、些細なことや既出の内容でも記事にするようにしています。
[Xcodeで画面遷移とともにデータを渡す](https://qiita.com/Hyperbolic_____/items/646d8314d5b3c6d36d42)
[Notificationによる通知
](https://qiita.com/Hyperbolic_____/items/74a61e8d2a205e8edee0)[複数のTextFieldにそれぞれ文字数の制限をつける](https://qiita.com/Hyperbolic_____/items/e1c8d907e89d11a64383)
[NotificationCenter.default.removeObserverの大切さを痛感した話](https://qiita.com/Hyperbolic_____/items/4bcb05edaaa6b15f8ea3)
[スクショ・画面録画されたことを通知する方法](https://qiita.com/Hyperbolic_____/items/62628225b07bc5f7afae)
[NavigationControllerの下の色を変える方法](https://qiita.com/Hyperbolic_____/items/8a5fafb4965dfb90139e)
[ラジオボタン(選択肢)を作る(xcode)
](https://qiita.com/Hyperbolic_____/items/3ef4732536e548deceb3)[NavigationControllerからモーダル遷移をする時に出たエラーCould not cast value of type..](https://qiita.com/Hyperbolic_____/items/24fb6f50f0cccc2ca5fe)
[アプリを再審査に提出する際にYour package contains a file ..と出た](https://qiita.com/Hyperbolic_____/items/e92333395a41806c2bbe)
[Firebase/Authenticationで匿名ログインにする方法](https://qiita.com/Hyperbolic_____/items/91ac39b938023c4f41b5)
[初回起動時のみ画面遷移する方法](https://qiita.com/Hyperbolic_____/items/02bc99d3a2479a8c9cf6)
[UserDefaultsに配列を追加・リセット](https://qiita.com/Hyperbolic_____/items/7eacc3131bd7453cc8c4)
[メッセージに含まれる特定の単語を＊で置き換える](https://qiita.com/Hyperbolic_____/items/f0fb29cd7a41066c8921)
[実行した時刻を数字として取得することで時系列でソートできるようにする](https://qiita.com/Hyperbolic_____/items/137316f0decb489e7236)
###Teratailでの質問
調べても解決できない時はTeratailで質問しました。回答やコメントしてくださった方々にはとても感謝しています。
[func applicationWillResignActiveが呼ばれない](https://teratail.com/questions/271190)
[Database.database().reference()　と　Firestore.firestore().collection().document()の違い](https://teratail.com/questions/271530)
[UI部品の重なりを解消したい](https://teratail.com/questions/271855)
[UIKitの中にSwiftUIを入れた時Buttonが反応しない](https://teratail.com/questions/271935)
[willTerminateNotificationでマルチタスクからアプリを消去した時に特定の処理ができない](https://teratail.com/questions/272273)
[Firestoreから取得したデータの順番を時系列にしたい](https://teratail.com/questions/272445)
[Could not cast value of type..というエラーが解決できない](https://teratail.com/questions/274454)

##FireStoreの構造
Databaseには"Rooms"と"Reports"の二つのコレクションを持っています。アプリ内でルームが作成されると、コレクションRoomsには"ルーム名"+"パスワード"をドキュメント名に持つドキュメントが作成されます。
<img width="1643" alt="スクリーンショット 2020-07-08 8.50.51.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/a8bf8ec7-5716-58b7-5dc6-485d08ec92d4.jpeg">
そして、メッセージが送信されると"messages"コレクションにデータがセットされます。
ユーザーが通報を行った際には各ルームドキュメントに"report"コレクションが作成されると同時に、同じ内容が"Reports"ドキュメントにも追加されます。
<img width="1590" alt="スクリーンショット 2020-07-08 8.51.17.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/58d41c54-1cb1-b0e7-8001-648a082aa335.jpeg">
利用規約に同意することで匿名登録が行われます。アカウントはuidというユーザーが一意に定まる文字列を持つため、ブロック機能の際にはこのuidを利用しています。
<img width="1223" alt="スクリーンショット 2020-07-03 8.04.47.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/64d0cdd6-6a32-5f71-7ccb-c28ab682e473.jpeg">

##終わりに
画像・動画を送れる機能やブデザインの向上などまだまだ実装したい内容はたくさんあります。これからも開発を継続していきます。
teratailで回答・コメントしてくださった方を始め様々な方のおかげでアプリを完成させることができました。ありがとうございました。