cristik / CKPromise

ObjectiveC implementation of the Promise/A+ proposal
BSD 2-Clause "Simplified" License
5 stars 0 forks source link

object not passed through on device... #1

Open danielt1263 opened 8 years ago

danielt1263 commented 8 years ago

I have the following code:

[self makeRequestWithURL:url].success(^(NSDictionary *responseObject){
    return responseObject[@"items"][0][@"contentDetails"][@"relatedPlaylists"][@"uploads"];
}).success(^(NSString *playlistId) {
    NSLog(@"playlistId = %@", playlistId);
    NSString *urlString = [NSString stringWithFormat:@"%@playlistItems?part=snippet&maxResults=50&playlistId=%@&key=%@", youtubeAPI, playlistId, apiKey];
    NSURL *url = [NSURL URLWithString:urlString];
    return [self makeRequestWithURL:url];
}).success(^(NSDictionary *responseObject){
    weakSelf.jsonEntries = [responseObject[@"items"] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        return [obj1[@"publishedAt"] compare:obj2[@"publishedAt"]] == NSOrderedDescending;
    }];
    [weakSelf.tableView reloadData];
    [weakSelf.progressHUD hide];
}).failure(^(NSError *error){
    UIAlertView* alert = [[UIAlertView alloc] initWithTitle: NSLocalizedString(@"Alert", @"AlertTitle") message: @"There was a server error. Please try again later." delegate: nil cancelButtonTitle: NSLocalizedString(@"OK", @"") otherButtonTitles: nil];
    [alert show];
    [weakSelf.progressHUD hide];
});

Note the NSLog(@"playlistId = %@", playlistId); line...

On the simulator, the playlistId is the correct value (an NSString,) but on the device it's an NSDictionary. Again, this code works on the simulator, but not the device. Any help?

cristiankocza-sv commented 8 years ago

Hmm... that's strange, the promise behaviour should be the same on device as on simulator. Could it be that the actual responseObject is different on the device, thus causing the malfunction?

danielt1263 commented 8 years ago

The response object is identical in both cases. I worked around the issue by rolling the first two success blocks into one, but I don't think I should have to do that.

cristik commented 8 years ago

Just tried with a hardcoded makeRequestWithURL: that returns a dictionary containing the key path you are using, and on both simulator and device the promise behaved the same. Could you give some more context of the called code, i.e. the makeRequestWithURL: method? I'm interested with the places in code you are resolving/rejecting the promise.

danielt1263 commented 8 years ago

I'm using AFNetworking and calling into the YouTube v3 API.

Here is my makeRequestWithURL: method:

- (CKPromise *)makeRequestWithURL:(NSURL *)url {
    CKPromise *result = [[CKPromise alloc] init];
    AFJSONRequestOperation *jsonRequest = [[AFJSONRequestOperation alloc] initWithRequest: [NSURLRequest requestWithURL: url]];
    [self.requests addObject:jsonRequest];
    [jsonRequest setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        [result resolve:responseObject];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        [result reject:error];
    }];
    [jsonRequest start];
    return result;
}

The initial URL:

NSString *urlString = [NSString stringWithFormat:@"https://www.googleapis.com/youtube/v3/channels?part=contentDetails&forUsername=%@&key=%@", channel, apiKey];
NSURL *url = [NSURL URLWithString:urlString];
cristik commented 8 years ago

The code looks legit, you should have no problems. Are you using the latest CKPromise version?

danielt1263 commented 8 years ago

I'm installing v1.4.6 from cocoapods. CKPromise is working everywhere else I'm using it.... and the code below works so I'm good.

[self makeRequestWithURL:url].success(^(NSDictionary *responseObject){
    NSString *playlistId = responseObject[@"items"][0][@"contentDetails"][@"relatedPlaylists"][@"uploads"];
    NSString *urlString = [NSString stringWithFormat:@"%@playlistItems?part=snippet&maxResults=50&playlistId=%@&key=%@", youtubeAPI, playlistId, apiKey];
    NSURL *url = [NSURL URLWithString:urlString];
    return [self makeRequestWithURL:url];
}).success(^(NSDictionary *responseObject){
    weakSelf.jsonEntries = [responseObject[@"items"] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        return [obj1[@"publishedAt"] compare:obj2[@"publishedAt"]] == NSOrderedDescending;
    }];
    [weakSelf.tableView reloadData];
    [weakSelf.progressHUD hide];
}).failure(^(NSError *error){
    UIAlertView* alert = [[UIAlertView alloc] initWithTitle: NSLocalizedString(@"Alert", @"AlertTitle") message: @"There was a server error. Please try again later." delegate: nil cancelButtonTitle: NSLocalizedString(@"OK", @"") otherButtonTitles: nil];
    [alert show];
    [weakSelf.progressHUD hide];
});
cristik commented 8 years ago

It's very strange that it doesn't work for you, I tried with the youtube API and got the behaviour as expected, even with the first implementation (no dictionary instead of string). However this problems inspired me to add a new feature: block signature check and exception throwing if the promise is resolved with another value than the block expects.