NSFetchedResultsController 中的自定义排序
花了几个小时后,我发现不可能在下面的文章中由 SQLite 支持的 NSFetchedResultsController 中进行自定义排序。
NSFetchedResultsController 自定义排序未被调用
但是,我找不到实际的解决方案我的问题。
这就是我正在尝试做的事情。
背景:
我在 CoreData 中有一个英语词典数据库(只是一个简单的单词列表 - 非常大)。使用 NSFetchedResultsController 在 UITableView 中显示单词。
UITableView 有一个关联的搜索栏。当用户在搜索栏中输入字符串时,UITableView 会显示过滤后的单词列表。
为什么我需要自定义排序:
当用户输入一个字符串时,假设它是 bre
,我将其更改为正则表达式 b.*r.*e.*
并将其用作 NSPredicate,然后,执行performFetch。这样所有像“bare”和“break”这样的词都会显示在表格视图中。
默认情况下,单词按字母顺序显示。因此,bare
将出现在 break
之前。
我希望 break
位于搜索列表中的 bare
之前,因为 break
的前三个字符与用户输入的内容完全匹配。
可能的想法:
- 将 NSFetchedResultsController 的结果复制到 NSArray 中并进行自定义排序。 我不确定 NSArray 对于像英语字典这样的大型数组来说有多快。
- 多次尝试执行Fetch。例如上面的例子,尝试按顺序执行
bre.*
、br.+e.*
、b.+r.+e.*
的performFetch并将它们结合起来。
这两种想法看起来都不太简洁。
如果您能提出任何已知的整洁和建议,我将不胜感激。此类问题的典型解决方案。
After spending hours, I found that it was not possible to do customized sort in NSFetchedResultsController backed by SQLite from following article.
NSFetchedResultsController custom sort not getting called
However, I couldn't find actual solution for my problem.
Here's what I am trying to do.
Background:
I have a English dictionary database (just a simple list of words - very large) in CoreData. Words are shown in UITableView using NSFetchedResultsController.
UITableView has an associated Search Bar. When an user inputs a string in Search Bar, UITableView shows a list of words filtered.
Why do I need customized sort:
When a user inputs a string, let's say it was bre
, I change it to regular expression, b.*r.*e.*
and use it as a NSPredicate, then, do performFetch. So that all words like 'bare' and 'break' will be shown in the table view.
By default, the words are shown as a alphabetical order. Therefore, bare
will come before break
.
I want break
to come before bare
on the searched list because the first three character of break
exactly matches to what the user input.
Possible ideas:
- Copy the result of NSFetchedResultsController into NSArray and do the custom sort.
I am not sure how fast NSArray will work for a large array like an English dictionary. - Try performFetch multiple times. For example above, try performFetch for
bre.*
,br.+e.*
,b.+r.+e.*
in order and combine them.
Both ideas don't look very neat.
I appreciate if you can suggest any known neat & typical solution for this kind of problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以考虑的另一种方法是使用瞬态属性来装饰结果以指示匹配的类型,然后使用该瞬态属性作为第一个排序描述符。
这需要循环遍历所有结果,再次比较字符串,并设置属性。如果您期望得到一长组结果,使用数组可能同样简单。
如果您需要有效地处理大型结果集,我建议使用两种排序描述符,一种仅返回精确匹配,另一种仅返回非精确匹配。然后显示第一个结果,然后显示第二个结果。使用应该可以完成的复合谓词。
Another approach you could consider is using a transient property to decorate the results to indicate the type of match, and then using that transient property as the first sort descriptor.
This requires looping through all the results, comparing the strings again, and setting the attributes. If you expect a long set of results, using an array might be just as easy.
If you need to handle large result sets efficiently, I'd suggest using two sort descriptors, one which returns only exact matches, and another which returns only non-exact matches. Then display the results from the first followed by the results from the second. With a compound predicate that should be possible to accomplish.
哇,这个问题很烦人。
我的设置如下。我有一个搜索,它接受输入并通过匹配用户名或全名来查找用户。服务器已经返回了适当的顺序,但由于我使用的是 NSFetchedResultsController,我需要一些排序描述符,这就是我所做的,似乎运行良好。我向我的用户实体添加了一个名为
matchScore
的新属性,在从服务器进行 CRUD 期间,我获得了查询 <-> 之间的MIN()
Levenshtein Distance 分数。用户名和查询<->全名我现在有一个排序描述符,它将按服务器中与用户查询最接近的匹配结果进行排序。代码是 rubymotion,但应该仍然可读。
使用新的排序描述符,我现在可以获取“不太理想”的结果,并且仍然首先保留最接近的匹配。我现在可以避免 @Jaemin 的一些潜在解决方案,这些解决方案涉及复杂的结果聚合,以避免自定义排序不起作用。
现在,比赛分数是通过服务器的 CRUD 生成的。
这是我用来获取 Levenshtein 距离的
NSString
类别。 https://gist.github.com/iloveitaly/1515464Wow, this problem was annoying.
My setup is as follows. I have a search that takes input and looks for users by matching username or full name. The server was already returning the appropriate order, but since i'm using NSFetchedResultsController I need some sort descriptor Here is what I did that seems to be working well. I added a new property to my user entity called
matchScore
and during CRUD from the server I get theMIN()
Levenshtein Distance score between the query <-> username and query <-> full nameI now have a sort descriptor that will order by the closest matching results from the server with the user's query. The code is rubymotion, but should still be readable.
With the new sort descriptor I can now fetch "less than ideal" results and still keep closest matches first. I can now avoid some of @Jaemin's potential solutions which involved complicated result aggregation to get around custom sorts not working.
The match score is now generated on CRUD from the server.
Here is the
NSString
category that I am using to get the Levenshtein distance. https://gist.github.com/iloveitaly/1515464