iOS8 を含むSwift3対応時の不具合対応
Swift 2.1 から 3 へ移行する際に、大きな不具合が1つあったので、その対応を考えてみました。
※ ただし、多くの端末・バージョンで検証したものではありません。
問題
UITableViewDelegate の tableView(_:heightForRowAt:)
に渡される indexPath の値が間違っていました。具体的には、indexPath.row の値が、0, 1, 2, 3, … の順番で渡されるはずが、0, 0, 1, 2, … とずれてしまっていました。いざ表示してみると問題ないように見えるのですが、画面遷移時にレイアウトが崩れてしまいます。
不具合の内容や対応方法に関しては、こちらを参考にさせていただきました。
期待する動作
今回は、「tableView(_:heightForRowAt:)
で正しい値を取得する」ということでやってみます。
対応
まずはコードを貼ります。
Objective-C の Method Swizzling という、既存のメソッドを入れ替える機能を利用しました。Swift から Objective-C のコードを扱う方法は省きます。
まず参考サイトのように、問題となっている箇所を探っていくと、iOS8の UIMutableIndexPath *1 の getIndexes:range:
で取得できる値が間違っている可能性があることがわかりました。しかし、UIMutableIndexPath は開発者側には非公開となっているので、直接書き換えることができませんでした。そのため、NSIndexPath の getIndexes:range:
の値を正しい値を取得できる indexAtPosition:
で書き換えたところ、うまく動作しました。
まとめ
今回は、iOS 8 のtableView(_:heightForRowAt:)
で渡される indexPath の値が間違っていることに対し、Objective-C のコードで不具合のあるメソッドを書き換え、正しい値を返す対応を考えてみました。
ただ、やはりこの不具合は怖いので、Swift3 対応をリリースする際にはなるべく iOS8 は切りたいと思っています。
*1:憶測ですが、UIMutableIndexPath はNSIndexPath を継承しているようで、iOS9 移行は使用されていないようです。