ScrollView not updated with imageview - ios

I have 20 images in my main bundle and i want to display it in my scroll view horizontally.
I am doing it successfully but now the problem is images are visible in scrollview after all imageview are set in scroll view and it takes time.
For resolve that I create one nsoperation.
-(BOOL)sync:(NSError**)error
{
float imageLeftPosition = 0;
for (int imageCount = 1; imageCount<=syncObject.syncNumberOfImages; imageCount++) {
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(imageLeftPosition, 0, syncObject.syncImageWidth, syncObject.syncImageHeight)];
[imgView setImage:[UIImage imageNamed:[NSString stringWithFormat:#"%d_%d.jpg",syncObject.syncChapterNumber,imageCount]]];
imgView.tag = imageCount;
// NSDictionary *dictionary = [NSDictionary new];
//
// [dictionary setValue:imgView forKey:CHAPTER_IMAGE];
imageLeftPosition = imageLeftPosition+syncObject.syncImageWidth;
//[dictionary setValue:[NSString stringWithFormat:#"%f",imageLeftPosition] forKey:CHAPTER_SCROLL_LEFT_POSITION];
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:imgView,[NSString stringWithFormat:#"%f",imageLeftPosition], nil] forKeys:[NSArray arrayWithObjects:CHAPTER_IMAGE,CHAPTER_SCROLL_LEFT_POSITION, nil]];
[self sendNotification:dictionary];
imgView = nil;
dictionary = nil;
}
return YES;
}
what i am doing here is add create one image view and post it to main view using notification
-(void)addImageView:(NSNotification*)notification
{
NSInteger thread = [NSThread isMainThread]?CVC_MainThread:CVC_BackgroundThread;
switch (thread) {
case CVC_MainThread:
{
NSDictionary *dictionary = notification.userInfo;
if(dictionary != nil)
{
NSLog(#"image view : %#",(UIImageView*)[dictionary valueForKey:CHAPTER_IMAGE]);
NSLog(#"leftposition: %f",[[dictionary valueForKey:CHAPTER_SCROLL_LEFT_POSITION] floatValue]);
[_scrChapters addSubview:((UIImageView*)[dictionary valueForKey:CHAPTER_IMAGE])];
_scrChapters.contentSize = CGSizeMake([[dictionary valueForKey:CHAPTER_SCROLL_LEFT_POSITION] floatValue], 0);
}
dictionary = nil;
}
break;
case CVC_BackgroundThread:
{
dispatch_async(dispatch_get_main_queue(), ^(void) {
NSDictionary *dictionary = notification.userInfo;
if(dictionary != nil)
{
NSLog(#"image view : %#",(UIImageView*)[dictionary valueForKey:CHAPTER_IMAGE]);
NSLog(#"leftposition: %f",[[dictionary valueForKey:CHAPTER_SCROLL_LEFT_POSITION] floatValue]);
[_scrChapters addSubview:((UIImageView*)[dictionary valueForKey:CHAPTER_IMAGE])];
_scrChapters.contentSize = CGSizeMake([[dictionary valueForKey:CHAPTER_SCROLL_LEFT_POSITION] floatValue], 0);
}
dictionary = nil;
});
}
break;
default:
break;
}
}
this is the notification handler method where i set the content size and image view in scroll view for each loop on main thread still scroll view are visible after all the images are load.
What I am doing wrong?

Try to use pagedflowview. This will load only the visible items into the Scrollview and is easy to customize. You can also search for iCarousel.
https://www.cocoacontrols.com/controls/pagedflowview

Try this
-(void)showimagesasSlide:(int) totalimagesCount
{
int xAxisofimageView=0;
for (int initialimagesCount=0;initialimagesCount<totalimagesCount; initialimagesCount++) {
UIImageView *detailedImageview=[[UIImageView alloc] init];
detailedImageview.userInteractionEnabled=YES;
UIImage *dynamicImage=[ScaleImageSize squareImageWithImage:[images objectAtIndex:initialimagesCount] scaledToSize:CGSizeMake(300, 500) ];
if (IS_IPHONE_5) {
detailedImageview.frame=CGRectMake(xAxisofimageView, 0, 320, 568);
}
else
{
detailedImageview.frame=CGRectMake(xAxisofimageView, 0, 320, 460);
}
// detailedImageview.contentMode=UIViewContentModeCenter;
detailedImageview.backgroundColor=[UIColor clearColor];
detailedImageview.image=dynamicImage;
detailedImageview.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin ;
detailedImageview.tag=initialimagesCount+12;
[mainScrollview addSubview:detailedImageview];
xAxisofimageView=xAxisofimageView+320;
}
mainScrollview.contentSize=CGSizeMake(320*images.count, 0);
}

Related

Unable to change image from UIImageView

I have an NSMutableArray with some UIImageView's inside. After a scroll action I want to change the images of some UIImageView but I can't.
This is how I first initiate the Array:
NSMutableArray *dotsImageSliderList = [[NSMutableArray alloc]init];
for (int i=0; i<totalImages; i++)
{
UIImageView *dot =[[UIImageView alloc] initWithFrame:CGRectMake(distance,2,5,5)];
if (i==0)
{
dot.image=[UIImage imageNamed:#"dotselected.png"];
}
else
{
dot.image=[UIImage imageNamed:#"dotunselected.png"];
}
[dotsImageSliderList addObject:dot];
}
And this is how I retrieve the UIImageView's and trying to change the images:
-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
NSInteger pagenumber = scrollView.contentOffset.x / scrollView.bounds.size.width;
NSLog(#"%zd", pagenumber);
if (pagenumber < [dotsImageSliderList count])
{
for (int i=0; i<[dotsImageSliderList count]; i++)
{
UIImageView *view = [dotsImageSliderList objectAtIndex:pagenumber];
if (i==pagenumber)
{
view.image=[UIImage imageNamed:#"dotselected.png"];
}
else
{
view.image=[UIImage imageNamed:#"dotunselected.png"];
}
}
}
}
I have no idea why the images don't change. Can you spot the mistake?
Initialise image object outside the loop.
NSMutableArray *dotsImageSliderList = [[NSMutableArray alloc]init];
UIImage * selectedImage = [UIImage imageNamed:#"dotselected.png"];
UIImage * unselectedImage = [UIImage imageNamed:#"dotunselected.png"];
for (int i=0; i<totalImages; i++)
{
UIImageView *dot =[[UIImageView alloc] initWithFrame:CGRectMake(distance,2,5,5)];
if (i==0)
{
dot.image=selectedImage;
}
else
{
dot.image=unselectedImage;
}
[dotsImageSliderList addObject:dot];
}
Super silly mistake. I have to change this line:
UIImageView *view = [dotsImageSliderList objectAtIndex:pagenumber];
to this:
UIImageView *view = [dotsImageSliderList objectAtIndex:i];

UITableView sorting

I've been brought in on this project where the previous developers made custom table cells and headers by using xib files and then registering the nibs like so:
[self.accountTable registerNib:[UINib nibWithNibName:kNonATITableViewCellLandscapeNib bundle:[NSBundle mainBundle]] forCellReuseIdentifier:kNonATITableViewCellLandscapeIdentifier];
[self.accountTable registerNib:[UINib nibWithNibName:kNonATITableHeaderLandscapeNib bundle:[NSBundle mainBundle]] forCellReuseIdentifier:kNonATITableHeaderLandscapeId];
The header files have buttons in them and uiimageviews. The buttons are for sorting, the uiimageviews for an arrow icon to show you the direction of the sort (asc, desc). All the buttons and imageviews are IBOutlets. All the buttons are linked to an IBAction:
- (IBAction)sortButtonTouched:(id)sender;
The file also has two other properties:
#property (nonatomic, assign) SortType currentSortingOption;
#property (nonatomic, strong) UIButton* btnLastTouched;
Here is sortButtonTouched:
- (IBAction)sortButtonTouched: (UIButton*) buttonTouched {
if (!self.btnLastTouched) {
self.btnLastTouched = buttonTouched;
}
NSString* strFieldToSort;
UIImageView* ivSortImage;
NSArray* arrSortIcons = [[NSArray alloc] initWithObjects:self.ivAccountSort,self.ivNameSort, self.ivAddressSort, self.ivCitySort, self.ivZipSort, self.ivLastCallSort, self.ivMileageSort, nil];
//get the image for the button selected
if (buttonTouched.tag == 0) {
strFieldToSort = #"customerNumber";
ivSortImage = self.ivAccountSort;
} else if (buttonTouched.tag == 1) {
strFieldToSort = #"customerName";
ivSortImage = self.ivNameSort;
} else if (buttonTouched.tag == 2) {
strFieldToSort = #"address";
ivSortImage = self.ivAddressSort;
} else if (buttonTouched.tag == 3) {
strFieldToSort = #"city";
ivSortImage = self.ivCitySort;
} else if (buttonTouched.tag == 4) {
strFieldToSort = #"zip";
ivSortImage = self.ivZipSort;
} else if (buttonTouched.tag == 5) {
strFieldToSort = #"lastCallDate";
ivSortImage = self.ivLastCallSort;
} else if (buttonTouched.tag == 6) {
strFieldToSort = #"mileage";
ivSortImage = self.ivMileageSort;
}
//set the sort option and add icon
if (!self.currentSortingOption) {
self.currentSortingOption = SORT_ASC;
[ivSortImage setImage:[UIImage imageNamed:Ascending_Icon]];
} else {
if (![self.btnLastTouched isEqual:buttonTouched]) {
self.currentSortingOption = SORT_ASC;
[ivSortImage setImage:[UIImage imageNamed:Ascending_Icon]];
} else {
if (self.currentSortingOption == SORT_ASC) {
self.currentSortingOption = SORT_DESC;
[ivSortImage setImage:[UIImage imageNamed:Descending_Icon]];
} else {
self.currentSortingOption = SORT_ASC;
[ivSortImage setImage:[UIImage imageNamed:Ascending_Icon]];
}
}
}
//show and hide
for(int i=0; i<arrSortIcons.count; i++) {
UIImageView* ivThisImage = [arrSortIcons objectAtIndex:i];
if (buttonTouched.tag == i) {
[UIView animateWithDuration:.25 animations:^(void) {
ivThisImage.alpha = 1.0;
}];
} else {
[UIView animateWithDuration:.25 animations:^(void) {
ivThisImage.alpha = 0.0;
}];
}
}
//call back to routing view controller and sort results based on sort order and field selected
NSDictionary* dictUserData = [[NSDictionary alloc] initWithObjectsAndKeys:
#"Sort Non-ATI", #"Action",
strFieldToSort, #"Field To Sort",
[NSNumber numberWithLong:self.currentSortingOption], #"Sortng Option",
nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"rvc" object:self userInfo:dictUserData];
self.btnLastTouched = buttonTouched;
}
And the notification fires this method:
- (void) sortNonATIResults : (NSDictionary*) dictSortParams {
if (self.arrNonATIResults.count > 0) {
NSString* sortKey = [dictSortParams objectForKey:#"Field To Sort"];
//change the field to sort to match the customerInfo object properties...
NSNumber* numSortType = [dictSortParams objectForKey:#"Sortng Option"];
BOOL isAsc = YES;
if ([numSortType intValue] == 2) {
isAsc = NO;
}
NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:isAsc];
NSArray* arrSortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
NSArray* arrSortedNonATIResults = (NSArray*)[self.arrNonATIResults sortedArrayUsingDescriptors:arrSortDescriptors];
self.arrNonATIResults = [arrSortedNonATIResults mutableCopy];
self.arrDatasource = self.arrNonATIResults;
[self.accountTable reloadData];
}
}
There are two problems right now. The icons are not showing up if the notification is sent. Comment out the notification and they function as expected. The other problem is that the property currentSortingOption doesn't retain it's value. I think both issues are related but I am not 100% sure. When the tableview is reloaded, does the header get instantiated again? This would make sense to me since then the uiimageviews would be reset with no image and the property would lose it's value and reset to 0 (it is the value of a typedef).
So, I am correct, how can I resolve this and if not, what could be causing the problems?
Thanks
OK, sorry for posting and then solving my problem right away, I guess sometimes you just need to write out the problem to find the solution. All I needed to do was not reload the table but just reload the rows. Here's the updated method:
(void) sortNonATIResults : (NSDictionary*) dictSortParams {
if (self.arrNonATIResults.count > 0) {
NSString* sortKey = [dictSortParams objectForKey:#"Field To Sort"];
//change the field to sort to match the customerInfo object properties...
NSNumber* numSortType = [dictSortParams objectForKey:#"Sortng Option"];
BOOL isAsc = YES;
if ([numSortType intValue] == 2) {
isAsc = NO;
}
NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:isAsc];
NSArray* arrSortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
NSArray* arrSortedNonATIResults = (NSArray*)[self.arrNonATIResults sortedArrayUsingDescriptors:arrSortDescriptors];
self.arrNonATIResults = [arrSortedNonATIResults mutableCopy];
self.arrDatasource = self.arrNonATIResults;
dispatch_async(dispatch_get_main_queue(), ^{
NSMutableArray *indexPathArray = [[NSMutableArray alloc] init];
for (NSInteger section = 0; section < [self.accountTable numberOfSections]; ++section)
{
for (NSInteger row = 0; row < [self.accountTable numberOfRowsInSection:section]; ++row)
{
[indexPathArray addObject:[NSIndexPath indexPathForRow:row inSection:section]];
}
}
[self.accountTable reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationNone];
[self.accountTable scrollsToTop];
});
}
}

How do I apply 5 different avatars to 5 different UIButtons?

I am creating 5 UIButtons, using a for loop, and would like to put 5 different avatars on the UIButtons. However, only one avatar is filling all 5 buttons.
The code I have constructed looks like the following,
// create a subview for avatar buttons
UIView *avatarView = [[UIView alloc] init];
avatarView.frame = CGRectMake(20, 125, 280, 100); // don't mess with these values.
// avatarView.layer.borderColor = [UIColor redColor].CGColor;
// avatarView.layer.borderWidth = 3.0f;
[self.view addSubview:avatarView];
UIScrollView *avatarScroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0,0, self.view.frame.size.width, self.view.frame.size.height)];
avatarScroll.contentSize = CGSizeMake(500, 500);
avatarScroll.scrollEnabled = YES;
[avatarView addSubview:avatarScroll];
// fetch Data from Core Data
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Account" inManagedObjectContext:_managedObjectContext];
[fetchRequest setEntity:entity];
// fetch records and handle error
NSError *error;
NSArray *results = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
// sort results array by lastLogin
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"lastLogin" ascending:NO];
NSArray *sortedArray = [NSArray arrayWithObject:sort];
NSArray *sortedArray2 = [results sortedArrayUsingDescriptors:sortedArray];
// how to remove values from NSArray
NSArray *lastLoginArray = [sortedArray2 valueForKey:#"lastLogin"];
// NSLog(#"lastLoginArray = %#",lastLoginArray);
// make an array that only hold 5 values
// NSArray *last5LoginArray;
// for (int i=5; i<[lastLoginArray count]; i++) {
// [last5LoginArray addObject:[lastLoginArray objectAtIndex:i]];
// }
// NSLog(#"last5LoginArray = %#",last5LoginArray);
// NSArray *last5LoginArray = [NSArray arrayWithObjects:lastLoginArray count:4];
// NSArray *last5LoginArray = [NSArray arrayByAddingObjectsFromArray:lastLoginArray count:4];
NSMutableArray *last5LoginArray = [[NSMutableArray alloc] initWithArray:[lastLoginArray subarrayWithRange:NSMakeRange(0, 5)] ];
NSLog(#"last5LoginArray = %#",last5LoginArray);
// NSLog(#"sortedArray2 = %#",sortedArray2);
CGFloat staticX = 0;
CGFloat staticWidth = 80;
CGFloat staticHeight = 80;
CGFloat staticPadding = 5;
// need to put the avatars stored in sortedArray2 in the scrollView
for ( int i = 0; i < 5; i++) {
// do additional loading for avatars
UIButton *avatarButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
// the last two values control the size of the button
// avatarButton.frame = CGRectMake(0, 0, 80, 80);
[avatarButton setFrame:CGRectMake((staticX + (i * (staticHeight + staticPadding))),5,staticWidth,staticHeight)];
// make corners round
avatarButton.layer.cornerRadius = 40; // value varies -- // 35 yields a pretty good circle.
avatarButton.clipsToBounds = YES;
// create a stock image
UIImage *btnImage = [UIImage imageNamed:#"HomeBrewPoster1.jpg"];
Account *anAccount;
for ( anAccount in results) {
if([last5LoginArray containsObject:anAccount.lastLogin]) {
NSLog(#"anAccount.lastLogin = %#",anAccount.lastLogin);
UIImage *avatarImg = [UIImage imageWithData:anAccount.avatar ];
// apply avImg to btn
[avatarButton setBackgroundImage:avatarImg forState:UIControlStateNormal];
}
}
if (btnImage == nil) {
NSLog(#"can't find HomeBrewPoster1.jpg");
// apply stock image to button(s)
[avatarButton setBackgroundImage:btnImage forState:UIControlStateNormal];
} else {
}
// this should add 5x buttons
[avatarScroll addSubview:avatarButton];
}
Your innermost for-in loop always sets the last matching avatar to the button, because the current value of i makes absolutely no difference to what the innermost loop does.
You should move the nested loop outside the first loop to prepare the five avatars upfront, and then use i to index into the array of avatars, like this:
NSMutableArray *avatars = [NSMutableArray arrayWithCapacity:5];
for ( anAccount in results) {
if([last5LoginArray containsObject:anAccount.lastLogin]) {
NSLog(#"anAccount.lastLogin = %#",anAccount.lastLogin);
UIImage *avatarImg = [UIImage imageWithData:anAccount.avatar ];
[avatars addObject:avatarImg];
}
}
NSAssert(
avatars.count == last5LoginArray.count
, #"The loop is expected to find as many avatars as there are items in last5LoginArray"
);
for ( int i = 0; i < 5; i++) {
...
// Check that we have enough logins
if (i < last5LoginArray.count) {
[avatarButton setBackgroundImage:avatars[i] forState:UIControlStateNormal];
}
}
Declare button as an array
NSArray *arrImages = [NSArray arrayWithObjects:#"1.jpg",#"2.jpg",#"3.jpg",#"4.jpg",#"5.jpg", nil];
UIButton *button[5];
button[i] = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button[i] addTarget:self action:#selector(aMethod:) forControlEvents:UIControlEventTouchUpInside];
[button[i] setBackgroundImage:[UIImage imageNamed:[arrImages objectAtIndex:i]] forState:UIControlStateNormal];
[button[i] setTitle:#"Title" forState:UIControlStateNormal];
button[i].frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[avatarScroll addSubview:button[i]];
You can name your images like "HomeBrewPoster0", "HomeBrewPoster1", etc. And add this to choose right image in your loop:
UIImage *btnImage = [UIImage imageNamed:[NSString stringWithFormat:#"HomeBrewPoster%ld.jpg", i]];

iOS CollectionView: Loading Data Asynchronously

I'm using a collection view and trying to transition from loading the data synchronously to loading it asynchronously.
I know that the following currently works (it takes a while to load, but all the cells appear correctly when it's done):
// load projectData in main thread
NSData * projectData = [NSData dataWithContentsOfURL:userUrl];
[self performSelectorOnMainThread:#selector(fetchProjects:)withObject:projectData waitUntilDone:YES];
I rewrote it to do everything asynchronously:
// load project data asynchronously
dispatch_async(bgQueue, ^{
UIView *loadingAnimation = loadingCircle;
loadingAnimation.tag = 15;
[self.collectionView addSubview:loadingAnimation];
[loadingCircle startAnimating];
NSData * projectData = [NSData dataWithContentsOfURL:userUrl];
[self performSelector:#selector(fetchProjects:) withObject:projectData];
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"finished with loading projects");
UIView *viewToRemove = [self.view viewWithTag:15];
[viewToRemove removeFromSuperview];
[self.collectionView reloadData];
});
});
When I run the app after loading the data asynchronously, the view appears empty (the cells have no content), but when I scroll, some of the cells begin to appear.
Is there anything else I need to call besides reloadData to get my collection cells to appear properly?
Here is my fetchProjects:
// get JSON data of projects
- (void)fetchProjects:(NSData *)responseData {
NSError * error;
NSDictionary * json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error]; // get dictionary from json data
NSDictionary * data = [json objectForKey:#"data"]; // get data in array
NSArray * projects = [data objectForKey:#"projects"];
NSDictionary * mostRecentProject = [projects objectAtIndex:0];
mostRecentProjectID = [mostRecentProject objectForKey:#"id"];
for (NSDictionary *currentProject in projects)
{
[projectIDs addObject: [currentProject objectForKey:#"id"]];
NSString *projectTitle = [currentProject objectForKey:#"title"];
NSString *trimmedProjectTitle = [projectTitle stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
id delegate = [[UIApplication sharedApplication] delegate];
self.managedObjectContext = [delegate managedObjectContext];
Project *newProject = (Project *) [NSEntityDescription insertNewObjectForEntityForName:#"Project" inManagedObjectContext:[self managedObjectContext]];
CustomLabel *cellLabel=[[CustomLabel alloc]init];
cellLabel.text = trimmedProjectTitle;
NSLog(#"fetchprojects:%#",projectTitle);
[titles addObject:projectTitle];
CGSize maxLabelSize = CGSizeMake(screenWidth/2 - 30,100);
CustomLabel *titleLabel = [[CustomLabel alloc]init];
[titleLabel setNumberOfLines:0];
titleLabel.text = projectTitle;
CGSize expectedLabelSize = [titleLabel.text sizeWithFont:titleLabel.font constrainedToSize:maxLabelSize lineBreakMode:NSLineBreakByWordWrapping];
CGRect labelFrame = (CGRectMake(0, 0, screenWidth/2 - 30, 0));
labelFrame.origin.x = 0;
labelFrame.origin.y = screenWidth/2 - 70 - expectedLabelSize.height;
labelFrame.size.height = expectedLabelSize.height;
titleLabel.frame = labelFrame;
titleLabel.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.5f];
titleLabel.textColor =[UIColor whiteColor];
[titleLabel setFont: [UIFont fontWithName: #"HelveticaNeue" size:12]];
//NSLog(#"%#", titleLabel.text);
UIImageView *imagePreview = [[UIImageView alloc] initWithFrame:CGRectMake(7.5, 10, screenWidth/2 -30, screenWidth/2 -70)];
imagePreview.contentMode= UIViewContentModeScaleAspectFill;
imagePreview.clipsToBounds = YES;
[imagePreview setImage:[UIImage imageNamed:#"blank.png"]];
[imagePreview addSubview:titleLabel];
[imagePreview.subviews[0] setClipsToBounds:YES];
[projectContainers addObject: imagePreview];
}
}
You're doing a lot of UI work on a background thread which you really shouldn't do. From what I can see, the only line that really needs to be run on a background thread is this one:
NSData * projectData = [NSData dataWithContentsOfURL:userUrl];
The rest looks like it deals with setting up and displaying your UI and some CoreData stuff; all of that needs to be run on the main thread. The easiest way to do that and keep everything running in the right order would be something like this:
// NOTE: If you're sure you're already on the main thread here, you don't need the dispatch, but it's not going to hurt to leave it in.
dispatch_async(dispatch_get_main_queue(), ^{
UIView *loadingAnimation = loadingCircle;
loadingAnimation.tag = 15;
[self.collectionView addSubview:loadingAnimation];
[loadingCircle startAnimating];
});
dispatch_async(bgQueue, ^{
NSData * projectData = [NSData dataWithContentsOfURL:userUrl];
dispatch_async(dispatch_get_main_queue(), ^{
[self fetchProjects:projectData];
NSLog(#"finished with loading projects");
UIView *viewToRemove = [self.view viewWithTag:15];
[viewToRemove removeFromSuperview];
[self.collectionView reloadData];
});
});
Note: I also changed [self performSelector:#selector(fetchProjects:) withObject:projectData] to [self fetchProjects:projectData]; you don't really need to go through performSelector: there.

unable to create multiple UIImageView in loop ios

I am trying to show no. of images in different image view. if i have 3 image then i want show in 3 diff. UIImageView in my View. Here is my code that only shows one image. What have i missed here?
NSArray * _thumbnails = _claimReport.photos.allObjects;
if (_thumbnails.count >0)
{
NSMutableArray *imageViews = [[NSMutableArray alloc] init];
for (int i =1; i<_thumbnails.count; i++)
{
UIImageView *newImageViews = [[UIImageView alloc]initWithFrame:CGRectMake(40, 1700*i+20, 670, 700)];
LAPhoto *photo = [_thumbnails objectAtIndex:i];
[newImageViews setImage:[UIImage imageWithData:photo.photo]];
NSLog(#" newImageViews %# ",newImageViews);
[imageViews addObject:newImageViews];
[self.formView addSubview:newImageViews];
}
NSLog(#"Count %d" , imageViews.count);
}
You can add the images in a scroll view:
self.scrollView = [[UIScrollView alloc]initWithFrame:self.view.bounds];
[self.formView addSubview:self.scrollView];
NSArray * _thumbnails = _claimReport.photos.allObjects;
if (_thumbnails.count >0)
{
NSMutableArray *imageViews = [[NSMutableArray alloc] init];
for (int i =0; i<_thumbnails.count; i++)
{
UIImageView *newImageViews = [[UIImageView alloc]initWithFrame:CGRectMake(40, 800*i+20, 670, 700)];
LAPhoto *photo = [_thumbnails objectAtIndex:i];
[newImageViews setImage:[UIImage imageWithData:photo.photo]];
NSLog(#" newImageViews %# ",newImageViews);
[imageViews addObject:newImageViews];
self.scrollView.contentSize = CGSizeMake(670, 800 *i + 800);
[self.scrollView addSubview:newImageViews];
}
NSLog(#"Count %d" , imageViews.count);
}

Resources