【Objective-C/Swift】iOS13対応にてUITableViewの「shouldIndentWhileEditingRowAtIndexPath」が機能しなくなった話。

##こういう人に向けて発信しています。
・編集モード中に左寄せしていた人
・iOS13対応をしている人
・下記UITableViewDelegateのデリゲートメソッドを使用している人

```
//インテント調整
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath{
      //チェックマーク分の余白を詰める為にインテントは表示しない。
      return NO;
}
```

iOS12以前では編集モードで出てくるチェックボタンを消したい場合は
冒頭に貼りましたコードなどで対応する必要がありました。

そうすればインデント（左からの余白）が無しになり、
詰められるといった算段です。

しかしながら、iOS13でiOSシミュレータ上・実機で確認してみると、
上記コードは全く動作していない事が分かりました。

<img width="300" alt="picture_pc_9eae92328994458c88cdd127d5145a18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551622/54f8ea86-b288-dabb-f86d-058592cd6542.png">


上記iOSシミュレーターは下記のコードで動かしております。
つまり、インデントを調整するデリゲートメソッドも採用しているにも
関わらずインデントがNOになっておりません。

```
#import "ViewController.h"

@interface ViewController ()<UITableViewDataSource,UITableViewDelegate>
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@end

@implementation ViewController
- (void)viewDidLoad {
   [super viewDidLoad];
   self.tableView.delegate = self;
   self.tableView.dataSource = self;
   
       //編集モードを有効にする。
   [self.tableView setEditing:YES animated:YES];
   self.tableView.allowsMultipleSelectionDuringEditing = true;
}

//インテント調整
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath{
      //チェックマーク分の余白を詰める為にインテントは表示しない。
      return NO;
}

//row = 行数を指定するデリゲートメソッド
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
   //必ずNSInteger型を返してあげている。
   return 30;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
   //標準で用意されているTableViewを利用する場合。
   NSString *cellIdentifier = @"Cell";
   UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
   
   if (!cell) {
       cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
   }
   cell.textLabel.text = [NSString stringWithFormat:@"このセルは%ld番目のセルになります！", (long)indexPath.row];
   return cell;
}

@end
```
##調査結果について
そもそもshouldIndentWhileEditingRowAtIndexPathでTweet検索して、
最新のツイートが2013年とかなので**ニッチなデリゲートメソッド**です。

なのでiOS13とか以前に関連する文献は一切見つかりませんでした。

特に公式で非推奨になるとアナウンスされたコードでも無いので、
不具合動作なのかなとも考えておりますが、
現時点で編集モード中インデントを無しにするというのは難しいと考えております。

**対応策について**
・編集モードは制御出来ないと考え使用しない。
・編集モードを自作する。

まずは仕様としては
・汎用性が高いようにセルを複数選択を想定する。
・セルを押下時は背景色を変えて、非選択時には背景色をデフォルトに。

上記仕様で考えて実装してみました。
**Objective-C/Swift両方**とも書いてみました。

##Objective-C版
```
#import "ViewController.h"

@interface ViewController ()<UITableViewDataSource,UITableViewDelegate>
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (strong,nonatomic) NSMutableArray<NSIndexPath *> *selectedIndexPathArray;

@end

@implementation ViewController


- (void)viewDidLoad {
   [super viewDidLoad];
   self.tableView.delegate = self;
   self.tableView.dataSource = self;
   self.selectedIndexPathArray = @[].mutableCopy;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return 30;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
   //標準で用意されているTableViewを利用する場合。
   NSString *cellIdentifier = @"Cell";
   UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
   
   if (!cell) {
       cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
   }
   cell.textLabel.text = [NSString stringWithFormat:@"このセルは%ld番目のセルになります！", (long)indexPath.row];
   return cell;
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
   if([self.selectedIndexPathArray containsObject:indexPath]){
       [self.selectedIndexPathArray removeObject:indexPath];
   }else{
       [self.selectedIndexPathArray addObject:indexPath];
   }
   [self.tableView reloadData];

}



/**
@brief セル表示前の処理
*/
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
   //セルのテキストが入っている場合は色を青にする
   if([self.selectedIndexPathArray containsObject:indexPath]){
       cell.backgroundColor = [UIColor lightGrayColor];
   }else{
       cell.backgroundColor = [UIColor clearColor];
   }
}

@end
```
##Swift版

```
import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource  {
   @IBOutlet weak var tableView: UITableView!
   var selectedIndexPathArray : NSMutableArray = [] ;
   override func viewDidLoad() {
       super.viewDidLoad()
       // Do any additional setup after loading the view.
       self.tableView.dataSource = self;
       self.tableView.delegate = self;
   }

   func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
       return 30;
   }
   
   func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
       let cell = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "Cell")
       // セルに表示する値を設定する
       cell.textLabel!.text = indexPath.row.description
       return cell
   }
   
   func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
       if self.selectedIndexPathArray .contains(indexPath){
           self.selectedIndexPathArray.remove(indexPath)
       }else{
           self.selectedIndexPathArray.add(indexPath)
       }
       tableView.reloadData()
   }
   
   func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
       if self.selectedIndexPathArray .contains(indexPath){
           cell.backgroundColor = .blue
       }else{
           cell.backgroundColor = .clear
       }
   }

}
```
簡単に解説するのであれば、
**（１）選択されたNSIndexPathを管理する配列を用意する。
（２）押下時に配列にNSIndexPathを含むか判定し、
　　　含む場合は削除、含まない場合は追加する。
（３）セル表示前にセル自身のindexPathを判定し、
　　　含む場合は選択色、含まない場合は透過色（デフォルト）にする。**

以上がロジックです。

**Objective-C**
```NSArray *selectedIndexPaths = [self.tableView indexPathsForSelectedRows];
```

上記のようなコードで最後にTableViewの選択されている全てのセルを
取得すると思いますが、その場合は上記コードの配列をそのまま活用すればOKです。
（押下されたセルのみ、NSIndexPath型の配列なので）