@@ -275,7 +275,8 @@ internal class IntermediateTextInputUIView(
275275 * @return A substring of a document that falls within the specified range.
276276 */
277277 override fun textInRange (range : UITextRange ): String? {
278- return input?.textInRange(range.toTextRange())
278+ val textRange = range.toTextRange() ? : return null
279+ return input?.textInRange(textRange)
279280 }
280281
281282 /* *
@@ -285,8 +286,9 @@ internal class IntermediateTextInputUIView(
285286 * @param withText A string to replace the text in range.
286287 */
287288 override fun replaceRange (range : UITextRange , withText : String ) {
289+ val textRange = range.toTextRange() ? : return
288290 input?.withBatch {
289- input?.replaceRange(range.toTextRange() , withText)
291+ input?.replaceRange(textRange , withText)
290292 }
291293 }
292294
@@ -482,19 +484,20 @@ internal class IntermediateTextInputUIView(
482484 withinRange : UITextRange
483485 ): NSInteger {
484486 return if (usingNativeTextInput) {
485- if ( ! withinRange.isValid()) { return 0L }
487+ val withinTextRange = withinRange.toTextRange() ? : return 0L
486488 val intermediatePosition = (position as ? IntermediateTextPosition )?.position ? : 0
487- (intermediatePosition - withinRange.toTextRange() .start).toLong()
489+ (intermediatePosition - withinTextRange .start).toLong()
488490 } else 0L
489491 }
490492
491493 override fun positionWithinRangeAtCharacterOffset (
492494 range : UITextRange ,
493495 atCharacterOffset : NSInteger
494496 ): UITextPosition = if (usingNativeTextInput) {
495- val textRange = range.toTextRange()
497+ val fallback = IntermediateTextPosition (0 )
498+ val textRange = range.toTextRange() ? : return fallback
496499 (textRange.start + atCharacterOffset.toInt()).takeIf { range.isValid() && it in textRange }
497- ?.let { IntermediateTextPosition (it) } ? : IntermediateTextPosition ( 0 )
500+ ?.let { IntermediateTextPosition (it) } ? : fallback
498501 } else {
499502 IntermediateTextPosition (0 )
500503 }
@@ -503,11 +506,13 @@ internal class IntermediateTextInputUIView(
503506 range : UITextRange ,
504507 farthestInDirection : UITextLayoutDirection
505508 ): UITextPosition = if (usingNativeTextInput) {
509+ val fallback = IntermediateTextPosition (0 )
510+ val textRange = range.toTextRange() ? : return fallback
506511 PlatformTextLayoutDirection (farthestInDirection)?.let { direction ->
507- input?.positionWithinRange(range.toTextRange() , direction)?.let {
512+ input?.positionWithinRange(textRange , direction)?.let {
508513 IntermediateTextPosition (it)
509514 }
510- } ? : IntermediateTextPosition ( 0 )
515+ } ? : fallback
511516 } else {
512517 IntermediateTextPosition (0 )
513518 }
@@ -540,8 +545,10 @@ internal class IntermediateTextInputUIView(
540545
541546 override fun firstRectForRange (range : UITextRange ): CValue <CGRect > {
542547 if (usingNativeTextInput) {
543- return input?.firstSelectionRectForRange(range.toTextRange())?.asCGRect()
544- ? : CGRectZero .readValue()
548+ val fallback = CGRectZero .readValue()
549+ val textRange = range.toTextRange() ? : return fallback
550+ return input?.firstSelectionRectForRange(textRange)?.asCGRect()
551+ ? : fallback
545552 } else {
546553 return CGRectNull .readValue()
547554 }
@@ -807,7 +814,7 @@ internal class IntermediateTextInputUIView(
807814 }
808815
809816 private fun UITextRange.isValid (): Boolean {
810- val range = this .toTextRange()
817+ val range = this .toTextRange() ? : return false
811818 val textEndPos = input?.endOfDocument() ? : 0
812819 return range.start in 0 .. range.end && range.end <= textEndPos
813820 }
@@ -865,9 +872,10 @@ private class IntermediateTextRange(
865872 }
866873}
867874
868- private fun UITextRange.toTextRange (): TextRange {
869- val start = (start() as IntermediateTextPosition ).position
870- val end = (end() as IntermediateTextPosition ).position
875+ // Despite UITextRange being declared as non-null, iOS can still pass null to methods that take a UITextRange parameter.
876+ private fun UITextRange.toTextRange (): TextRange ? {
877+ val start = (start() as ? IntermediateTextPosition )?.position ? : return null
878+ val end = (end() as ? IntermediateTextPosition )?.position ? : return null
871879 return TextRange (start, end)
872880}
873881
0 commit comments