iOS7でポップオーバー上のテーブルビューに指定したセパレータ色が反映されない事がある


皆さん2月1日のSDK7強制事件で対応を迫られていると思いますが、そんな中でバグらしき症状に出くわしましたので発生条件と暫定回避方法をメモしておきます。

- Xcode 5.0.2 + SDK 7.0 + iPad Air + iOS 7.0.4で確認 (2014/01/22)

## 基本

ポップオーバーを表示し、そのポップオーバー内にUITableViewControllerの派生クラスを載せます。
テーブルのセパレーターの色を赤にします。

```objectivec:ポップオーバーを出す側
- (void)loadView
{
    [super loadView];
    self.view.backgroundColor = [UIColor yellowColor]; // 判りやすいように黄色背景にしておきます
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    _popover = [[UIPopoverController alloc] initWithContentViewController:[ContentViewController new]];    
    [_popover presentPopoverFromRect:CGRectMake(100, 0, 30, 30) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
```

```objectivec:ContentViewController.h
#import <UIKit/UIKit.h>

@interface ContentViewController : UITableViewController

@end

```

```objectivec:ContentViewController.m
#import "ContentViewController.h"

@implementation ContentViewController

- (id)init
{
    self = [super initWithStyle:UITableViewStylePlain];
    if (self) {
        self.tableView.backgroundColor = [UIColor whiteColor];
        self.tableView.separatorColor = [UIColor redColor];
    }
    return self;
}

#pragma mark - Table view data source

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    cell.textLabel.text = @"あいうえお";
    return cell;
}

@end
```

ちゃんとセパレータが赤になりましたね。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/31347/76786f62-b4a4-f29d-ab93-1929011a4b48.png "1.png")

## separatorInsetを設定すると...

iOS 7でセパレータの左端が切れているのが嫌な場合は```separatorInset```で詰めると思いますが、これをやると...

```objectivec:ContentViewController.m
- (id)init
{
    self = [super initWithStyle:UITableViewStylePlain];
    if (self) {
        self.tableView.backgroundColor = [UIColor whiteColor];
        self.tableView.separatorInset = UIEdgeInsetsZero; // ←これ
        self.tableView.separatorColor = [UIColor redColor];
    }
    return self;
}
```

セルが無い部分のセパレータの色が反映されなくなりました。

![2.png](https://qiita-image-store.s3.amazonaws.com/0/31347/1fafb676-5b40-c0b4-eb1d-aaa40a0d06e9.png "2.png")

## 更にselectRowAtIndexPathで選択すると...

```objectivec:ContentViewController.m
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    [self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionNone];
    
}
```

完全に反映されなくなりました。

![3.png](https://qiita-image-store.s3.amazonaws.com/0/31347/c2966369-6066-535c-0817-a69742bee2ab.png "3.png")

## 別のケース

`selectRowAtIndexPath:animated:scrollPosition:`を呼ばなくても`reloadData`の直後に`cellForRowAtIndexPath:`でセルにアクセスするだけでも同様に反映されなくなります。


```objectivec:ContentViewController.m
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    [self.tableView reloadData];
    [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];    
}
```

## 症状のまとめ

- iOS 7 + ポップオーバー上に乗っているテーブルビューのセパレータ色を変える　という事が前提（iOS 6以前やポップオーバー上でない場合は発生しない）。また、UITableViewControllerに限らず、UITableViewをサブビューとして表示している場合も発生する。
- `separatorInset`に値をセットすると、セルが存在しない箇所のセパレータの色が反映されなくなる。
- `viewWillAppear:`などで`selectRowAtIndexPath:animated:scrollPosition:`で初期選択を行うと、セルが存在している箇所のセパレータの色が反映されなくなる。

## 回避方法

今のところ`separatorInset`での副作用については良い回避策を見つけていませんが、`selectRowAtIndexPath:animated:scrollPosition:`側での副作用は、標準の選択機構を使わずに、自前で選択状態を作り出せば回避できる事を確認済みです。

何か情報をお持ちの方がいらっしゃいましたらコメント頂ければ幸いです。

※ β版まだ確認していませんが、治ってたらいいな...