SNSの報告・ブロック機能

#完成予想図
SNSをリリースする上で必須なブロックと報告機能を、tableviewをスワイプさせて実装してみました。
コードの書き方は基本同じなので、アラートで出したい場合なども応用してみてください！

**途中途中に出てくる 【やること】2つと、【完成形】２つを行ってください！**

全体像を知りたい場合は、[こちらのGitHub](https://github.com/EricaFujita/MyAppMovie)と併用して見てみてください〜！


![ブロック.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490120/731d960b-fa8a-1108-4b70-cc34443b1f2a.gif)

#【説明】他人に対して報告・ブロック機能
他人の投稿（自分の投稿ではないもの）をブロックします。

①まず、サーバーから投稿とユーザー情報（誰がその投稿をしたか）を取得します（ここは割愛）
取得したuserのobjectIdが自分のobjectIdと一致しない（=つまり他人）ものに関して処理を書いていきます。

```swift

if 〇〇.user.objectId != NCMBUser.current()?.objectId{
//他人の投稿に対する処理
}
```

処理内容は、いきなりスワイプ選択したものが実行されないように、アラートを入れとくと良いかもですね！（ここも割愛）

②報告した投稿Idをサーバーに保存しましょう！
今回はサーバーをNCMBとしてコーディングします
###【やること】そのため、新たにNCMBのclassを作っておいてください。→今回はReport

保存するものは投稿IDと、現在ログインしているユーザー情報です。
以下のように、setした後は、保存しておいてください。

```swift

 let object = NCMBObject(className: "Report")
                    object?.setObject(self.〇〇[indexPath.row].objectID, forKey: "reportId")
                    object?.setObject(NCMBUser.current(), forKey: "user")
```

###【やること】ブロック機能も同様に、アラートとサーバー上のclassを作っておいてください！→今回はBlock


#【説明】自分の投稿の場合削除する
先ほど、他人のログインしている人と異なるIdの場合の非同期処理を書きましたが、それ以外（つまり、ログインしている人と同じ人が投稿している場合）はelseの方に分岐されます。
この部分で、自分の投稿を削除するアラートをかけば良さそうです！
削除したい項目をqueryでサーバーにアクセスしてください！

```swift

if 〇〇.user.objectId != NCMBUser.current()?.objectId{
//他人の投稿に対する処理
}else{
//ここに自分の投稿に対する処理
}
```


#【完成形①】ブロックユーザーを格納する配列の読み込み
①NCMB上で保存したブロックされたユーザーIDの値を持ってきて、格納する配列を用意します。（この配列に入っているIDの表示をしないようにするためです！）→今回は blockUserIdArray
②先ほど作成した"Block"という名前のNCMBのclassNameの情報を持ってくる関数(この場合はgetBlockUser())を用意します。(いつも通りqueryで持ってくるだけ)＋その関数の中でタイムラインに表示する(この場合はloadData())関数を読み込みます。
③そして、②の最後に読み込んだ関数の中で、NCMBから値を持ってきてappendする時にそのブロックIDだけを排除するようにコードを書きます。
firstIndexの説明は[こちら](https://developer.apple.com/documentation/swift/array/2994720-firstindex)

```swift
//①
    var blockUserIdArray = [String]()

//② この関数はviewWillAppearと、ブロックが選択される部分(※最後のtableviewのコードに記載あり)の二箇所で読み込む
func getBlockUser() {
        
        let query = NCMBQuery(className: "Block")

        //includeKeyでBlockの子クラスである会員情報を持ってきている
        query?.includeKey("user")
        query?.whereKey("user", equalTo: NCMBUser.current())
        query?.findObjectsInBackground({ (result, error) in
            if error != nil {
                //エラーの処理
            } else {
                //ブロックされたユーザーのIDが含まれる + removeall()は初期化していて、データの重複を防いでいる
                self.blockUserIdArray.removeAll()
                for blockObject in result as! [NCMBObject] {
                    //この部分で①の配列にブロックユーザー情報が格納
self.blockUserIdArray.append(blockObject.object(forKey: "blockUserID") as! String)
                    
                }
                
            }
        })
        loadData()
    }


//③
func loadData(){
//ここにNCMBから値を持ってくるコードが書いてある前提

//appendする時に、ブロックユーザーがnilであったらappendされるようにしている。

//Movieクラスのinitalをmovieという定数で定義した場合
let movie = Movie(title: title, user: userModel, objectID: objectID!)

if self.blockUserIdArray.firstIndex(of: movie.user.objectId) == nil{
                            self.movies.append(movie)
               }
}

```

#【完成形②】TableViewの全体コード
editActionsForRowAt関数の中に書いていきます。
アラートも付けた一例を示しておくので、自分でカスタマイズしてみてください☺️
NCMB仕様なので、サーバー違う人は気を付けてください！
ライブラリのSVProgressHUDを使用しています！


```swift

//Movieという名前のクラスの場合→クラスの名前は自分のものに変更しましょう
var movies = [Movie]()

//自分以外＝>報告・ブロックする
    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
        if movies[indexPath.row].user.objectId != NCMBUser.current()?.objectId {
            let reportButton: UITableViewRowAction = UITableViewRowAction(style: .normal, title: "報告") { (action, index) -> Void in
                let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
                let reportAction = UIAlertAction(title: "報告する", style: .destructive ){ (action) in
                    SVProgressHUD.showSuccess(withStatus: "この投稿を報告しました。ご協力ありがとうございました。")
                    let object = NCMBObject(className: "Report") //新たにクラス作る
                    object?.setObject(self.movies[indexPath.row].objectID, forKey: "reportId")
                    object?.setObject(NCMBUser.current(), forKey: "user")
                    object?.saveInBackground({ (error) in
                        if error != nil {
                            SVProgressHUD.showError(withStatus: "エラーです")
                        } else {
                            SVProgressHUD.dismiss(withDelay: 2)
                            tableView.deselectRow(at: indexPath, animated: true)
                        }
                    })
                }
                let cancelAction = UIAlertAction(title: "キャンセル", style: .cancel) { (action) in
                    alertController.dismiss(animated: true, completion: nil)
                }
                
                alertController.addAction(reportAction)
                alertController.addAction(cancelAction)
                self.present(alertController, animated: true, completion: nil)
                tableView.isEditing = false
                
            }
            reportButton.backgroundColor = UIColor.red
            let blockButton: UITableViewRowAction = UITableViewRowAction(style: .normal, title: "ブロック") { (action, index) -> Void in
                //self.comments.remove(at: indexPath.row)
                //tableView.deleteRows(at: [indexPath], with: .fade)
                let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
                let blockAction = UIAlertAction(title: "ブロックする", style: .destructive) { (action) in
                    SVProgressHUD.showSuccess(withStatus: "このユーザーをブロックしました。")
                    
                    let object = NCMBObject(className: "Block") //新たにクラス作る
                    object?.setObject(self.movies[indexPath.row].user.objectId, forKey: "blockUserID")
                    object?.setObject(NCMBUser.current(), forKey: "user")
                    object?.saveInBackground({ (error) in
                        if error != nil {
                            SVProgressHUD.showError(withStatus: "エラーです")
                        } else {
                            SVProgressHUD.dismiss(withDelay: 2)
                            tableView.deselectRow(at: indexPath, animated: true)

                     //ここで③を読み込んでいる
       　　　　　　　　　self.getBlockUser()
                        }
                    })
                    
                }
                let cancelAction = UIAlertAction(title: "キャンセル", style: .cancel) { (action) in
                    alertController.dismiss(animated: true, completion: nil)
                }
                
                alertController.addAction(blockAction)
                alertController.addAction(cancelAction)
                self.present(alertController, animated: true, completion: nil)
                tableView.isEditing = false
            }
            blockButton.backgroundColor = UIColor.blue
            return[blockButton,reportButton]
        } else {
            let deleteButton: UITableViewRowAction = UITableViewRowAction(style: .normal, title: "削除") { (action, index) -> Void in
                let query = NCMBQuery(className: "取り出したいクラスの名前")
                query?.getObjectInBackground(withId: self.movies[indexPath.row].objectID, block: { (post, error) in
                    if error != nil {
                        SVProgressHUD.showError(withStatus: "エラーです")
                        SVProgressHUD.dismiss(withDelay: 2)
                    } else {
                        DispatchQueue.main.async {
                            let alertController = UIAlertController(title: "投稿を削除しますか？", message: "削除します", preferredStyle: .alert)
                            let cancelAction = UIAlertAction(title: "キャンセル", style: .cancel) { (action) in
                                alertController.dismiss(animated: true, completion: nil)
                            }
                            let deleteAction = UIAlertAction(title: "OK", style: .default) { (acrion) in
                                post?.deleteInBackground({ (error) in
                                    if error != nil {
                                        SVProgressHUD.showError(withStatus: "エラーです")
                                        SVProgressHUD.dismiss(withDelay: 2)
                                    } else {
                                        tableView.deselectRow(at: indexPath, animated: true)
                                        self.loadData()
                                        self.〇〇TableView.reloadData()
                                    }
                                })
                            }
                            alertController.addAction(cancelAction)
                            alertController.addAction(deleteAction)
                            self.present(alertController,animated: true,completion: nil)
                            tableView.isEditing = false
                        }
                        
                    }
                })
            }
            deleteButton.backgroundColor = UIColor.red //色変更
            return [deleteButton]
        }
    }
```