LoginSignup
3
0

More than 5 years have passed since last update.

いまさらNSMutableAttributedStringでRange or index out of bounds

Last updated at Posted at 2016-11-10

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSConcreteTextStorage attribute:atIndex:effectiveRange:]: Range or index out of bounds' ***

UITableView 上に Custom Cell を作成して、NSMutableAttributedStringを装飾して使用していました。

部分的に下記のコードで、

cell.bodyTextView.attributedText = nil

表示非表示を対応していましたが。。。
該当のCellを選択するとがRange or index out of boundsでcrushしてしまう不具合が派生していました。

答えは特殊な設定にありました。

// NOTE: リンクのみ選択を許可
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let glyphIndex = self.layoutManager.glyphIndex(for: point, in: self.textContainer)
        let characterIndex = self.layoutManager.characterIndexForGlyph(at: glyphIndex)
        // NOTE: textStorageが空の場合でcrashする
        guard let _ = self.textStorage.attribute(NSLinkAttributeName, at: characterIndex, effectiveRange: nil) else {
            return nil
        }

        return self
}

cellの選択とリンクの選択を取得する為にhitTestでtextStorage内のテキストを判定していた為でした。

// NOTE: リンクのみ選択を許可
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let glyphIndex = self.layoutManager.glyphIndex(for: point, in: self.textContainer)
        let characterIndex = self.layoutManager.characterIndexForGlyph(at: glyphIndex)
        // NOTE: textStorageが空の場合でcrashする
        if self.text.isEmpty {
            return nil
        }

        guard let _ = self.textStorage.attribute(NSLinkAttributeName, at: characterIndex, effectiveRange: nil) else {
            return nil
        }

        return self
}

予期しないcrashが多発する辛い事象でした。。

3
0
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
3
0