Ios Swift中的核心数据:比较for循环中的对象
我试图通过检查MPMediaItemPropertyPlayCount自上次检查以来是否有任何更改来更新用户的音乐播放历史记录。现在,每次检查时,我都会查询整个iPod库,并比较核心数据中已有的播放次数。如果当前播放计数!=播放计数存储在核心数据中,我们对这首歌做了一些处理,因为我们知道用户最近听过这首歌 在我的代码中,我正在努力循环浏览所有iPod歌曲,同时搜索相应的核心数据对象。下面的代码打印的行太多了。如何在Ios Swift中的核心数据:比较for循环中的对象,ios,swift,for-loop,core-data,Ios,Swift,For Loop,Core Data,我试图通过检查MPMediaItemPropertyPlayCount自上次检查以来是否有任何更改来更新用户的音乐播放历史记录。现在,每次检查时,我都会查询整个iPod库,并比较核心数据中已有的播放次数。如果当前播放计数!=播放计数存储在核心数据中,我们对这首歌做了一些处理,因为我们知道用户最近听过这首歌 在我的代码中,我正在努力循环浏览所有iPod歌曲,同时搜索相应的核心数据对象。下面的代码打印的行太多了。如何在for循环中搜索核心数据中的对象 class func checkiPodSong
for
循环中搜索核心数据中的对象
class func checkiPodSongsForUpdate() {
var appDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
var context: NSManagedObjectContext = appDel.managedObjectContext!
var newSong = NSEntityDescription.insertNewObjectForEntityForName("IPodSongs", inManagedObjectContext: context) as! NSManagedObject
var request = NSFetchRequest(entityName: "IPodSongs")
request.returnsObjectsAsFaults = false
var results = context.executeFetchRequest(request, error: nil)
let query = MPMediaQuery.songsQuery()
let queryResult = query.collections as! [MPMediaItemCollection]
for song in queryResult {
for song in song.items as! [MPMediaItem] {
request.predicate = NSPredicate(format: "title = %@", "\(song.valueForProperty(MPMediaItemPropertyTitle))")
for result: AnyObject in results! {
if let playCount = result.valueForKey("playCount") as? String {
if playCount != "\(song.valueForProperty(MPMediaItemPropertyPlayCount))" {
println("\(song.valueForProperty(MPMediaItemPropertyTitle)) has a new play count.")
} else {
println("User hasn't listened to this song since last check.")
}
}
}
}
}
}
直接的问题是您为
request.predicate
赋值,但这样做没有效果。获取请求谓词只有在执行获取之前分配它时才有效。它成为获取的一部分,获取结果只包含与谓词匹配的对象
解决此特定问题有两种可能性:
request.predicate
,而是通过执行以下操作过滤内存中的结果
数组
let predicate = NSPredicate(format: "title = %@", "\(song.valueForProperty(MPMediaItemPropertyTitle))")
let currentResults = results.filteredArrayUsingPredicate(predicate)
这将得到一个只包含与谓词匹配的歌曲的数组。这将比选项1更快,但仍然存在一个主要问题,即您在此处获取所有歌曲。这可能意味着每次调用此函数时都会将大量托管对象加载到内存中(假设用户有50000首歌曲?)。这仍然不是一个好的解决方案。不幸的是,我对MPMediaQuery
了解不够,无法推荐更好的方法这两种方法都可以解决眼前的问题,但您需要解决更重要的概念问题。您正在比较两个潜在的大型集合,以查找单个匹配项。这将需要大量的CPU时间或内存,或者两者兼而有之,不管你如何处理。找到了我自己的解决方案。正如@Tom所说,如果每个数组中有足够的对象,在两个数组中循环可能会很昂贵。我决定在
arrayOne
中循环,并在该循环中调用一个自定义函数,该函数在arrayTwo
中查找给定的键/值对
// Custom function that returns Bool if arrayTwo contains a given key/value pair from inside the arrayOne loop
func arrayContains(array:[[String:String]], #key: String, #value: String) -> Bool {
for song in array {
if song[key] == value {
return true
}
}
return false
}
非常感谢@vacawama在此提供的帮助:谢谢你的回答,汤姆。但是我不能使用类型为
NSPredicate
的参数列表调用filteradarayusingpredicate
。您更广泛的想法是将核心数据搜索结果存储在一个字典中(我将为每首歌曲提供标题、艺术家和播放计数),然后使用MPMediaQuery
循环该字典?我不知道不能使用NSPredicate
参数调用filteradarayusingpredicate
是什么意思。这是调用该方法的唯一方法。不,我没有提到像你描述的那样使用字典,我也不推荐。我确实建议您尝试找到一个比您尝试比较两个大型对象集合更好的解决方案。我正在删除request.predicate
行,并将其替换为您的建议,我得到了错误。这在Xcode中真的适用吗?这对我来说当然是有道理的,只是我不明白为什么我会犯这样的错误。