gpt4 book ai didi

ios - 如何在获取歌曲列表的所有 Persistent ID 和 Assets URL 时防止设备挂起?

转载 作者:行者123 更新时间:2023-11-28 19:55:26 25 4
gpt4 key购买 nike

我想要一组来自歌曲列表的持久 ID。我知道如何获取任何歌曲的持久 ID,但是一首检索 MPMediaItem 并获取它们的持久 ID 会花费大量时间并挂起设备。

我检索持久性 id 的代码:

for (MPMediaItem *item in itemArray) {
NSURL *assetUrl = [item valueForProperty:MPMediaItemPropertyAssetURL];
NSNumber *persistentID = [item valueForProperty:MPMediaItemPropertyPersistentID];
if (assetUrl != nil) {
[localMedias addObject:assetUrl];
[saveQueue addToQueue:persistentID];
}
}

当歌曲列表超过 500 首歌曲时挂起设备。

最佳答案

理想情况下,您执行的任何挂起设备的操作都应该在后台队列中执行。有两种方法可以做到这一点:Grand Central Dispatch (GCD)NSOperationQueues .由于我们不需要 NSOperationQueue 提供的任何额外功能来解决您的问题,因此我们将使用 GCD。

首先,让我们在后台队列上执行您的代码。

// show user that app is doing background work somehow

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (MPMediaItem *item in itemArray) {
NSURL *assetUrl = [item valueForProperty:MPMediaItemPropertyAssetURL];
NSNumber *persistentID = [item valueForProperty:MPMediaItemPropertyPersistentID];
if (assetUrl != nil) {
[localMedias addObject:assetUrl];
[saveQueue addToQueue:persistentID];
}
}

dispatch_async(dispatch_get_main_queue(), ^{
// update UI to show user background work is done
});
});

这将防止设备挂起,但它并不完美。如果我们想在多个位置执行此任务,我们将以复制粘贴代码结束,which is bad .因此,让我们将其包装在一个方法中。

-(void)fetchPersistentIDsFromSongList {
// show user that app is doing background work somehow

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (MPMediaItem *item in itemArray) {
NSURL *assetUrl = [item valueForProperty:MPMediaItemPropertyAssetURL];
NSNumber *persistentID = [item valueForProperty:MPMediaItemPropertyPersistentID];
if (assetUrl != nil) {
[localMedias addObject:assetUrl];
[saveQueue addToQueue:persistentID];
}
}

dispatch_async(dispatch_get_main_queue(), ^{
// update UI to show user background work is done
});
});
}

但是,我们在这里遇到了一些问题。如果我们调用此方法,我们无法保证在下一行代码运行之前获取将完成(有关更多详细信息,请参见 dispatch_async)。此外,假设 localMedias 是一个 NSMutableArray,在获取过程中从中获取项目可能不安全。我们需要的是一种判断提取是否已完成的方法,但我们仍然需要提取本身在后台队列上执行。我们需要的是以 block 的形式向我们的方法添加一个完成处理程序。 . ( See here for block syntax. ) 此外,为了防止读/写冲突,我们不会在获取完全完成之前返回数组。但是因为我们是异步执行所有操作,所以我们不能使用常规的 return 语句返回它,所以我们将把它作为参数传递给完成 block 。

-(void)fetchPersistentIDsFromSongListWithCompletion:(void (^)(NSArray *results))completion {
// show user that app is doing background work somehow

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// initialize container for results
NSMutableArray *localMedias = [[NSMutableArray alloc] initWithCapacity:[itemArray count]];

// fetch persistent ID from each item and save to results array
for (MPMediaItem *item in itemArray) {
NSURL *assetUrl = [item valueForProperty:MPMediaItemPropertyAssetURL];
NSNumber *persistentID = [item valueForProperty:MPMediaItemPropertyPersistentID];
if (assetUrl != nil) {
[localMedias addObject:assetUrl];
[saveQueue addToQueue:persistentID];
}
}

// perform completion block and update UI
dispatch_async(dispatch_get_main_queue(), ^{
// update UI to show user background work is done

if(completion) {
completion(localMedias);
}
});
});
}

现在您可以调用此方法,将结果保存在完成 block 中,并确保免受多线程可能导致的可怕调试情况的影响。此外,关于完成处理程序,我看到的一般约定是在主队列上执行所有完成 block ,除非您在方法中指定一个队列作为参数,在这种情况下,应该在该队列上执行完成 block 。

[self fetchPersistentIDsFromSongListWithCompletion:^void (NSArray *results){
// assume self.songIDs exists and is an NSArray
self.songIDs = [results copy];
}];

关于ios - 如何在获取歌曲列表的所有 Persistent ID 和 Assets URL 时防止设备挂起?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26797491/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com