谓词宏不能使用 Array.contains() 构建

问题描述 投票:0回答:1

DocumentModel
包含与
TagModel
关系的标签。视图接收 selectedTag。谓词(作为 @Query 的一部分)应该过滤具有给定标签的文档。

let selectedTag = TagModel()

#Predicate<DocumentModel> { document in
   document.tags.contains {
      $0.tagID == selectedTag.tagID
   }
}

谓词未构建,因为:无法转换为闭包结果类型“任何 StandardPredicateExpression”。

谓词宏扩展为:

Foundation.Predicate<DocumentModel>({ document in
   PredicateExpressions.build_contains(
       PredicateExpressions.build_KeyPath(
           root: PredicateExpressions.build_Arg(document),
           keyPath: \.tags
       )
   ) {
       PredicateExpressions.build_Equal(
           lhs: PredicateExpressions.build_KeyPath(
               root: PredicateExpressions.build_Arg($0),
               keyPath: \.tagID
           ),
           rhs: PredicateExpressions.build_KeyPath(
               root: PredicateExpressions.build_Arg(selectedTag),
               keyPath: \.tagID
           )
       )
   }
})

完整错误消息:

无法将“PredicateExpressions.SequenceContainsWhere、PredicateExpressions.Equal、PredicateExpressions.KeyPath>>”类型的值转换为闭包结果类型“any StandardPredicateExpression”

Apple 开发人员文档 有使用

contains()
和比较字符串的示例代码:

let messagePredicate = #Predicate<Message> { message in
   message.recipients.contains {
       $0.firstName == message.sender.firstName
   }
}

如何过滤包含选定标签的文档?

swift predicate swiftdata
1个回答
0
投票

您不应该访问除

document
(传递给
#Predicate
的闭包参数)之外的任何其他属性。虽然
#Predicate
在技术上支持这一点(即宏可以扩展到某些结果),但 SwiftData 不支持。 SwiftData 只能与
StandardPredicateExpression
一起使用,而只有 some
PredicateExpression
才可以。

不要使用闭包捕获

selectedTag
,而只使用闭包捕获
selectedTag.tagID

struct SomeView: View {
    let selectedTag: TagModel
    
    @Query var documents: [DocumentModel]
    
    init(selectedTag: TagModel) {
        self.selectedTag = selectedTag
        let selectedTagID = selectedTag.tagID
        _documents = Query(filter: #Predicate<DocumentModel> { document in
            document.tags.contains {
                $0.tagID == selectedTagID
            }
        })
    }

    ...
}

你也可以直接在闭包的捕获列表中写入

selectedTagID = selectedTag.tagID

_documents = Query(filter: #Predicate<DocumentModel> { [selectedTagID = selectedTag.tagID] document in
    document.tags.contains {
        $0.tagID == selectedTagID
    }
})
© www.soinside.com 2019 - 2024. All rights reserved.