0

The following code runs great and gives me the results I am looking for. However, I would like to run it in its own thread. Is MPMediaQuery thread safe, and what am I doing wrong, if it is?

-(NSArray*) mediaItemsFromPersistentIds:(NSArray*) mediaPersistentIds
{
    if (debug==1) {
        NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));
    }

       MPMediaQuery *mediaQuery = [MPMediaQuery new];
       NSArray *itemsmediaQuery = mediaQuery.items;
       NSPredicate *predicate   = [NSPredicate predicateWithFormat:@"%K IN %@", @"itemId", mediaPersistentIds];

    return [itemsmediaQuery filteredArrayUsingPredicate:predicate];
}

When I try the following, I get

Terminating app due to uncaught exception 'MPMediaItemCollectionInitException', reason: 'items array must not be empty'

I know the [itemsmediaQuery filteredArrayUsingPredicate:predicate] is being returned as (null)

-(NSArray*) mediaItemsFromPersistentIds:(NSArray*) mediaPersistentIds
{
    if (debug==1) {
        NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));
    }
    __block NSArray *itemsmediaQuery;
    __block NSPredicate *predicate;

    dispatch_queue_t mediaQueryQueue = dispatch_queue_create("media query", NULL);
    dispatch_async(mediaQueryQueue, ^{

        MPMediaQuery *mediaQuery      = [MPMediaQuery new];
        itemsmediaQuery = mediaQuery.items;
        predicate = [NSPredicate predicateWithFormat:@"%K IN %@", @"itemId", mediaPersistentIds];

    });

    return [itemsmediaQuery filteredArrayUsingPredicate:predicate];
}
Marco
  • 6,692
  • 2
  • 27
  • 38
Paul S.
  • 1,342
  • 4
  • 22
  • 43

1 Answers1

2

It is safe to request these items in the background.

Right now, you're not actually running the query in the background. You could do something like this:

- (void)mediaItemsFromPersistentIds:(NSArray*)ids
                           callback:(void (^)(NSArray *items))callback {
    dispatch_queue_t mediaQueryQueue = dispatch_queue_create("media query", NULL);
    dispatch_async(mediaQueryQueue, ^{
        MPMediaQuery *mediaQuery = [MPMediaQuery new];
        itemsmediaQuery = mediaQuery.items;
        predicate = [NSPredicate predicateWithFormat:@"%K IN %@", @"itemId", ids];

        // Do the query
        NSArray *items = [itemsmediaQuery filteredArrayUsingPredicate:predicate];

        // Post the query results to the main thread in some way
        dispatch_async(dispatch_get_main_queue(), ^{
            // You could pass this off to a delegate or callback block
            if (callback)
                callback(items);
        });
    });
}

And to call it:

NSArray *ids = ...
[someObj mediaItemsFromPersistentIds:ids callback:^(NSArray *items) {
    // Do something with `items`
}];
drhr
  • 2,261
  • 2
  • 17
  • 35
  • Thanks for the reply. How do I return the NSArray *items, like in my example above? This method returns an NSArray. Thanks again for the help, I appreciate it. – Paul S. Feb 03 '14 at 00:34
  • Added some more detail – drhr Feb 03 '14 at 03:06
  • I implemented the following: `NSArray *ids = [self mediaItemsFromPersistentIds:collection callback:^(NSArray *items) { MPMediaItemCollection *mediaCollection = [MPMediaItemCollection collectionWithItems:items]; [_musicPlayer setQueueWithItemCollection:mediaCollection]; }];` and get the following error: Initializing 'NSArray *__strong' with an expression of incompatible type 'void' I resolved this by removing the `NSArray *ids = ` Seems to work great now. Thanks for the help. – Paul S. Feb 03 '14 at 13:06