0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-12-15

こういう人に向けて発信しています。

・編集モード中に左寄せしていた人
・iOS13対応をしている人
・下記UITableViewDelegateのデリゲートメソッドを使用している人

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

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

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

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

picture_pc_9eae92328994458c88cdd127d5145a18.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
       }
   }

}

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

以上がロジックです。

Objective-C

NSArray *selectedIndexPaths = [self.tableView indexPathsForSelectedRows];

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

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?