RealmSwift泛型查询函数提示“永远不会执行”问题求助
Hey there! Let's break down why you're seeing that "Will never be executed" warning and how to fix it properly.
Why the Warning Pops Up
The compiler is flagging this because it can't guarantee your generic type T matches the Realm object type tied to your DataType case. For example, if you call query<Product>(type: .Case, id: 1), the cast realm.objects(Case.self)... as? Results<T> will always fail (since Case and Product are different types). Because this cast is guaranteed to fail in mismatched scenarios, the compiler thinks the successful branch of your guard statement (where you call complete(true, ...)) will never run for some possible inputs.
Fixes to Resolve the Warning
There are two clean approaches to fix this, depending on whether you still need the DataType enum or not.
Option 1: Keep the DataType Enum (Make It Type-Safe)
First, update your enum to explicitly link each case to its corresponding Realm object type. This removes the need for unsafe casts:
enum DataType { case `case` case product case category case composition // Map each case to its Realm object type var associatedType: Object.Type { switch self { case .`case`: return Case.self case .product: return Product.self case .category: return Category.self case .composition: return Composition.self } } }
Then rewrite your query function to validate that the generic T matches the enum's associated type, and avoid unsafe casting:
func query<T: Object>(type: DataType, id: Int, complete: @escaping (_ success: Bool, _ results: Results<T>?, _ error: String?) -> ()) { let targetType = type.associatedType // First check if the generic T matches the enum's target type guard targetType == T.self else { complete(false, nil, "Type mismatch: Expected \(T.self), but requested \(targetType)") return } // Use parameterized filter to avoid security risks (better than string interpolation!) let results = realm.objects(targetType).filter("id = %@", id) as? Results<T> if let validResults = results { complete(true, validResults, nil) } else { complete(false, nil, "Query failed for type \(targetType)") } }
Option 2: Ditch the Enum (Use Generics Directly)
Since you're already using a generic function, the DataType enum is actually redundant. You can simplify the code by letting the generic type T directly determine which Realm object to query:
func query<T: Object>(id: Int, complete: @escaping (_ success: Bool, _ results: Results<T>?, _ error: String?) -> ()) { // No need for enum—T tells us exactly which object to query let results = realm.objects(T.self).filter("id = %@", id) complete(true, results, nil) }
To call this, just specify the generic type explicitly:
// Query a Case object with id 1 query<Case>(id: 1) { success, results, error in if let cases = results { // Handle your results here } else { // Handle error } }
Quick Note on Filter Safety
One small fix in your original code: avoid using string interpolation ("id = \(id)") in Realm filters. This can lead to unexpected behavior or security issues. Instead, use parameterized placeholders like %@ (as shown in the examples above) or NSPredicate with arguments.
内容的提问来源于stack exchange,提问作者廖豪豪

