I have a collectionView of Photos, when the photo is tapped it should show a detail view of that photo.
The problem is, the first photo I tap doesn't do anything, and then every tap after works except it shows the photo tapped two times ago.
For example:
Tap Photo 1... does nothing.
Tap Photo 2... shows Photo 1.
Tap Photo 6... shows Photo 2.
Thanks for the help!
ViewController.m
#property (nonatomic) NSArray *photos;
- (void)viewDidLoad
{
[super viewDidLoad];
[self.collectionView registerClass:[BlissPhotoCell class]
forCellWithReuseIdentifier:#"photo"];
NSURLSession *session = [NSURLSession sharedSession];
NSString *urlString = [[NSString alloc] initWithFormat:#"https://api.instagram.com/v1/;
NSURL *url = [[NSURL alloc]initWithString:urlString];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
NSString *text = [[NSString alloc] initWithContentsOfURL:location encoding:NSUTF8StringEncoding error:nil];
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];
});
}];
[task resume];
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *photo = self.photos[indexPath.row];
BlissDetailViewController *viewController = [[BlissDetailViewController alloc] init];
viewController.modalPresentationStyle = UIModalPresentationCustom;
viewController.transitioningDelegate = self;
viewController.photo = photo;
[self presentViewController:viewController animated:YES completion:nil];
}
BlissPresentDetailTransition.h
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
UIViewController *detail = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *containerView = [transitionContext containerView];
detail.view.alpha = 0.0;
CGRect frame = containerView.bounds;
frame.origin.y += 20.0;
frame.size.height -= 20.0;
detail.view.frame = frame;
[containerView addSubview:detail.view];
[UIView animateWithDuration:0.3 animations:^{
detail.view.alpha = 1.0;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
return 0.3;
}
You inadvertently implemented didDeselect rather than didSelect. It's an easy mistake to make if you use auto completion when you type since didDeselect comes up first alphabetically.
Related
I making here simple application on XCODE 7.1. I just display 2 label and 1 image in tableview cell.I am parsing data from this URL. I am simply load data in TableviewHere i put the code of ViewController.m file
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.alpha = 1.0;
[self.view addSubview:activityIndicator];
activityIndicator.center = CGPointMake([[UIScreen mainScreen]bounds].size.width/2, [[UIScreen mainScreen]bounds].size.height/2);
[activityIndicator startAnimating];//to start animating
// Do any additional setup after loading the view, typically from a nib.
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:#"http://www.androidbegin.com/tutorial/jsonparsetutorial.txt"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(#"Error: %#", error);
} else {
[activityIndicator stopAnimating];
_responsedic = (NSDictionary*) responseObject;
_Worldpopulation = [_responsedic valueForKey:#"worldpopulation"];
_imageURL = [_Worldpopulation valueForKey:#"flag"];
_country = [_Worldpopulation valueForKey:#"country"];
_population = [_Worldpopulation valueForKey:#"population"];
NSLog(#"Data:%#",_imageURL);
NSLog(#"Population",_population);
NSLog(#"Country",_country);
// NSLog(#"%#",_MovieList);
//NSLog(#"Array: %#",_imageURL);
//NSLog(#"%#",responseObject);
}
}];
[dataTask resume];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 10;
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *Identifier = #"mycell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Identifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:Identifier];
// Set and load the images
[cell.imageView sd_setImageWithURL:[_imageURL objectAtIndex:indexPath.row] placeholderImage:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
// Get rid of the activity indicator when the image has been loaded
}];
cell.textLabel.text = [_country objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [_population objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//NSString *rowValue = self.friends[indexPath.row+1];
NSString *message = [[NSString alloc] initWithFormat:#"You selected %#",[_country objectAtIndex:indexPath.row]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"YOU SELECT"
message:message
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
I am using AFNetworking 3.0 and SDWebImage for image loading.Data parse successfully and and displayed in tableview.I attached screenshot below
Problem is what the all data are not displayed in the tableview cell i also put the Alert dialog on each cell of tableview data successfully loaded but not displayed in cell. I search everywhere i can't find solution for this i am using 3G connection so net speed is not an issue Please someone help.
Try to reload table view with updated data in completion block.
NSURL *URL = [NSURL URLWithString:#"http://www.androidbegin.com/tutorial/jsonparsetutorial.txt"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(#"Error: %#", error);
} else {
[activityIndicator stopAnimating];
_responsedic = (NSDictionary*) responseObject;
_Worldpopulation = [_responsedic valueForKey:#"worldpopulation"];
_imageURL = [_Worldpopulation valueForKey:#"flag"];
_country = [_Worldpopulation valueForKey:#"country"];
_population = [_Worldpopulation valueForKey:#"population"];
NSLog(#"Data:%#",_imageURL);
NSLog(#"Population",_population);
NSLog(#"Country",_country);
// NSLog(#"%#",_MovieList);
//NSLog(#"Array: %#",_imageURL);
//NSLog(#"%#",responseObject);
//Added Code -> Reloading data on Main queue for update
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableview reloadData];
});
}
}];
[dataTask resume];
Hope, it'll help you.
Thanks.
1) Parse Data and after getting data relaod table
-(void)ParseData
{
NSURLSession * session = [NSURLSession sharedSession];
NSURL * url = [NSURL URLWithString: #"http://www.androidbegin.com/tutorial/jsonparsetutorial.txt"];
//Create URLReques
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[request addValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
// Set Method POST/GET
[request setHTTPMethod:#"GET"];
// Asynchronously Api is hit here
NSURLSessionDataTask* dataTask=[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!error) //If error nil
{
//Serialization data
NSDictionary * json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"json %#",json);
array=[json valueForKey:#"worldpopulation"];
dispatch_async(dispatch_get_main_queue(), ^(void) {
if(array.count!=0)
{
//Reload table View
[_tblView reloadData];
}
});
}
else
{
//failure;
}
}];
[dataTask resume] ; // Executed task
}
2) Table View DataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(array.count!=0)
{
return [array count];
}
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell;
//= [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.backgroundColor =[UIColor whiteColor];
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
UILabel *lblCountry=(UILabel*)[cell viewWithTag:2];
lblCountry.text= [[array objectAtIndex:indexPath.row]valueForKey:#"country"];
UILabel *lblPopulation=(UILabel*)[cell viewWithTag:3];
lblPopulation.text= [[array objectAtIndex:indexPath.row]valueForKey:#"population"];
UIImageView *img = (UIImageView *)[cell viewWithTag:1];
[img setImageWithURL:[NSURL URLWithString:[[array objectAtIndex:indexPath.row]valueForKey:#"flag"]]];
return cell;
}
I'm creating an app with a Newsfeed as a UICollectionView however it doesn't seem to update when I change the JSON file. I am using a UIRefreshControl to refresh it but I can't tell if my issue is to do with this or to do with how the JSON is read (or something else entirely).
viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.navigationItem.title = #"News";
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(0,0,23,16);
[btn setBackgroundImage:[UIImage imageNamed:#"menuImage.png"] forState:UIControlStateNormal];
[btn addTarget:(NavigationViewController *)self.navigationController action:#selector(showMenu) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barBtn = [[UIBarButtonItem alloc] initWithCustomView:btn];
self.navigationItem.leftBarButtonItem = barBtn;
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:config
delegate:self
delegateQueue:nil];
[self fetchFeed];
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat frameWidth = screenRect.size.width - 20;
CGFloat frameHeight = screenRect.size.height - 20;
_collectionView=[[UICollectionView alloc] initWithFrame:CGRectMake(10, 10, frameWidth, frameHeight) collectionViewLayout:layout];
[_collectionView setDataSource: self];
[_collectionView setDelegate: self];
[_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[_collectionView setBackgroundColor:[UIColor clearColor]];
[self.view addSubview:_collectionView];
UIRefreshControl * refreshControl = [[UIRefreshControl alloc] init];
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:#"Refresh Images"];
[_collectionView addSubview:refreshControl];
[refreshControl addTarget:self action:#selector(refresh:) forControlEvents:UIControlEventValueChanged];
[self.collectionView reloadItemsAtIndexPaths:[self.collectionView indexPathsForVisibleItems]];
[self.collectionView reloadData];
}
fetchFeed
- (void)fetchFeed
{
NSString *requestString = #"http://www.jameslester.xyz/example.json";
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:req
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data
options:0
error:nil];
self.articles = jsonObject[#"articles"];
NSLog(#"%#", self.articles);
NSLog(#"Feed Fetched!!!");
dispatch_async(dispatch_get_main_queue(), ^{[self.collectionView reloadData];
});
}];
[dataTask resume];
}
refresh
- (void)refresh:(id)sender
{
[self fetchFeed];
[(UIRefreshControl *)sender endRefreshing];
NSLog(#"Refreshed");
}
Any help will be really appreciated.
Collection View Data Source
#define LABEL_TAG 100001
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
UILabel *articleTitle = [cell.contentView viewWithTag:LABEL_TAG];
NSDictionary *article = self.articles[indexPath.row];
if (!articleTitle) {
articleTitle = [[UILabel alloc]initWithFrame:CGRectMake(5, cell.bounds.size.height - cell.bounds.size.height / 2.2, cell.bounds.size.width - 10, cell.bounds.size.height / 2)];
articleTitle.textColor = [UIColor whiteColor];
articleTitle.numberOfLines = 3;
articleTitle.adjustsFontSizeToFitWidth = YES;
articleTitle.tag = LABEL_TAG;
[cell.contentView addSubview:articleTitle];
}
articleTitle.text = article[#"title"];
NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: article[#"image"]]];
UIImageView *bgImageView = [[UIImageView alloc] initWithImage:[UIImage imageWithData:imageData]];
[bgImageView setContentMode:UIViewContentModeScaleAspectFill];
[bgImageView setClipsToBounds:YES];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = CGRectMake(0, cell.bounds.size.height - cell.bounds.size.height / 2, cell.bounds.size.width, cell.bounds.size.height/2);
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor clearColor] CGColor], (id)[[UIColor blackColor] CGColor], nil];
//gradient.locations = [NSArray arrayWithObjects:[NSNumber numberWithInt:0.0],[NSNumber numberWithInt:0.5], nil];
[bgImageView.layer insertSublayer:gradient atIndex:0];
cell.backgroundView = bgImageView;
return cell;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionView *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 10; // This is the minimum inter item spacing, can be more
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 10;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
int x = screenWidth/2 - 15;
int y = x;
return CGSizeMake(x, y);
}
- (void)collectionView:(UICollectionView *)colView didSelectItemAtIndexPath:(nonnull NSIndexPath *)indexPath
{
NSDictionary *article = self.articles[indexPath.row];
NSURL *URL = [NSURL URLWithString:article[#"url"]];
self.webViewController.title = article[#"title"];
self.webViewController.URL = URL;
[self.navigationController pushViewController:self.webViewController
animated:YES];
}
If NSLog(#"%#", self.articles) works and shows data you have proven that you are getting network data back. Did you set up your UIView as the delegate and the datasource properly? This is usually done at the top of the UIViewController class and looks like this:
class MyClassName: UICollectionViewDataSource {
// Your code here.
}
One way to check if the datasource is set up correctly is to set a breakpoint here
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
print(“This shows that I’m getting called”)
// Your custom code
}
When you call
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
})
this will in turn call cellForItemAtIndexPath to display data. If cellForItemAtIndexPath isn’t called then you have not properly set your UICollectionViewDataSource
Try to this
- (void)fetchFeed {
NSString *requestString = #"http://www.jameslester.xyz/example.json";
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest*req = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask*dataTask = [self.session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
self.articles = jsonObject[#"articles"];
NSLog(#"%#", self.articles);
NSLog(#"Feed Fetched!!!");
dispatch_async(dispatch_get_main_queue(), ^{
[_collectionView reloadData];
});
}];
[dataTask resume];
}
I'm using AFNetworking to load data.In my case, I load data into a collectionview.
I load data inside my custom method and inside that I reload collectionview data.
And I call this method in viewDidLoad method. Why I'm asking this is, it takes more time to load data. I thought this is because of the place I reload collectionview data.I want to know ,can I speed up the process by reloading collectionview data in another method like viewwillappear or any other.hope your help.thank you
- (void)viewDidLoad {
[super viewDidLoad];
[self loadcategoryData];
SWRevealViewController *revealcontroller = self.revealViewController;
if (revealcontroller) {
[self.sideBarbutton setTarget:self.revealViewController];
[self.sideBarbutton setAction:#selector(revealToggle:)];
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
}
// Do any additional setup after loading the view.
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
- (void)viewDidAppear:(BOOL)animated
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
- (void)viewDidDisappear:(BOOL)animated
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)loadcategoryData
{
post = nil;
NSString *mainurl = [NSString stringWithFormat:#"some url"];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:#"text/html"];
[manager GET:mainurl parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
posts = (NSDictionary *)responseObject;
post = [NSMutableArray array];
for(NSDictionary *all in posts)
{
Categories *category = [Categories new];
category.title = [all objectForKey:#"catname"];
category.firsturl = [all objectForKey:#"url"];
[self.maincollectionView reloadData];
//call for images
imagespost = nil;
NSString *imageUrl = [NSString stringWithFormat:#"%#", category.firsturl];
AFHTTPRequestOperationManager *managerone = [AFHTTPRequestOperationManager manager];
[managerone GET:imageUrl parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
imagesposts = (NSDictionary *)responseObject;
NSArray *resultone = [imagesposts objectForKey:#"posts"];
imagespost = [NSMutableArray array];
if ([resultone count]) {
NSDictionary *firstpost = resultone[0];
// Categories *newmogocat = [Categories new];
NSDictionary *thumbnail_images = [firstpost objectForKeyedSubscript:#"thumbnail_images"];
NSDictionary *thumbnail = [thumbnail_images objectForKey:#"thumbnail"];
category.imageOneUrl = [NSString stringWithFormat:#"%#",[thumbnail objectForKey:#"url"]];
// NSLog(#"%#", newmogocat.imageOneUrl);
// [imagespost addObject:newmogocat];
[post addObject:category];
[self.maincollectionView reloadData];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//
// UIAlertView *erroralert = [[UIAlertView alloc] initWithTitle:#"Something Wrong!" message:[NSString stringWithFormat:#"%#", error.localizedDescription] delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
// [erroralert show];
}];
}
} failure:^(AFHTTPRequestOperation *operation, NSError * responseObject) {
}];
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [post count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CategoryCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cellidentifier" forIndexPath:indexPath];
// cell.layer.borderWidth = 2.0f;
cell.layer.masksToBounds = NO;
cell.layer.cornerRadius = 5.0;
cell.layer.borderColor = [UIColor lightGrayColor].CGColor;
cell.layer.shadowOffset = CGSizeMake(0, 1);
cell.layer.shadowRadius = 4.0;
cell.layer.shadowColor = [UIColor darkGrayColor].CGColor;
[cell addSubview:cell.maintitleLabel];
Categories *cat = [post objectAtIndex:indexPath.row];
[self.maincollectionView reloadInputViews];
cell.maintitleLabel.text = [NSString stringWithFormat:#" %# ", cat.title];
[cell.maintitleLabel sizeToFit];
NSString *mainstring = [NSString stringWithFormat:#"%#", cat.imageOneUrl];
NSURL *url = [NSURL URLWithString:mainstring];
//
[cell.mainImageView setImageWithURL:url placeholderImage:nil];
//
return cell;
}
The earliest you can begin to load your data is in the init method. But to be honest most of the time they get called so quickly after eachother you probably wont even notice the difference. But if you were interested, just wack it in here:
- (id)init
{
self = [super init];
if (self)
{
[self loadcategoryData];
}
return self;
}
Also I don't know how much data your downloading, but if you are loading a long list and it is taking a long time then maybe you should consider doing "paging" (i.e. only downloading a sub section of the data and then requesting more as the user scrolls down the page.
As you can see I have two methods tuula and wendyslookbook. Then I call them both in my mostPopular method. I have requested the photos from the Instagram API but now I want to put these two user photos together. How can I do that?
//
// PhotosViewController.m
// Photo Bombers
//
// Created by Alex Macleod on 20/8/14.
// Copyright (c) 2014 Alex Macleod. All rights reserved.
//
#import "PhotosViewController.h"
#import "PhotoCell.h"
#import "DetailViewController.h"
#import "PresentDetailTransition.h"
#import "DismissDetailTransition.h"
#import <SimpleAuth/SimpleAuth.h>
#interface PhotosViewController () <UIViewControllerTransitioningDelegate>
#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 = #"Fashun";
[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 mostPopular];
}];
} else {
[self mostPopular];
}
}
- (void)tuula {
NSURLSession *session = [NSURLSession sharedSession];
NSString *urlString = [[NSString alloc]initWithFormat:#"https://api.instagram.com/v1/users/7522782/media/recent/?access_token=%#", self.accessToken];
NSURL *url = [[NSURL alloc] initWithString:urlString];
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
NSLog(#"links: %#", location);
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];
});
}];
[task resume];
}
- (void)wendyslookbook {
NSURLSession *session = [NSURLSession sharedSession];
NSString *urlString = [[NSString alloc]initWithFormat:#"https://api.instagram.com/v1/users/14454619/media/recent/?access_token=%#", self.accessToken];
NSURL *url = [[NSURL alloc] initWithString:urlString];
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
NSLog(#"links: %#", location);
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];
});
}];
[task resume];
}
- (void)mostPopular {
[self tuula];
[self wendyslookbook];
}
- (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;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *photo = self.photos[indexPath.row];
DetailViewController *viewController = [[DetailViewController alloc]init];
viewController.modalPresentationStyle = UIModalPresentationCustom;
viewController.transitioningDelegate = self;
viewController.photo = photo;
[self presentViewController:viewController animated:YES completion:nil];
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented
presentingController:(UIViewController *)presenting
sourceController:(UIViewController *)source {
return [[PresentDetailTransition alloc]init];
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
return [[DismissDetailTransition alloc]init];
}
#end
I have a view controller, that loads some an array. While everything is loading, I need to present another view controller (with the UIProgressView) and update it's UI (the progress property of a UIProgressView) and then dismiss and present first vc with downloaded data. I'm really struggling on it and I've tried delegation, but nothing worked for me.
- (void)viewDidLoad
{
[super viewDidLoad];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"downloaded"]) {
} else {
NSLog(#"First time Launched");
ProgressIndicatorViewController *progressVC = [ProgressIndicatorViewController new];
progressVC.modalPresentationStyle = UIModalPresentationFullScreen;
[self syncContacts];
[self presentViewController:progressVC animated:YES completion:nil];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"downloaded"];
[progressVC release];
}
}
sync contacts method:
- (void)syncContacts
{
NSLog(#"Sync data");
NSMutableArray *allContacts = [ContactsOperations getAllContactsFromAddressBook];
NSInteger allContactsCount = [allContacts count];
if (allContactsCount > 0) {
for (ContactData *contact in allContacts) {
NSMutableArray *phoneNumbersArray = [[NSMutableArray alloc] init];
NSString *nospacestring = nil;
for (UserTelephone *tel in [contact.abonNumbers retain]) {
NSArray *words = [tel.phoneNumber componentsSeparatedByCharactersInSet :[NSCharacterSet whitespaceCharacterSet]];
NSString *nospacestring = [words componentsJoinedByString:#""];
[phoneNumbersArray addObject:nospacestring];
}
contact.abonNumbers = phoneNumbersArray;
if (phoneNumbersArray != nil) {
NSLog(#"NOT NULL PHONENUMBERS: %#", phoneNumbersArray);
}
NSDictionary *dataDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:contact.abonNumbers, #"phoneNumbers", contact.contactName, #"fullName", [NSNumber numberWithBool:contact.isBlackList], #"blacklist", [NSNumber numberWithBool:contact.isIgnore], #"ignore", contact.status, #"status", nil];
NSLog(#"dictionary: %#", dataDictionary);
NSError *error;
NSData *postData = [NSJSONSerialization dataWithJSONObject:dataDictionary options:0 error:&error];
NSLog(#"POST DATA IS : %#", postData);
NSMutableURLRequest *newRequest = [self generateRequest:[[NSString stringWithFormat:#"%#c/contacts%#%#", AVATATOR_ADDR, SESSION_PART, [[ServiceWorker sharedInstance] SessionID]] stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding] withHTTPMethod:#"POST"];
[newRequest setHTTPBody:postData];
[newRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
//__block NSMutableData *newData;
[NSURLConnection sendAsynchronousRequest:newRequest queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
{
if (!connectionError) {
NSDictionary *allData = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"alldata from contacts: %#", allData);
//NSInteger errorCode = [[allData objectForKey:#"CommandRes"] integerValue];
//if (errorCode == 0) {
NSInteger remoteId = [[allData objectForKey:#"contactId"] integerValue];
contact.remoteId = remoteId;
NSLog(#"remote id is from parse content : %d", remoteId);
[[AvatatorDBManager getSharedDBManager]createContactWithContactData:contact];
} else {
NSLog(#"error");
}
}];
//Somewhere here I need to update the UI in another VC
[phoneNumbersArray release];
[dataDictionary release];
}
} else {
}
}
generate request method:
- (NSMutableURLRequest *)generateRequest:(NSString *)urlString withHTTPMethod:(NSString *)httpMethod
{
NSLog(#"url is :%#", urlString);
NSURL *url = [NSURL URLWithString:urlString];
request = [NSMutableURLRequest requestWithURL:url];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[request setHTTPMethod:httpMethod];
return request;
}
ProgressViewController is just an empty VC with the progress bar. No code yet.
In the view controller that will display the progress view expose a method like this...
- (void)updateProgress:(float)progress;
Its implementation will look like this...
- (void)updateProgress:(float)progress {
[self.progressView setProgress:progress animated:YES];
}
On the main view controller you need to execute the long-running process on a background thread. Here's viewDidLoad for the main view controller. This example code uses a property for the progress view controller (you may not require this) and assumes your are in a navigation controller...
- (void)viewDidLoad {
[super viewDidLoad];
// Create and push the progress view controller...
self.pvc = [[ProgressViewController alloc] init];
[self.navigationController pushViewController:self.pvc animated:YES];
// Your long-running process executes on a background thread...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Your long-running process goes here. Wherever required you would
// call updateProgress but that needs to happen on the main queue...
dispatch_async(dispatch_get_main_queue(), ^{
[self.pvc updateProgress:progress];
});
// At the end pop the progress view controller...
dispatch_async(dispatch_get_main_queue(), ^{
[self.navigationController popViewControllerAnimated:YES];
});
});
}