29
30

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] UIScrollView/UITableViewのcontentOffsetがずれるときがある

Posted at

iOS7から、UIScrollViewを継承したViewをViewControllerのviewの最初のviewに設定しているとviewのinsetsを操作して自動的に位置を補正するようになりました。

これは、iOS7からナビゲーションバーの下も表示領域として確保され、実質フルスクリーンが表示領域となるための措置です。

ただこの補正が自動的に行われるため、実装内容によっては意図した挙動にならず混乱することがあります。

scrollView.contentOffsetを使わない

今回色々実装していて、UIScrollViewcontentOffsetを使って、スクロール位置に応じてごにょごにょ実装していたのですが、これだとバックグラウンドから復帰した際などに自動的に補正されて意図した値が取れないことがありました。

最初はNSNotificationCenterUIApplicationWillEnterForeGroundNotificationUIApplicationDidEnterBackgroundNotificationを使って対処しようとしたんですが、色々変化して難しかったのでやめました。

結論としては scrollView.contentOffset を使わず bounds.origin.y + contentInset.top を使う、です。

ログを出力してみて気づいたのが、UIScrollViewが画面上端にある場合はbounds.origin.y-64contentInset.top64に設定されていていました。

contentOffset.yは通常時は-64ですが、contentOffset.yが少しでもずれているときにバックグラウンド→フォアグラウンドと遷移すると、自動的に位置が補正されるようです。
おそらく、自動的にinsetsを補正する機能が動いているためと思われます。

一方で、bounds.origin.y + contentInset.topの値は、UIScrollViewが画面上部にある場合は常に0となります。
なので、この値をスクロール位置として利用することでどんな状態でも適切に値を参照することができるようになりました。

console出力

実際に出力したconsoleのログを参考のため載せておきます。

通常時

po self.tableView

<TableView: 0x14887c00; baseClass = UITableView; frame = (0 0; 320 519); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x14513740>; layer = <CALayer: 0x145d1b00>; contentOffset: {0, -64}>

---------------------

po self.tableView.contentInset

 (top = 64, left = 0, bottom = 0, right = 0)

-----------------------------

po (CGRect)[self.tableView bounds]

origin=(x=0, y=-64) size=(width=320, height=519)
 {
  (x=0, y=-64)
 {
    0
    -64
  }
  (width=320, height=519)
 {
    320
    519
  }
}

ずれた状態

po self.tableView

<TableView: 0x14887c00; baseClass = UITableView; frame = (0 0; 320 519); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x14513740>; layer = <CALayer: 0x145d1b00>; contentOffset: {0, 0}>

------------------------------------------------------------------

po self.tableView.contentInset

 (top = 0, left = 0, bottom = 0, right = 0)

------------------------------------------------------------------

po (CGRect)[self.tableView bounds]

origin=(x=0, y=0) size=(width=320, height=519)
 {
  (x=0, y=0)
 {
    0
    0
  }
  (width=320, height=519)
 {
    320
    519
  }
}
29
30
2

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
29
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?