noki雑記

iOS、ときどきAndroid

iOS8 を含むSwift3対応時の不具合対応

Swift 2.1 から 3 へ移行する際に、大きな不具合が1つあったので、その対応を考えてみました。
※ ただし、多くの端末・バージョンで検証したものではありません。

問題

UITableViewDelegate の table​View(_:​height​For​Row​At:​) に渡される indexPath の値が間違っていました。具体的には、indexPath.row の値が、0, 1, 2, 3, … の順番で渡されるはずが、0, 0, 1, 2, … とずれてしまっていました。いざ表示してみると問題ないように見えるのですが、画面遷移時にレイアウトが崩れてしまいます。

不具合の内容や対応方法に関しては、こちらを参考にさせていただきました。

期待する動作

今回は、「table​View(_:​height​For​Row​At:​) で正しい値を取得する」ということでやってみます。

対応

まずはコードを貼ります。

Objective-C の Method Swizzling という、既存のメソッドを入れ替える機能を利用しました。Swift から Objective-C のコードを扱う方法は省きます。

まず参考サイトのように、問題となっている箇所を探っていくと、iOS8の UIMutableIndexPath *1get​Indexes:​range:​ で取得できる値が間違っている可能性があることがわかりました。しかし、UIMutableIndexPath は開発者側には非公開となっているので、直接書き換えることができませんでした。そのため、NSIndexPath の get​Indexes:​range:​ の値を正しい値を取得できる index​At​Position:​ で書き換えたところ、うまく動作しました。

まとめ

今回は、iOS 8 のtable​View(_:​height​For​Row​At:​) で渡される indexPath の値が間違っていることに対し、Objective-C のコードで不具合のあるメソッドを書き換え、正しい値を返す対応を考えてみました。

ただ、やはりこの不具合は怖いので、Swift3 対応をリリースする際にはなるべく iOS8 は切りたいと思っています。

*1:憶測ですが、UIMutableIndexPath はNSIndexPath を継承しているようで、iOS9 移行は使用されていないようです。