Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS Build a Photo Browser iPhone App Gestures Introducing Gesture Recognizers

Kevin Daniel Pantasdo
Kevin Daniel Pantasdo
6,369 Points

App did not ask permission for likes

After deleting the app in the simulator and running the code again, the app requires me to sign in. So far so good.

However, after singing in, app did not ask permission to like.. Thus even after including the options:@{@"scope" : @[@"likes"]} in the simpleAuth, status code is still 400. Does that mean that there is something wrong with my code regarding the syntax?

Most likely if error code is 400, it has to be in the THPhotoCell implementation right? But I have proofread the code letter by letter and I'm pretty sure there's nothing wrong.

Kevin Daniel Pantasdo
Kevin Daniel Pantasdo
6,369 Points

As I have mentioned, status code is 400 and instagram won't ask permission to like...

This is my code:

PhotosViewController.m

#import "PhotosViewController.h"
#import "PhotoCell.h"
#import <SimpleAuth/SimpleAuth.h>

@interface PhotosViewController ()

@property (nonatomic) NSString *accessToken;
@property (nonatomic) NSArray *photos;

@end

@implementation PhotosViewController

- (instancetype)init
{
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
    layout.itemSize = CGSizeMake(106.0, 106.0);
    layout.minimumInteritemSpacing = 1.0;
    layout.minimumLineSpacing = 1.0;

    return (self = [super initWithCollectionViewLayout:layout]);

}

- (void) viewDidLoad {
    [super viewDidLoad];

    self.title = @"Photo Bombers";

    [self.collectionView registerClass:[PhotoCell class] forCellWithReuseIdentifier:@"photo"];
    self.collectionView.backgroundColor = [UIColor whiteColor];

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    self.accessToken = [userDefaults objectForKey:@"accessToken"];

    if (self.accessToken == nil){
        [SimpleAuth authorize:@"instagram" options:@{@"scope": @[@"likes"]} completion:^(NSDictionary *responseObject, NSError *error) {
            self.accessToken = responseObject[@"credentials"][@"token"];
            [userDefaults setObject:self.accessToken forKey:@"accessToken"];
            [userDefaults synchronize];

            [self refresh];

        }];
    }else{
        [self refresh];
    }

}

-(void) refresh {
        NSURLSession *session  = [NSURLSession sharedSession];
        NSString *urlString = [[NSString alloc] initWithFormat:@"https://api.instagram.com/v1/tags/photobomb/media/recent?access_token=%@", self.accessToken];
        NSURL *url = [[NSURL alloc] initWithString:urlString];
        NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
        NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
            NSData *data = [[NSData alloc] initWithContentsOfURL:location];
            NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];

            self.photos = [responseDictionary valueForKeyPath:@"data"];

            dispatch_async(dispatch_get_main_queue(), ^{
                [self.collectionView reloadData];
            });
        }];
        [downloadTask resume];
}

-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return [self.photos count];
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    PhotoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"photo" forIndexPath:indexPath];
    cell.backgroundColor = [UIColor lightGrayColor];

    cell.photo = self.photos[indexPath.row];

    return cell;
}

@end

PhotoCell.m

#import "PhotoCell.h"
#import <SAMCache/SAMCache.h>

@implementation PhotoCell


//Override setter method

-(void)setPhoto:(NSDictionary *)photo {
    _photo = photo;
    NSURL *url = [[NSURL alloc] initWithString:_photo[@"images"][@"thumbnail"][@"url"]];
    [self downloadPhotoWithURL:url];
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.imageView = [[UIImageView alloc] init];

        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(like)];
        tap.numberOfTapsRequired = 2;
        [self addGestureRecognizer:tap];

        [self.contentView addSubview:self.imageView];
    }
    return self;
}

-(void) layoutSubviews{
    [super layoutSubviews];
    self.imageView.frame = self.contentView.bounds;
}

-(void) downloadPhotoWithURL:(NSURL *) url{

    NSString *key = [[NSString alloc] initWithFormat:@"%@-thumbnail",self.photo[@"id"]];
    UIImage *photo = [[SAMCache sharedCache] imageForKey:key];

    if (photo) {
        self.imageView.image = photo;
        return;
    }
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {

        NSData *data = [[NSData alloc] initWithContentsOfURL:location];
        UIImage *image = [[UIImage alloc] initWithData:data];

        [[SAMCache sharedCache] setImage:image forKey:key];


        dispatch_async(dispatch_get_main_queue(), ^{
            self.imageView.image = image;
        });
    }];
    [downloadTask resume];

}

- (void) like {
    NSLog(@"Link: %@", self.photo[@"Link"]);
    NSURLSession *session = [NSURLSession sharedSession];
    NSString *accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"accessToken"];
    NSString *urlString = [[NSString alloc] initWithFormat:@"https://api.instagram.com/v1/media/%@/likes?access_token=%@", self.photo[@"id"], accessToken];
    NSURL *url = [[NSURL alloc] initWithString:urlString];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
    request.HTTPMethod = @"Post";
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            NSLog(@"response %@", response);
            NSLog(@"data %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }];
    [task resume];

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Liked!" message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:nil];
    [alert show];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [alert dismissWithClickedButtonIndex:0 animated:YES];
    });


}

@end

See this post about Instagram's new API endpoints policy. https://teamtreehouse.com/forum/instagram-api-changes

Basically, they are no longer allowing you to make POST requests for likes without applying and getting approved. I would suggest just observing the material covered in these videos concerning HTTP requests via endpoints and not worrying too much about the fact that your app isn't ACTUALLY liking the photos on Instagram's side.