More than 1 image on a subview not loading - objective-c

I'm trying to add images over a ScrollView. I have the x and y point in a plist file and they are called by an enum.
enum {
kLogoImage = 1,
kNewLogoImage,
};
#implementation
- (void) _setupStaticViews
{
UIButton *image = [UIButton buttonWithType:UIButtonTypeCustom];
[image setBackgroundImage:[UIImage imageNamed:#"logo.png"] forState:UIControlStateNormal];
[image addTarget:self action:#selector(_addContactButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
image.frame = CGRectMake(0.0 ,0.0, 150.0, 150.0);
image.tag = kLogoImage;
[_mapImageView addSubview:image];
_staticViews = #[image];
UIButton *image2 = [UIButton buttonWithType:UIButtonTypeCustom];
[image2 setBackgroundImage:[UIImage imageNamed:#"Time Bakground.png"] forState:UIControlStateNormal];
[image2 addTarget:self action:#selector(_addContactButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
image2.frame = CGRectMake(0.0 ,0.0, 250.0, 150.0);
image2.tag = kNewLogoImage;
[_mapImageView addSubview:image2];
_staticViews = #[image2];
for ( UIView *view in _staticViews ) {
CGPoint point = [self _basePositionForView:view];
CGRect frame = view.frame;
frame.origin = point;
view.frame = frame;
}
}
If I have only image showing, it works fine. But I need to add more than one and adding the second one causes the first one to be at xy point 0,0, and Image2 isn't visible.
How would I go about adding another image?
- (CGPoint) _basePositionForView:(UIView *)view {
NSString *key = [NSString stringWithFormat:#"%d", view.tag];
NSString *stringValue = [_coordinates objectForKey:key];
NSArray *values = [stringValue componentsSeparatedByString:#":"];
if ( [values count] < 2 ) return CGPointZero;
CGPoint result = CGPointMake([[values objectAtIndex:0] floatValue], [[values objectAtIndex:1] floatValue]);
return result;
}

I noticed that you first make
_staticViews = #[image];
and later
_staticViews = #[image2];
Don't you rather mean to have
_staticViews = #[image, image2];
?

You should iterate and change x accordingly in the frame:
for ( int iterator=0; iterator< [[_staticViews subviews] count]; iterator++){
...
current_image.frame = CGRectMake(YOUR_IMG_WIDTH * iterator ,0.0, YOUR_IMG_WIDTH, 150.0);
...}

Related

UIButton is not setting text

I seem to have a problem in my Objective C iOS app where I am creating multiple buttons depending on the amount of objects in an array. I know Swift, so I replicated the logic into Swift, and it worked. Yet in Objective C, I am unable to see the text of the button (after I remove the for loop) or create multiple buttons. For example, I have an array full of three names. I would like to create a button for each name with the title set to the corresponding name. So far, I have this:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *ages = [[NSMutableArray alloc] init];
for (int i = 0; i > 10; i++) {
[ages addObject:[NSString stringWithFormat:#"%i", i]];
}
UIScrollView *scrollView= [[UIScrollView alloc]initWithFrame:self.view.frame];
scrollView.delegate= self;
self.automaticallyAdjustsScrollViewInsets= NO;
scrollView.backgroundColor= [UIColor clearColor];
scrollView.scrollEnabled= YES;
scrollView.userInteractionEnabled= YES;
[scrollView setShowsHorizontalScrollIndicator:NO];
[scrollView setShowsVerticalScrollIndicator:NO];
CGFloat xValue = 0;
for(int x=0; x > ages.count; x++){
UIButton *button= [[UIButton alloc] initWithFrame:CGRectMake(xValue ,0 , 172 ,65)];
UIColor *buttonOutline = [[UIColor redColor] CGColor];
button.layer.borderColor = [buttonOutline CGColor];
button.layer.backgroundColor = [[UIColor clearColor] CGColor];
button.layer.borderWidth = 1.0;
button.layer.cornerRadius = 6.0;
[button.titleLabel setFont:[UIFont fontWithName:#"Helvetica" size:13.0]];
button.titleLabel.text = [ages objectAtIndex:x];
[button addTarget:self action:#selector(test:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:button];
NSLog(#"Button Added");
xValue = button.frame.size.width + 40;
}
scrollView.contentSize = CGSizeMake(xValue, 65);
[self.view addSubview:scrollView];
}
- (void)test:(UIButton*)sender{
NSLog(#"Clicked %#", sender.titleLabel.text);
}
#end
If anyone sees anything wrong with this code, please point it out!
Thanks,
Arnav K.
I found four problems (there may be others) that stop this working correctly:
1) The for loop bound when setting up the ages array is incorrect.
2) The for loop bound when creating the buttons is incorrect.
3) You are setting the buttonOutline colour incorrectly.
4) xValue is being updated incorrectly.
Here is the viewDidLoad method after the changes have been made:
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *ages = [[NSMutableArray alloc] init];
for (int i = 0; i < 10; i++) { // UPDATED
[ages addObject:[NSString stringWithFormat:#"%i", i]];
}
UIScrollView *scrollView= [[UIScrollView alloc]initWithFrame:self.view.frame];
scrollView.delegate= self;
self.automaticallyAdjustsScrollViewInsets= NO;
scrollView.backgroundColor= [UIColor clearColor];
scrollView.scrollEnabled= YES;
scrollView.userInteractionEnabled= YES;
[scrollView setShowsHorizontalScrollIndicator:NO];
[scrollView setShowsVerticalScrollIndicator:NO];
CGFloat xValue = 0;
for(int x=0; x < ages.count; x++){ // UPDATED
UIButton *button= [[UIButton alloc] initWithFrame:CGRectMake(xValue ,0 , 172 ,65)];
UIColor *buttonOutline = [UIColor redColor]; // UPDATED
button.layer.borderColor = [buttonOutline CGColor];
button.layer.backgroundColor = [[UIColor clearColor] CGColor];
button.layer.borderWidth = 1.0;
button.layer.cornerRadius = 6.0;
[button.titleLabel setFont:[UIFont fontWithName:#"Helvetica" size:13.0]];
button.titleLabel.text = [ages objectAtIndex:x];
[button addTarget:self action:#selector(test:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:button];
NSLog(#"Button Added");
xValue += button.frame.size.width + 40; // UPDATED
}
scrollView.contentSize = CGSizeMake(xValue, 65);
[self.view addSubview:scrollView];
}
I have marked the four lines I changed with a UPDATED comment so you can compare them to the original.
EDIT
To change the text and text colour use the following:
[button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[button setTitle:[ages objectAtIndex:x] forState:UIControlStateNormal];
and remove this:
button.titleLabel.text = [ages objectAtIndex:x];
You need to do this because you can set different text for the different states of the button and this is all handled automatically for you.

Setting uibutton frame not working

I have values in dictionaries that will make a frame of a uibutton
tags = (
{
height = "15.513672";
text = jeans;
width = "39.808105";
x = "225.500000";
y = "265.000000";
},
{
height = "15.513672";
text = jacket;
width = "44.080078";
x = "190.000000";
y = "156.500000";
}
);
I set the frame of uibuttons with the values from the dictionaries
for (int i = 0; i<[tags count]; i++) {
NSLog(#"adding tags");
NSMutableDictionary *propertiesdict = [[NSMutableDictionary alloc] init];
propertiesdict = [[tags objectAtIndex:i] mutableCopy];
float x = [[dict objectForKey:#"x"] floatValue];
float y = [[dict objectForKey:#"y"] floatValue];
float width = [[dict objectForKey:#"width"] floatValue];
float height = [[dict objectForKey:#"height"] floatValue];
NSString *title = [dict objectForKey:#"text"];
UIButton *button = [[UIButton alloc] init];
[button setFrame:CGRectMake(x, y, width, height)];
[button setTitle:title forState:UIControlStateNormal];
button.layer.cornerRadius = 2.5;
//button.alpha = 0.9;
[button.titleLabel setFont:[UIFont systemFontOfSize:13]];
[button setBackgroundColor:[UIColor viewFlipsideBackgroundColor]];
button.tag = i;
[button addTarget:self action:#selector(tappedOnTag:) forControlEvents:UIControlEventTouchUpInside];
[tagsView addSubview:button];
}
After adding the buttons to the subview, the NSLog shows that each button has a frame (0,0,0,0) which differs from when I set the frame in the for loop.
2015-10-15 12:25:17.787 kyss[1018:316548] tapped on tags view. Number of subviews = 2. Subviews: (
"<UIButton: 0x15f732330; frame = (0 0; 0 0); opaque = NO; layer = <CALayer: 0x15f72eb60>>",
"<UIButton: 0x15f6d10e0; frame = (0 0; 0 0); opaque = NO; tag = 1; layer = <CALayer: 0x15f6b3790>>"
)
Let's take a look at the code...
for (int i = 0; i<[tags count]; i++) {
NSLog(#"adding tags");
NSMutableDictionary *propertiesdict = [[NSMutableDictionary alloc] init];
propertiesdict = [[tags objectAtIndex:i] mutableCopy];
You create a new dictionary and immediately overwrite the reference with an item from the tags array.
float x = [[dict objectForKey:#"x"] floatValue];
float y = [[dict objectForKey:#"y"] floatValue];
float width = [[dict objectForKey:#"width"] floatValue];
float height = [[dict objectForKey:#"height"] floatValue];
You reference dict, which isn't defined in the code you posted. It's safe to assume that it's not the same as propertiesdict, so you're getting nil references, thus the value 0 for each assignment.
NSString *title = [dict objectForKey:#"text"];
Again with the dict.
UIButton *button = [[UIButton alloc] init];
[button setFrame:CGRectMake(x, y, width, height)];
[button setTitle:title forState:UIControlStateNormal];
button.layer.cornerRadius = 2.5;
//button.alpha = 0.9;
[button.titleLabel setFont:[UIFont systemFontOfSize:13]];
[button setBackgroundColor:[UIColor viewFlipsideBackgroundColor]];
button.tag = i;
[button addTarget:self action:#selector(tappedOnTag:) forControlEvents:UIControlEventTouchUpInside];
[tagsView addSubview:button];
}
The rest of the code is ok.
Anyway, your problem is referencing the wrong dictionary. Did you not notice that the title is wrong too?

UIButtons in UIScrollView stop working after 3 rows

I have a UIScrollView with a list of UIViews within it. Bit like a fancy tableview. One issue I am having is the buttons work ok for the first 3 'rows' in the scrollview, but none of the buttons after this respond when i scroll down. Looks like its working ok for the buttons that show on screen when the view has loaded but anything further down when i scroll will now respond at all...
code from within the uiview repeated within uiscrollview
-(void)addButtons
{
UIButton *visiteWebSite = [UIButton buttonWithType:UIButtonTypeCustom];
[visiteWebSite addTarget:self
action:#selector(visitSite:)
forControlEvents:UIControlEventTouchDown];
[visiteWebSite setTintColor:[UIColor colorWithRed:247 green:143 blue:30 alpha:1.0]];
visiteWebSite.frame = CGRectMake(440.0, 10.0, 120.0, 26.0);
if(![self IsPhone5]) {
visiteWebSite.frame = CGRectMake(350.0, 10.0, 120.0, 26.0);
}
//visiteWebSite.backgroundColor = [UIColor orangeColor]; //[UIColor colorWithRed:247 green:143 blue:30 alpha:1.0];
[visiteWebSite setBackgroundImage:[UIImage imageNamed:#"orangeBG"] forState:UIControlStateNormal];
[visiteWebSite setTitle:#"VISITE WEBSITE" forState:UIControlStateNormal];
visiteWebSite.titleLabel.font = [UIFont fontWithName:#"arial" size:12];
[self addSubview:visiteWebSite];
UIButton *getDirections = [UIButton buttonWithType:UIButtonTypeCustom];
[getDirections addTarget:self
action:#selector(getDirections:)
forControlEvents:UIControlEventTouchDown];
[getDirections setTitle:#"GET DIRECTIONS" forState:UIControlStateNormal];
getDirections.titleLabel.font = [UIFont fontWithName:#"arial" size:12];
getDirections.frame = CGRectMake(440.0, 46.0, 120.0, 26.0);
if(![self IsPhone5]) {
getDirections.frame = CGRectMake(350.0, 46.0, 120.0, 26.0);
}
[getDirections setBackgroundImage:[UIImage imageNamed:#"orangeBG"] forState:UIControlStateNormal];
[self addSubview:getDirections];
}
Code from Parent View containing the UIScrollView
-(void)performSearch
{
[self.loadinglabel removeFromSuperview];
NSString* searchTerm = txtSearch.text;
searchTerm = [searchTerm stringByReplacingOccurrencesOfString:#" " withString:#""];
NSData *urldata = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://www.collectioncosmetics.co.uk/storelocatorapi?store=%#",searchTerm]]];
NSString *json = [[NSString alloc] initWithData:urldata encoding:NSUTF8StringEncoding];
SBJsonParser *jsonParser = [[SBJsonParser alloc] init];
NSArray *jsonObjects = [jsonParser objectWithString:json];
float y = 0;
float height = 84;
if([jsonObjects count] < 1) {
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:#"NO RESULTS" message:#"There are no stores near the postcode you searched" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alertView show];
[self back:nil];
return;
}
for (int i = 0; i < [jsonObjects count]; i++)
{
NSDictionary *dict = [jsonObjects objectAtIndex:i];
CARStoreResult* result = [[CARStoreResult alloc] initWithFrame:CGRectMake(0, height*i, tv.frame.size.width, height)];
result.name = [dict objectForKey:#"name"];
result.street = [dict objectForKey:#"street"];
result.area = [dict objectForKey:#"area"];
result.county = [dict objectForKey:#"County"];
result.postcode = [dict objectForKey:#"PostCode"];
result.distance = [dict objectForKey:#"distance"];
result.usersPostCode = searchTerm;
result.y = y;
result.num = i;
y = y + height;
[result build];
[tv addSubview:result];
}
[tv setFrame:CGRectMake(tv.frame.origin.x, tv.frame.origin.y, tv.frame.size.width, height*[jsonObjects count])];
[self.scrollView setContentSize:tv.frame.size];
[Flurry logEvent:#"Store Locator"];
}
FIXED!
instead of adding the views to a view within the scrollview i added them just directly to the scrollview. with the scrollview having scrollView.canCancelContentTouches set to NO.
//[tv addSubview:result];
[self.scrollView addSubview:result];
}
//[tv setFrame:CGRectMake(tv.frame.origin.x, tv.frame.origin.y, tv.frame.size.width, height*[jsonObjects count])];
[self.scrollView setContentSize:CGSizeMake(320, height*[jsonObjects count])];
//[self.scrollView setContentSize:tv.frame.size];
[Flurry logEvent:#"Store Locator"];

Create Grid of UIVews in NSArray

What I am trying to do is align views in a grid that are in an array. I have created the views and the array.
for (int i = 0; i < [directoryContents count]; i++){
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0,0,100,120)];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, 100, 100);
button.accessibilityIdentifier = [directoryContents objectAtIndex:i];
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 100, 100, 20)];
label.textAlignment = NSTextAlignmentCenter;
label.text = [directoryContents objectAtIndex:i];
[containerView addSubview:button];
[containerView addSubview:label];
[self.view addSubview:containerView];
[_containerViewArray addObject:containerView];
}
[self layoutViews:_containerViewArray inView:self.view];
What I have working is aligning them next to each other the problem I am having is I need to have them wrap down instead of going off the edge. What I am doing to algin them is this
- (void)layoutViews:(NSArray *)views inView:(UIView *)contentView
{
NSInteger overallWidth = 0;
for ( UIView *view in views ) {
overallWidth += view.frame.size.width;
}
CGSize contentSize = contentView.frame.size;
CGFloat startOffset = (contentSize.height - overallWidth)/2.0;
CGFloat offset = startOffset;
for ( UIView *view in views ) {
CGRect frame = view.frame;
frame.origin.x = offset;
view.frame = frame;
offset += view.frame.size.width;
}
}
If we assumed that we have an array of sections (your views) and you need to layout 3 item per row the view has size 98*98 and spacing 6.5px horizontally and 8px Vertically
for (int i = 0; i< [sectionsArray count]; i++) {
int row = (int)i/3;
int col = i%3;
float x = 6.5 + (104.5*col);
float y = 8 + (106*row);
UIView *sectionView = [[UIView alloc] initWithFrame:CGRectMake(x, y, 98, 98)];
sectionView.backgroundColor = [UIColor clearColor];
//button
UIButton *sectionButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[sectionButton setTintColor:[UIColor grayColor]];
sectionButton.frame = CGRectMake(0, 0, 98, 98);
sectionButton.tag = i+100;
[sectionButton addTarget:self action:#selector(showSectionDetail:) forControlEvents:UIControlEventTouchUpInside];
[sectionView addSubview:sectionButton];
//adding title
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 75, 98, 20)];
titleLabel.textAlignment = UITextAlignmentCenter;
titleLabel.backgroundColor=[UIColor clearColor];
titleLabel.font=[UIFont fontWithName:#"Helvetica" size:14];
titleLabel.textColor = [UIColor colorWithRed:241.0/255.0 green:124.0/255.0 blue:22.0/255.0 alpha:1.0];
titleLabel.text = [[sectionsArray objectAtIndex:i] objectForKey:#"Title"];
[sectionView addSubview:titleLabel];
[titleLabel release];
[scroll addSubview:sectionView];
[sectionView release];
}
int numberOfRows;
if ([sectionsArray count]/3.0f == 0) {
numberOfRows = [sectionsArray count]/3;
}else{
numberOfRows = [sectionsArray count]/3 +1;
}
scroll setContentSize:CGSizeMake(320, numberOfRows*106);
Here's what I used until the UICollectionView was released, easy to modify to accommodate for how many rows you want in the grid, and the size of the views.
NSUInteger buttonWidth = 100;
NSUInteger buttonHeight = 100;
NSUInteger space = 5;
float scrollContentY = (ceilf((float)imageNames.count / 3.0f) * (buttonHeight + space));
[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
int row = idx / 3;
int column = idx % 3;
UIView *view = [UIView new];
[view setBackgroundColor:[UIColor redColor]];
view.frame = CGRectMake((buttonWidth + space) * column + space, (buttonHeight + space) * row + space , buttonWidth, buttonHeight);
[view setTag:(NSInteger)idx];
[self.scrollView addSubview:view];
[self.scrollView setContentSize:CGSizeMake(self.scrollView.frame.size.width, scrollContentY)];
}];
Mind you, this might not be advisable if you have a large array to enumerate because this doesn't have any kind of reusable views. It will alloc/init a view for every item in the array.

UIScrollView setNeedsDisplay not working, or something else?

Final solution to this issue is given below the question
My goal is to create an image picker that initially creates each image view inside of a scroll view, and then passes a reference for that image view to a method that will asynchronously update the imageview.image with the appropriate image.
This works great as is.
The issue I run into is that the scroll view only shows the image views in a batch at the end of the method, whereas I'd like for them to print one by one as they are created (image available or not).
If I touch the scroll view to scroll, it works the way I want it to, but if I make no touch at all, the screen stays white until all of the images, not just image views, have finished loading.
I've tried placing setNeedsDisplay everywhere, for every view, including self.view, scrollview, and each individual imageview. What's going on?
- (void)viewDidLoad {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
[self setGridView];
});
}
- (void)setGridView {
// begin loading images
NSString * retina = ([[MVProject sharedInstance] settings_retina]) ? #"2" : #"";
CGRect scrollframe = CGRectMake(0, 0, 300, 275);
UIScrollView * newscrollview;
newscrollview = [[UIScrollView alloc] initWithFrame:scrollframe];
newscrollview.scrollEnabled = YES;
newscrollview.delegate = self;
[newscrollview setContentSize:CGSizeMake(300, (((ceilf([[NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:#"Flickr_Dictionary"]] count]/4)) * (58+15)) + 15 + 58 + 15))];
[picsMVContentCell.contentView addSubview:newscrollview];
float currentx = 11;
float currenty = 17;
NSInteger index = 0;
for (NSDictionary * d in [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:#"Flickr_Dictionary"]]) {
// create button
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(currentx, currenty, 58, 58);
button.imageView.backgroundColor = [UIColor colorWithRed:(241/255.0) green:(241/255.0) blue:(241/255.0) alpha:1];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;
button.imageView.layer.cornerRadius = 6;
button.imageView.layer.masksToBounds = YES;
button.imageView.accessibilityLabel = [d objectForKey:#"id"];
button.imageView.accessibilityValue = [d objectForKey:#"full"];
button.imageView.tag = index++;
[button addTarget:self action:#selector(imageClick:) forControlEvents:UIControlEventTouchUpInside];
UIImage * image = [MVImage imageWithImage:[UIImage imageNamed:#""] covertToWidth:58.0f covertToHeight:58.0f];
[button setImage:image forState:UIControlStateNormal];
[newscrollview addSubview:button];
[newscrollview bringSubviewToFront:button];
[newscrollview setNeedsDisplay];
// calculate next image view position
currentx += (button.imageView.frame.size.width+15);
if (currentx >= 289) {
currentx = 11;
currenty += (button.imageView.frame.size.height+15);
}
// set image
NSString * nsuserdefault = [NSString stringWithFormat:#"Settings_SFThumbs%#_%#", retina, [d objectForKey:#"id"]];
if ([NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:nsuserdefault]]) {
MVImage * thumb = [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:nsuserdefault]];
[button setImage:[MVImage imageWithImage:[[UIImage alloc] initWithData:thumb.data] covertToWidth:58.0f covertToHeight:58.0f] forState:UIControlStateNormal];
} else {
[MVProject asynchronousImageLoad:button.imageView urlpath:[d objectForKey:#"thumb"] nsuserdefaultpath:nsuserdefault];
}
}
}
Edit on Feb 7, 2012 3:26 PM
these changes fixed all issues related to the code given in the question
thanks to #Eugene for pointing me in the right direction
/* ---------- ---------- ---------- ---------- ---------- */
- (void)viewDidLoad {
[super viewDidLoad];
[[MVProject sharedInstance] syncLoadSF:0];
self.newscrollview = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 300, 275)];
self.newscrollview.scrollEnabled = YES;
self.newscrollview.delegate = self;
[self.newscrollview setContentSize:CGSizeMake(300, (((ceilf(([[NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:#"Flickr_Dictionary"]] count]-1)/4)) * (58+15)) + 15 + 58 + 15))];
[picsMVContentCell.contentView addSubview:self.newscrollview];
[self setGridView];
}
/* ---------- ---------- ---------- ---------- ---------- */
- (void)setGridView {
NSString * retina = ([[MVProject sharedInstance] settings_retina]) ? #"2" : #"";
[self.newscrollview setNeedsDisplay];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSInteger index = 0;
for (NSDictionary * d in [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:#"Flickr_Dictionary"]]) {
// create button
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake((11 + ((index%4)*(58+15))), (17 + ((floorf(index/4))*(58+15))), 58, 58);
button.imageView.backgroundColor = [UIColor colorWithRed:(241/255.0) green:(241/255.0) blue:(241/255.0) alpha:1];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;
button.imageView.layer.cornerRadius = 3;
button.imageView.layer.masksToBounds = YES;
button.imageView.accessibilityLabel = [d objectForKey:#"id"];
button.imageView.accessibilityValue = [d objectForKey:#"full"];
button.imageView.tag = index++;
[button addTarget:self action:#selector(imageClick:) forControlEvents:UIControlEventTouchUpInside];
dispatch_sync(dispatch_get_main_queue(), ^ {
[button setImage:[MVImage imageWithImage:[UIImage imageNamed:#""] covertToWidth:58.0f covertToHeight:58.0f] forState:UIControlStateNormal];
[self.newscrollview addSubview:button];
[self.newscrollview bringSubviewToFront:button];
[self.newscrollview setNeedsDisplay];
// set image
NSString * nsuserdefault = [NSString stringWithFormat:#"Settings_SFThumbs%#_%#", retina, [d objectForKey:#"id"]];
if ([NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:nsuserdefault]]) {
MVImage * thumb = [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:nsuserdefault]];
[button setImage:[MVImage imageWithImage:[[UIImage alloc] initWithData:thumb.data] covertToWidth:58.0f covertToHeight:58.0f] forState:UIControlStateNormal];
} else {
[MVProject asynchronousImageLoad:button.imageView urlpath:[d objectForKey:#"thumb"] nsuserdefaultpath:nsuserdefault];
}
});
}
});
[self.newscrollview setNeedsDisplay];
}
You cannot work with drawing on the background thread. Each time you add subview you should do this in the main thread. So the salvation for you would be to use your drawing code in a sync block, that's run on the main queue
dispatch_sync(dispatch_get_main_queue(), ^ {
[newscrollview addSubview:button];
[newscrollview bringSubviewToFront:button];
[newscrollview setNeedsDisplay];
// calculate next image view position
currentx += (button.imageView.frame.size.width+15);
if (currentx >= 289) {
currentx = 11;
currenty += (button.imageView.frame.size.height+15);
}
// set image
NSString * nsuserdefault = [NSString stringWithFormat:#"Settings_SFThumbs%#_%#", retina, [d objectForKey:#"id"]];
if ([NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:nsuserdefault]]) {
MVImage * thumb = [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:nsuserdefault]];
[button setImage:[MVImage imageWithImage:[[UIImage alloc] initWithData:thumb.data] covertToWidth:58.0f covertToHeight:58.0f] forState:UIControlStateNormal];
} else {
[MVProject asynchronousImageLoad:button.imageView urlpath:[d objectForKey:#"thumb"] nsuserdefaultpath:nsuserdefault];
}
});
The problem your having is with setting the images. What your trying to do is add all the image containers to the scrollview. Then as the images are ready load them into their container. There are 2 ways to go about doing this.
First off add all the containers to the scrollview. (You might want some loading indicator or default image to show its loading)
1) Create a background thread for getting the images ready. When the image is ready add it to its container. (I find this way to be more work and kinda a pain)
2) Create a custom container, and let the custom container add its own image when its image is ready.
For example, I am loading images from a server. So I created AsyncImage class that is a custom class of UIImageView. And I created a function that I send the image url to and it handles the rest. It creates an NSURLConnection and when the data is loaded it calls self.image = [UIImage imageWithData:data];