How to get dynamicaly height of image in dispatch_async method in scrollview - objective-c

I am using below code to get the images from server. i want to get dynamicaly height of image and add image in scrollview.
From below code when i get the height outside the dispatch_async method it shows zero.
How i can get the dynamically height of image with async image load.
- (void)viewDidLoad {
[self LoadViewPublicEvents];
}
-(void) LoadViewPublicEvents
{
for (int i=0;i<arrayPublicEvents.count;i++)
{
UIImageView *img_vw1=[[UIImageView alloc] init];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://abc.us/uploads/event/%#",[[arrayPublicEvents objectAtIndex:i] valueForKey:#"image"]]]];
UIImage *images = [[UIImage alloc]initWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^{
img_vw1.image = images;
scaledHeight = images.size.height;
});
});
NSLog(#"%f",scaledHeight); // it print zero
img_vw1.backgroundColor=[UIColor clearColor];
img_vw1.frame=CGRectMake(0,y+5,screen_width,197);
[img_vw1 setContentMode:UIViewContentModeScaleAspectFit];
img_vw1.backgroundColor=[UIColor clearColor];
[self.scrll_vw addSubview:img_vw1];
}
}
Thanks in advance

Your code:
NSLog(#"%f",scaledHeight); // it print zero
img_vw1.backgroundColor=[UIColor clearColor];
img_vw1.frame=CGRectMake(0,y+5,screen_width,197);
[img_vw1 setContentMode:UIViewContentModeScaleAspectFit];
img_vw1.backgroundColor=[UIColor clearColor];
[self.scrll_vw addSubview:img_vw1];
Is being executed, before you loaded the image.
Thus you have to either wait (herefore you could use semaphores until the thread has finished) OR you place it inside of your block.
As you want to modify the UI it makes sense to place it into the main block:
UIImageView *img_vw1=[[UIImageView alloc] init];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://abc.us/uploads/event/%#",[[arrayPublicEvents objectAtIndex:i] valueForKey:#"image"]]]];
UIImage *images = [[UIImage alloc]initWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^{
img_vw1.image = images;
scaledHeight = images.size.height;
NSLog(#"%f",scaledHeight); // it print zero
img_vw1.backgroundColor=[UIColor clearColor];
img_vw1.frame=CGRectMake(0,y+5,screen_width,197);
[img_vw1 setContentMode:UIViewContentModeScaleAspectFit];
img_vw1.backgroundColor=[UIColor clearColor];
[self.scrll_vw addSubview:img_vw1];
});
});
For more information, here is a link to Apple's documentation: https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

Related

Create custom UIImage from json data

could you please provide me by sample code for creation a UIImage object with specific width and height programmatically in the code then load an Image in it which supposed to fetch from json (it has to be an image URL).
If I use synchronous network request for loading the picture does it block my UI till loading be completed or not? if so what's the solution?
Thanks in Advance
Pull out the image URL from your json data, download the image, and then use the image as needed.
NSString *imageURL = url from your json string;
NSURL *url = [NSURL URLWithString:imageURL];
UIImageView *imageView = [UIImageView alloc] initWithFrame:CGRectMake(0,0,50,75)];
[yourParentView addSubview: imageView];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
UIImage *image = [UIImage imageWithData: [NSData dataWithContentsOfURL:url]];
dispatch_sync(dispatch_get_main_queue(), ^{
imageView.image = image;
CGRect frame = CGRectMake(imageView.origin.x, imageView.origin.y, image.size.width, image.size.height);
imageView.frame = frame;
});
});

Can not adjust UIPopupController to display images

In my application (code listed below), I use a popover to display a series of colors that the user can choose. These colors are used for the color of the drawing they are completing above. I am trying to modify the popover to work the same way, except for this time I would want to display images (the images are saved in the application's documents folder as png files) instead of blocks of color. Listed below is the working code for the color selector popover. ColorGrid is a UIview which contains an NSArray Colors, as well as two NSUIntegers columnCount and rowCount. I have tried to replace the items in the colors array with UIImages of the png files, as well as UIImageViews but I have not been able to get a successful result (or a compilable one). Listed below is the working code. Could anyone show me how I can change the UIColor items to the images to show them in the grid?
- (IBAction)popoverStrokeColor:(id)sender {
StrokeColorController *scc = [[[StrokeColorController alloc] initWithNibName:#"SelectColorController" bundle:nil] autorelease];
scc.selectedColor = self.strokeColor;
[self doPopoverSelectColorController:scc sender:sender];
}
- (void)doPopoverSelectColorController:(SelectColorController*)scc sender:(id)sender {
[self setupNewPopoverControllerForViewController:scc];
scc.container = self.currentPopover;
self.currentPopover.popoverContentSize = scc.view.frame.size;
scc.colorGrid.columnCount = 2;
scc.colorGrid.rowCount = 3;
scc.colorGrid.colors = [NSArray arrayWithObjects:
//put the following below back in after testing
[UIColor blackColor],
[UIColor blueColor],
[UIColor redColor],
[UIColor greenColor],
[UIColor yellowColor],
[UIColor orangeColor],
//[UIColor purpleColor],
// [UIColor brownColor],
// [UIColor whiteColor],
// [UIColor lightGrayColor],
//[UIColor cyanColor],
//[UIColor magentaColor],
nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(colorSelectionDone:) name:ColorSelectionDone object:scc];
[self.currentPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; //displays the popover and anchors it to the button
}
Thanks for your help. I am new to objective-c.
edit - heres the function with my attempt to insert the images instead of the colors
- (void)doPopoverSelectColorController:(SelectColorController*)scc sender:(id)sender {
[self setupNewPopoverControllerForViewController:scc];
scc.container = self.currentPopover;
self.currentPopover.popoverContentSize = scc.view.frame.size;
// these have to be set after the view is already loaded (which happened
// a couple of lines ago, thanks to scc.view...
scc.colorGrid.columnCount = 2;
scc.colorGrid.rowCount = 3;
//here we need to get the UIImage items to try to put in the array.
NSArray *pathforsave = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [pathforsave objectAtIndex:0];
//here we need to add the file extension onto the file name before we add the name to the path
//[fileName appendString:#".hmat"];
NSString *strFile = [documentDirectory stringByAppendingPathComponent:#"test.png"];
NSString *strFile1 = [documentDirectory stringByAppendingPathComponent:#"test1.png"];
NSString *strFile2 = [documentDirectory stringByAppendingPathComponent:#"test2.png"];
NSString *strFile3 = [documentDirectory stringByAppendingPathComponent:#"test3.png"];
NSString *strFile4 = [documentDirectory stringByAppendingPathComponent:#"test4.png"];
NSString *strFile5 = [documentDirectory stringByAppendingPathComponent:#"test5.png"];
//now for the Images
UIImage *image = [ UIImage imageWithContentsOfFile: strFile];
UIImage *image1 = [ UIImage imageWithContentsOfFile: strFile1];
UIImage *image2 = [ UIImage imageWithContentsOfFile: strFile2];
UIImage *image3 = [ UIImage imageWithContentsOfFile: strFile3];
UIImage *image4 = [ UIImage imageWithContentsOfFile: strFile4];
UIImage *image5 = [ UIImage imageWithContentsOfFile: strFile5];
UIImageView *imageview = [[[UIImageView alloc] initWithImage:image] autorelease];
[self.view addSubview:imageview];
UIImageView *imageview1 = [[[UIImageView alloc] initWithImage:image1] autorelease];
[self.view addSubview:imageview1];
UIImageView *imageview2 = [[[UIImageView alloc] initWithImage:image2] autorelease];
[self.view addSubview:imageview2];
UIImageView *imageview3 = [[[UIImageView alloc] initWithImage:image3] autorelease];
[self.view addSubview:imageview3];
UIImageView *imageview4 = [[[UIImageView alloc] initWithImage:image4] autorelease];
[self.view addSubview:imageview4];
UIImageView *imageview5 = [[[UIImageView alloc] initWithImage:image5] autorelease];
[self.view addSubview:imageview5];
imageview.image = image;
imageview1.image = image1;
imageview2.image = image2;
imageview3.image = image3;
imageview4.image = image4;
imageview5.image = image5;
scc.colorGrid.colors = [NSArray arrayWithObjects:
// When attempting to add the images like this - get the error identified expected
// after the e in image, at the end bracket. Putting a * does nothing to change the error
[image],
// When adding one of the Imageviews, i get the same error as above
//below is how I attempted to add it
[imageView],
//
nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(colorSelectionDone:) name:ColorSelectionDone object:scc];
[self.currentPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; //displays the popover and anchors it to the button
}
Remove your square brackets around image and/or imageView :
scc.colorGrid.colors = [NSArray arrayWithObjects:
// Not : [image] but
image,
// or
imageView,
// Not : [imageView],
nil];

Activity Indicator while loading images inside UIScrollView

I have UIScrollView that contains images from the server.
I should put Activity Indicator while the image is currently loading.
UIScrollView contains dynamic number of images from the server.
May I know how can I add activity indicators on each page while the image is loading and remove once image is loaded.
Here's my code to retrieve images:
NSDictionary *items = [NSDictionary dictionaryWithObject:dictInfo forKey:#"images"];
imageList = [items objectForKey:#"images"];
NSArray *img = [imageList objectForKey:#"list"];
NSInteger imgCount = [img count];
buttonArray = [[NSMutableArray alloc] init];
for (int i=0; i<imgCount; i++) {
NSDictionary *imgDict = [img objectAtIndex:i];
// REQUEST FOR IMAGES
NSString *imgPath = [imgDict objectForKey:#"image_slot"];
NSString *imgURL = imgPath;
__block ASIHTTPRequest *requestImage = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:imgURL]];
[requestImage setCompletionBlock:^{
imgView = [UIImage imageWithData:[requestImage responseData]];
if (imgURL.length) {
[pendingRequests removeObjectForKey:imgURL];
}
scrollView.userInteractionEnabled = YES;
scrollView.exclusiveTouch = YES;
scrollView.canCancelContentTouches = YES;
scrollView.delaysContentTouches = YES;
scrollView.bounces = NO;
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
SWTUIButton *imgBtn = [[SWTUIButton alloc] initWithFrame:frame];
imgBtn.url = [requestImage.userInfo objectForKey:#"rURL"];
[imgBtn setImage:imgView forState:UIControlStateNormal];
imgBtn.backgroundColor = [UIColor clearColor];
[imgBtn addTarget:self action:#selector(buttonpushed:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:imgBtn];
[buttonArray addObject:imgBtn];
[imgBtn release];
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * img.count, self.scrollView.frame.size.height);
}];
I highly suggest you use NINetworkImageView from https://github.com/jverkoey/nimbus project.
It's very light and useful.
It has a delegate method to let you know when an image is loaded.
What you basically need to do is:
1. create an NINetworkImageView for each page, just like you do with UIImageView, and call set
NINetworkImageView* networkImageView = [[[NINetworkImageView alloc] initWithImage:initialImage]
autorelease];
networkImageView.delegate = self;
networkImageView.contentMode = UIViewContentModeCenter;
[networkImageView setPathToNetworkImage:
#"http://farm3.static.flickr.com/2484/3929945380_deef6f4962_z.jpg"
forDisplaySize: CGSizeMake(kImageDimensions, kImageDimensions)];
https://github.com/jverkoey/nimbus/tree/master/examples/photos/NetworkPhotoAlbums
the add the indicator to the networkImageView as a subview.
implement the delegate as follows:
-(void)networkImageView:(NINetworkImageView *)imageView didLoadImage:(UIImage *)image {
[imageView removeAllSubviews];
}
the end result would be a much smaller code for doing the same thing.

Lazy loading of PhotoLibrary Images

i found an issue with Photo Library Images. It not displaying first time in my View,Image View is blank while loading first time.
Because i found Asset Library block working on another thread.After reloading my View ,I can see all the Images. However first time the Image Views are Blank.
can any one tell me a good way to deal with the problem
It working with Bundle Images.
also some times console shows that
app is crashing due to Program received signal: “0”. Data Formatters temporarily unavailable, will re-try after a 'continue'. (Unknown error loading shared library "/Developer/usr/lib/libXcodeDebuggerSupport.dylib")
My Code:
for (int j = 0; j<9; j++)
{
//allocating View
UIView *smallView = [[UIView alloc] initWithFrame:CGRectMake(xCordImage, yCordImage, 200, 190)];
// allocating ImageView
imageViewTopic = [[[UIImageView alloc] init] autorelease];
typedef void (^ALAssetsLibraryAssetForURLResultBlock)(ALAsset *asset);
typedef void (^ALAssetsLibraryAccessFailureBlock)(NSError *error);
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
{
ALAssetRepresentation *rep = [myasset defaultRepresentation];
CGImageRef iref = [rep fullResolutionImage];
UIImage *images;
if (iref) {
images = [UIImage imageWithCGImage:iref];
}
else {
images = [UIImage imageNamed:#"Nofile.png"];
}
imageViewTopic .image = images ;
};
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror)
{
imageViewTopic .image = [UIImage imageNamed:#"Nofile.png"];
NSLog(#"booya, cant get image - %#",[myerror localizedDescription]);
};
NSString *string ;
MyClass *obj = [imageFileNameArray objectAtIndex:j];
**//obj.fileName contains ALAsset URL of a Image**
string = obj.fileName;
NSURL *asseturl = [NSURL URLWithString:string];
ALAssetsLibrary* assetslibrary = [[[ALAssetsLibrary alloc] init] autorelease];
[assetslibrary assetForURL:asseturl resultBlock:resultblock
failureBlock:failureblock];
imageViewTopic.userInteractionEnabled = YES;
imageViewTopic.frame = CGRectMake(0,0, 200, 150);
[currentView addSubview:scroller];
**// adding the imageView to View**
[smallView addSubview:imageViewTopic];
[myView addSubview:smallView];
[scroller addSubview:myView];
}
I am using this method to show images in scroll view with lazy loading. It works well.
First initialize the value of j1. And data is the image data coming from loop from an array.
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSData * data = [[NSData alloc] initWithContentsOfURL:url];
if ( data == nil )
return;
dispatch_async(dispatch_get_main_queue(), ^{
__block int j1=_j;
// WARNING: is the cell still using the same data by this point??
// NSURL *url = [NSURL URLWithString: imageName];
UIImage *image = [UIImage imageWithData: data]; //image.size.height
image1=[[UIImageView alloc] initWithFrame:CGRectMake(j1,10,image.size.width,image.size.height)];
image1.image=image;
CALayer *layer = [image1 layer];
[layer setMasksToBounds:YES];
[layer setCornerRadius:0.0]; //note that when radius is 0, the border is a rectangle
[layer setBorderWidth:3.0];
[layer setBorderColor:[[UIColor whiteColor] CGColor]];
[portfolio_scroll addSubview:image1];
});
});
_j = _j+ 320;

How can i scroll images dynamically

I m pretty new to iPhone development. I'm trying to implement scroll view with loading images dynamically from web. I m trying to use the following code.
for (counter = 0; counter < 2; counter++) {
RSSEntry *entry = [_allEntries objectAtIndex:counter];
NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: entry.articleUrl]];
UIImage *img = [UIImage imageWithData: imageData];
NSLog(#"%#", entry.articleUrl);
UIImageView *imageView = [[UIImageView alloc] initWithImage:img];
[imageData release];
CGRect rect = scrollViewController.frame;
imageView.frame = rect;
imageView.tag = (counter + 1); // tag our images for later use when we place them in serial fashion
[scrollViewController addSubview:imageView];
[imageView release];
}
These are two images that I load up on viewDidLoad. I want to load the next image when the user scroll onto the second image and if the user scroll next want to show that the image is loading. Any suggestion?
You muse use NSURLConnection and download the images asynchronously. You can use TCImageView
https://github.com/totocaster/TCImageView
It downloads the images in an async way.
I would also recommend Three20's TTImageView.