Выполнение цикла for вокруг блока SPTRequest с помощью Spotify iOS SDK 3.0

#ios #spotify

#iOS #spotify

Вопрос:

Я запускаю цикл for вокруг блока, который запрашивает данные с серверов Spotify. При вызове tracksLoaded иногда все выполняется внутри блока, а в других случаях пропускается один или несколько запросов. Переход в спящий режим улучшает ситуацию, но я почти уверен, что должен быть лучший способ справиться с этим.

 //From each given array of countryURLs, generate a playlist of songs
- (void)generatePlaylistFromURL:(NSMutableArray *)countryURLS {

NSMutableArray *regionPlaylist = [[NSMutableArray alloc] init];

//loop through all the Countries in one Region
for (int k=0; k<[countryURLS count]; k  ) {
    sleep(.2);
    //request playlist from Country URI
    [SPTRequest requestItemAtURI:[NSURL URLWithString:[@"spotify:user:funkytrumpet:playlist:" stringByAppendingString:[[countryURLS objectAtIndex:k] componentsSeparatedByString:@"/"][6]]]
                        withSession:session
                        callback:^(NSError *error, id object) {

                        if (error != nil) {
                            NSLog(@"*** Playlist lookup got error %@", error);
                            NSLog(@"id of playlist error:%@", [[countryURLS objectAtIndex:k] componentsSeparatedByString:@"/"][6]);
                            return;
                        }

                            //loop through all tracks in one Country and create array of track URIs
                            for (int i = 0; i < [[[object firstTrackPage] items] count]; i  ) {

                                //NSLog(@"playlist: %@", [[[object firstTrackPage] items] objectAtIndex:(i)]);


                                [regionPlaylist addObject:[[[object firstTrackPage] items] objectAtIndex:(i)]];


                            }


                            //only play next track if this is the last album to load
                            if (k == ([countryURLS count]-1)) {
                                [self tracksLoaded:(regionPlaylist)];
                            }


    }];



}
  

}

Ответ №1:

Да, спать ужасно. На ум приходят два решения.

Во-первых, необходимо последовательно загружать URL-адреса, используя то, что можно в некотором роде описать как асинхронный рекурсивный цикл. Псевдокод (не ожидайте, что он будет компилироваться, но вы должны уловить идею):

 @property (nonatomic, readwrite) NSMutableArray *urisToLoad;
@property (nonatomic, readwrite) NSMutableArray *loadedObjects;

-(void)viewDidLoad {
    self.loadedObjects = [NSMutableArray new];
    self.urisToLoad = …;
    [self recursivelyLoadObjects];
}

-(void)recursivelyLoadObjects {

    if (self.urisToLoad.count == 0) {
        [self objectsDone];
        return;
    }

    id nextURI = self.urisToLoad[0];
    [self.urisToLoad removeObjectAtIndex:0];

    [SPTRequest requestItemAtURI:nextURI
                     withSession:session
                        callback:^(NSError *error, id object) {

        // You should probably error check and stuff here.
        [self.loadedObjects addObject:object];
        [self recursivelyLoadObjects];
    }];

}

-(void)objectsDone {
    // All of the objects are now loaded (or failed to load)
    NSLog(@"%@", self.loadedObjects);
}
  

Второе решение — изучить реактивное программирование с использованием библиотеки, подобной ReactiveCocoa. Вы можете настроить цепочку сигналов, которые загружают каждый URI, а затем получать уведомления, когда все сигналы сработают.

Комментарии:

1. Спасибо, я внедрил рекурсивную опцию, и она работает хорошо.

2. Круто, приятно знать. Пожалуйста, поддержите / примите этот ответ как правильный!