Objective-C转Swift遇类型转换错误:Range<String.Index>?无法转为NSRange
Got it, let's sort out this type conversion problem you're hitting when porting your Objective-C code to Swift.
Why the Error Happens
In Objective-C, [NSString rangeOfString:] returns an NSRange directly—even when no match is found, it gives a range with location = NSNotFound and length = 0.
But in Swift, the String.range(of:) method returns a Range<String.Index>? (an optional value). This optional is nil if no match is found, and a valid Range if it does find a match. You can't directly assign this to an NSRange variable because they're incompatible types.
Solution 1: Convert Swift Range to NSRange (if you need NSRange for other logic)
If you specifically need to work with NSRange, use the NSRange(_:in:) initializer to convert the Swift range, and handle the optional properly with guard or optional binding:
func combinedName() -> String? { // First check if we found a valid range guard let swiftRange = name.range(of: brand) else { return "\(brand) \(name)" } // Convert the Swift Range to NSRange let nsRange = NSRange(swiftRange, in: name) if nsRange.length > 0 { return name } return "\(brand) \(name)" }
Solution 2: Use Swift's Native Range Logic (Simpler Approach)
You don't actually need to convert to NSRange for this specific logic! Since a non-nil Range<String.Index> already means a match was found (so "length" is implicitly greater than 0), you can simplify the code entirely:
func combinedName() -> String? { // If the brand exists in the name, return the name as-is if name.range(of: brand) != nil { return name } // Otherwise, combine brand and name return "\(brand) \(name)" }
Or even more concise with a ternary operator:
func combinedName() -> String? { return name.range(of: brand) != nil ? name : "\(brand) \(name)" }
This matches the intent of your original Objective-C code perfectly, but follows Swift's optional handling best practices.
内容的提问来源于stack exchange,提问作者Siva

