I'm inserting images in a UITableViewCell with AFNetworking. The problem is that i need to scroll the table to see the images.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
Recipe *recipe = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = recipe.value;
NSURL *url = [NSURL URLWithString:[BaseURLString stringByAppendingString:recipe.img]];
[cell.imageView setImageWithURL:url];
return cell;
}
There is such a method already implemented by AFNetworking in UIImageView+AFNetworking category.
[imageView setImageWithURLRequest:request placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
blockImageView.image = image;
} failure:nil];
Note that if you pass in nil in success the image is set to the imageview you call the method on. In my case imageView.
So here i guess you can do reload data if you need.
In addition to Peter Segerblom's answer, I would recommend using a __weak reference in place of the __block blockImageVariable variable to avoid a retain cycle.
If you just use __block, the copy of the imageView will never be deallocated and the count will always remain even after the tableView is gone because the pointer is referencing another memory address.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.textLabel.text = #"Cell text";
NSURLRequest *request = [NSURLRequest requestWithURL:imageURL];
__weak UITableView *weakTableView = tableView;
__weak UITableViewCell *weakCell = cell;
__weak UIImageView *weakImageView = cell.imageView;
[cell.imageView setImageWithURLRequest:request
placeholderImage:placeholderImage
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
weakImageView.image = image;
if ([weakTableView.visibleCells containsObject:weakCell]) {
[weakTableView reloadRowsAtIndexPaths:#[ indexPath ] withRowAnimation:UITableViewRowAnimationNone];
}
} failure:nil];
return cell;
}
#pxpgraphics: I had to replace
NSURLRequest *request = [NSURLRequest requestWithURL:imageURL];
with
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:imageURL]];
to prevent a runtime error .
Swift equivalent:
let request = NSURLRequest(URL: book.mediumImageURL)
cell.imageView.setImageWithURLRequest(request, placeholderImage: nil, success: { [weak cell] request, response, image in
if cell {
cell!.imageView.image = image
}
if tableView.visibleCells().bridgeToObjectiveC().containsObject(cell) {
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
}
}, failure:nil)
I think this is the best code to use:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
NSURL *url = [NSURL URLWithString:#"http://www.myimageurl.com"]; //Change this URL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
__weak UITableViewCell *weakCell = cell;
__weak UIImageView *weakImageView = cell.imageView;
[cell.imageView setImageWithURLRequest:request placeholderImage:[UIImage imageNamed:#"granaziOrange"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
weakImageView.image = image;
[weakCell setNeedsLayout];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
NSLog(#"Failed to get image");
}];
return cell;
}
This post has an answer that works: http://jabbleashish.blogspot.com/2013/12/setting-uitableviewcell-imageview-via.html
NSURLRequest *imageRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:#"YOUR_URL"]];
[cell.imageView setImageWithURLRequest:imageRequest placeholderImage:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image){
NSLog(#"success");
cell.imageView.image = image;
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
cell.imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[cell setNeedsLayout];// To update the cell {if not using this, your image is not showing over cell.}
}failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error){
NSLog(#"Failure");}
This seems straightforward without having to reload the cell according to index path.
it depends on the cell type - if you have a custom cell with your own UIImageView inside, make sure you DON'T call its outlet "imageView"! Because there is already internal imageView inside every cell.
I solved the problem by renaming linked IBOutlet with something like *myImageView and now everything works fine with code:
[cell.myImageView setImageWithURL:[NSURL URLWithString:#"http://placehold.it/100x100"]];
Related
I am setting image on UITableViewCell using image url ,but the images doesn't get load unless i scrolls the UITableView.Here is the code that i have been using,i got to know about SDWeb Image library to download images from url,but i does;t want to use any library.Please tell me what aim doing wrong in this.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
NSDictionary *dictCard=[cardsDetailsArray objectAtIndex:indexPath.row];
UILabel *nameLabel = (UILabel *)[cell viewWithTag:10];
UILabel *dateLabel = (UILabel *)[cell viewWithTag:11];
UIImageView *cellImage=(UIImageView *)[cell viewWithTag:0];
CGSize firstSize=CGSizeZero;
if([[dictCard objectForKey:#"orientation"]isEqualToString:#"1"]){
[cellImage setFrame:CGRectMake(0, 0, 75, 68)];
firstSize=CGSizeMake(75,68);
}
if([[dictCard objectForKey:#"orientation"]isEqualToString:#"0"]){
[cellImage setFrame:CGRectMake(0, 0, 107, 72)];
firstSize=CGSizeMake(107,72);
}
[cellImage setBackgroundColor:[UIColor clearColor]];
NSString *string=[dictCard objectForKey:#"email_sent"];
NSArray *items = [string componentsSeparatedByString:#","];
dateLabel.text=[dictCard objectForKey:#"date"];
nameLabel.text=[NSString stringWithFormat:#"Sent to %d People",[items count]];
NSURL* url = [NSURL URLWithString:(NSString *) [dictCard objectForKey:#"card_thumbnail"]];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (!error){
UIImage* image = [[UIImage alloc] initWithData:data];
//i am scaling the image here
UIImage *imageScale=[self imageWithImage:image scaledToSize:firstSize];
[cellImage setImage:imageScale];
}
}];
return cell;
}
I have also added [__tableViewDraft reloadData];after setting the cell image but due to this my cell keeps on changing its cell image.
Once the image has been downloaded, you need to ask iOS to refresh the cell. Check out reloadRowsAtIndexPaths:withRowAnimation:, among others.
Typically you might have have cells backed by CoreData objects and download and save the image to the managed object. You'd then have an NSFetchedResultsControllerDelegate trigger an update when the managed object changes, refreshing the row.
My question probably has a really obvious answer which I'm missing. I have an NSURLConnection like so:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *urlstring = [NSString stringWithFormat:#"http://127.0.0.1:8000/image/"];
NSMutableURLRequest *postRequest = [NSMutableURLRequest
requestWithURL:[NSURL URLWithString:urlstring]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:30.0];
[postRequest setHTTPMethod:#"POST"];
self.firstConnection = [[NSURLConnection alloc] initWithRequest:postRequest delegate:self];
}
-(void)connectionDidFinishLoading:(NSURLConnection*)connection
{
if (connection == _firstConnection){
// Deal with the data
[self getImages];
[self.collectionView reloadData];
}
-(void)getImages
{
NSError *error;
NSMutableArray* images= [NSJSONSerialization JSONObjectWithData:_data options:0 error:&error];
NSUInteger arrayLength = [images count];
dressURLS = [[NSMutableArray alloc] init];
for (NSInteger i=0;i<arrayLength;i++)
{
NSString *temp = [images[i] objectForKey:#"image"];
[dressURLS addObject:temp];
}
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UIImageView *dressImageView = (UIImageView *)[cell viewWithTag:100];
NSString *clothesurl = dressURLS[i]; //i value????
NSString *url =[NSString stringWithFormat:#"http://127.0.0.1:8000/media/%#",clothesurl];
NSURL *imageURL = [NSURL URLWithString:url];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
dispatch_async(dispatch_get_main_queue(), ^{
// Update the UI
dressImageView.image = [UIImage imageWithData:imageData];
});
});
return cell;
}
The code is quite messy, I'm aware. This is how it works. viewDidLoad initializes the connection. It goes to connectionDidFinishLoading where getImages deals with the data which I had to manipulate and store in an array. Then I used the reloadData method to go to the Collection View which is where I run into all kinds of problems.
I need to access the elements of dressURLS[i] where i=0,1,2,3. But the looping is severely complicated by the fact that a. The collection view gets reloaded b. The asynchronous dispatch. I am unable to get i to loop from 0 to 3.
Any solutions to make this less complicated?
-(void)connectionDidFinishLoading:(NSURLConnection*)connection
{
if (connection == _firstConnection){
// Deal with the data
[self getImages];
[collectionView reloaddata]; // or self.collectionView (for property)
}
}
"Discussion
Call this method to reload all of the items in the collection view. This causes the collection view to discard any currently visible items and redisplay them." - Apple
You can the BOOL for the first time & for second time check the condition & display the images by reloading the Collection View.
I'm using UICollectionView to display images which are loading from the device photo gallery. I'm using Asset Library to load the images. When I'm scrolling the UICollectionView, images are changing their positions inside the collection view (not duplicating). Therefore when I clicked on an image, different image is loading. Any help?
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UIImageView *GalleryImageView = (UIImageView *)[cell viewWithTag:100];
url=#"";
Document* doc = [galleryImages objectAtIndex:indexPath.row];
GalleryImageView.contentMode = UIViewContentModeScaleAspectFill;
url = doc.path;
NSLog(#"%#",url);
NSURL *referenceURL = [NSURL URLWithString:url];
__block UIImage *returnValue = nil;
[library assetForURL:referenceURL resultBlock:^(ALAsset *asset)
{
returnValue = [UIImage imageWithCGImage:[[asset defaultRepresentation] fullScreenImage]];
GalleryImageView.image = returnValue;
returnValue = nil;
documentID= [dbutil getDocumentIDbyPath:url];
GalleryImageView.tag = documentID;
}
failureBlock:^(NSError *error)
{
NSLog(#"error : %#", error);
}];
return cell;
}
I am showing the images in the tableview using NSData dataWithContentsOfURL method but when i scroll the tableview GUI gets hanged.so after searching over the forum i found that i can try with NSUrlConnection method. so i tried but i cant implement it successfully.
Please find my code below...
kindly help me out that how i can correctly done it..
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:#"DataIdentifier"] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = [UIColor colorWithRed:230.0/255.0 green:249.0/255.0 blue:230.0/255.0 alpha:2.0];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
profileName = [appDelegate.arrCommunityUserList objectAtIndex:indexPath.row];
NSString *imgName = [profileName.user_image stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *strValue = [NSString stringWithFormat:#"%d", profileName.userID];
if (tableView == myTableView)
{
cellRectangle = CGRectMake(15, 2, 75, 75 );
NSString *myurl = [NSString stringWithFormat: #"%#pics/photos/%#/%#",ConstantImgURL, strValue,imgName];
NSURL *url = [NSURL URLWithString: myurl];
imageView = [[UIImageView alloc] initWithFrame: cellRectangle];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:myurl]];
[NSURLConnection connectionWithRequest:request delegate:self];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection =[[NSURLConnection alloc] initWithRequest:
request delegate:self];
if (theConnection)
{
receivedData = [[NSMutableData data] retain];
}
[cell.contentView addSubview:imageView];
}
}
return cell;
}
// did receive response
- ( void )connection:( NSURLConnection * )connection didReceiveResponse:( NSURLResponse * )response
//--------------------------------------------------------------------------------------------------
{
NSLog(#"Received response: %#", response);
}
// get recieved data
- ( void )connection:( NSURLConnection * )connection didReceiveData:( NSData * )data
//----------------------------------------------------------------------------------
{
// NSLog(#"Connection received data, retain count: %d", [connection retainCount]);
[receivedData appendData:data];
}
// finished loading
- ( void )connectionDidFinishLoading:( NSURLConnection * )connection
//-------------------------------------------------------------------
{
// Set appIcon and clear temporary data/image
UIImage *image = [[UIImage alloc] initWithData:receivedData];
imageView.image = image;
}
// connection failed with error
- ( void )connection:( NSURLConnection * )connection didFailWithError:( NSError * )connError
//---------------------------------------------------------------------------------------
{
// NSLog(#"Error receiving response: %#", connError);
[connection release];
[receivedData release];
}
dataWithContentsOfURL is a synchronous network request. That means that where your code is called it will wait until the request finishes before moving on to the next instruction. Synchronous networking is bad. Really bad. It only really ever works in testing.
What you should be doing, is firing off asynchronous requests for these images. The reason why your code above is horrendously slow is that every single time that the tableView asks its dataSource delegate for cellForRowAtIndexPath:; your code fires off a network request synchronously - which means the cell won't be returned until the network request for the image is finished.
Instead, what you should be doing is either loading all the images asynchronously when the tableView is requested. Here's a good example which uses tags to identify them as they return. This is not easy in the whole context of what you're doing; so perhaps you might want to start all the NSURLConnections when the tableView is shown, return 0 for numberOfSectionsInTableView until the connections finish, then call reloadData on the tableView when they're all finished (and make numberOfSectionsInTableView now return the right number of rows to display).
Start using ASI library: http://allseeing-i.com/ASIHTTPRequest/How-to-use
The sooner the better.
I think this might solve your Problem... http://www.markj.net/iphone-asynchronous-table-image/
Kindly look the below code..i found from web
- (void) loadData {
NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
selector:#selector(loadDataWithOperation) object:nil];
[queue addOperation:operation];
[operation release];
}
- (void) loadDataWithOperation {
NSURL *dataURL = [NSURL URLWithString:#"http://icodeblog.com/samples/nsoperation/data.plist"];
NSArray *tmp_array = [NSArray arrayWithContentsOfURL:dataURL];
for(NSString *str in tmp_array) {
[self.array addObject:str];
}
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[cell.textLabel setText:[self.array objectAtIndex:indexPath.row]];
return cell;
}
I have found the above code which loads the text from the web without any problem.( i mean gui is not hanging ).like wise i want to load images into the table view.for that i have wriiten the below code.
- (void) loadDataWithOperation {
NSString *Img_id, *Img_name, *DynamicImgUrl;
Img_id = xmltag.equip_id;
Img_name = xmltag.image;
DynamicImgUrl = [NSString stringWithFormat:#"http://test.com/pics/equipment/%#/%#",Img_id, Img_name];
NSURL *ImageUrl = [NSURL URLWithString:DynamicImgUrl];
//UIImage *image = [UIImage imageWithData: [NSData dataWithContentsOfURL:ImageUrl]];
NSArray *tmp_array = [NSArray arrayWithContentsOfURL:ImageUrl];
for(NSString *str in tmp_array) {
[self.array addObject:str];
}
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
}
Am i correct here? how can i go with adding into the table view...
Kindly help me out...
U are seeking to display images on Tableview from URL, when u download image from url we need to consider some issues, it will freeze ur table view if u goahead with ordinary loading image.
i suggest u look at LazyLoading image
u see this link http://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html
Download this sample and get to know the things