Setting Multiple Images from SQL to Table View Cells - objective-c

I trying to set multiple images from SQL into Table View Cells using
SDWebImage.
I am using this code right now but this loads one image based on a URL.
[cell.imageView setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
How would you populate the imageView for multiple images? Thanks.
I tried using a for-loop. Does not work.
NSArray *itmImageArray = [self itemImages];
for(int i = 0; i <= [itmImageArray count]; i++)
{
[cell.imageView setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/%#",[itmImageArray objectAtIndex:i]]
placeholderImage:[UIImage imageNamed:#"addnewimage.png"]];
}

A UITableViewCell has only one imageView. The technique you are using will keep resetting the same imageView that a UITableViewCell has by default and what you will see is the last image of your for loop set in the cell. If you want to display more images you will have to create a custom cell and add multiple UIImageViews as subviews of the cell. You can then set different images into the UIImageViews you add. Remember, you will have to handle the frames of UIImageViews as well as height of the tableView row so that the content is displayed properly.

Related

Programmatically drawn UIView tags (or something alike)

I'm drawing a view that contains an xib, multiple times (same uiview) and then update the outlets each time it gets drawn displaying an nsmutablearray with different strings on the outlets
Clicking the view opens a viewcontroller that should be displaying the data from the view (+more), this works perfectly fine except it doesn't know which index of the array it's supposed to be displaying.
I'm trying to figure out a way to manage them in a way that I can see which view is being pressed so I can pass that 'id' onto the new vc (something to uniquely identify the view even though it's the same view being drawn)
Here's how the view is being drawn multiple times
- (void) populateUpcoming:(int)events {
[self resetVariables];
upcomingEventsCenterPos = self.view.frame.size.width / 2 - 159;
for (int i = 0; i < events; i++) {
upcomingEventsY2 = 175 * upcomingEvents2;
UIView *firstViewUIView = [[[NSBundle mainBundle] loadNibNamed:#"UpcomingEventFull" owner:self options:nil] firstObject];
[_scrollView addSubview:firstViewUIView];
CGRect frame = firstViewUIView.frame;
frame.origin.y = 9 + upcomingEventsY2;
frame.origin.x = upcomingEventsCenterPos + upcomingEventsX2;
firstViewUIView.frame= frame;
upcomingEvents2++;
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(tapUpcomingEvent:)];
[firstViewUIView addGestureRecognizer:singleFingerTap];
}
[self setupScroll];
}
I think you can use UITableView and custom UITableViewCell for this purpose. On click of "Add More", add one entry to NSMutableArray and just reload tableview.
And no need to manage index separately, you can get it directly by indexPath.row
Also you don't need to manage scroll view size as tableview automatically adjust is content height according to row.
If you are using same kind of view,then go with this approach, as its easy and will save your time.

UIImage as accessory view in UITableViewCell not showing

Within my app, I bring up a UITableView when prompting the user to select an item. Based on whether the item is in stock, out of stock, on order, etc., I want to display an image on the right-hand side of the UITableViewCell.
I have tried using the accessory view button, but it isn't showing up on the UITableViewCell. I have tried changing the UITableViewCellStyle to UITableViewCellStyleValue2 (the style with the detail closure button), and have also tried setting the accessory type of the cell directly.
static NSString *CellIdentifier = #"MyCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
//cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier];
}
[cell.textLabel setText:#"Testing"];
[cell.detailTextLabel setText:#""];
//cell.accessoryType = UITableViewCellAccessoryNone;
//cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
UIImageView *imageView = [[UIImageView alloc] initWithImage:[myImageFilePath stretchableImageWithLeftCapWidth:0 topCapHeight:1.0]];
[imageView setContentMode: UIViewContentModeScaleAspectFit];
[imageView setFrame:CGRectMake(0, 5, cell.frame.size.height - 10, cell.frame.size.height - 5)];
cell.accessoryView = imageView;
return cell;
When the app runs, the UITableViewCells appear with the "Testing" text, but there is no image on the right-hand side of the cells.
Is there another method that needs to be overridden in order to implement a custom UIImage for the detail diclosure button?
The "button" is more of a status indicator, because I don't want the tap of the button to do anything different than tapping anywhere else on the UITableViewCell does (just select the row).
Some additional info:
If I remove
[imageView setFrame:CGRectMake(0, 5, cell.frame.size.height - 10, cell.frame.size.height - 5)];
then the image shows up in the UITableViewCell, but it is too big and does not fit on a single row, so it overlaps with other rows' accessory views.
I was using the setFrame so that it would resize the image to fit with the UIViewContentModeScaleAspectFit so that it would fit on the row, but it seems to prevent the image from appearing at all.
Note that in this example cell.frame.size.height = 44.
If I change the frame to:
[imageView setFrame:CGRectMake(0.0, 0.0, 120, 44)];
then the image appears on the row.
However, since it is 120 pixels wide, it is cutting off the text with the trailing ... earlier that needed. The image could fit about 3 times before the trailing ..., with the width being 120 and height being 44.
How can I get the trailing ... to get closer to the image?
If I reduce the 120 to a lower value, the image moves to the right and eventually runs off the cell.
The width of the UITableView was 804. Updating it to 768 allowed me to use the original code that was posted.
Your question is very similar to this one here:
Using a custom image for a UITableViewCell's accessoryView and having it respond to UITableViewDelegate
You can ignore the "have it respond" bit unless you need to. But, as you can see there, the rect is square for the accessoryView property, so an image that is 120x44 is probably not going to fit correctly, ever.
I would rethink your approach to this problem, and create a custom UITableViewCell subclass that has the necessary items you require (sounds like a UILabel and a UIImageView). This way, you can easily control how large the label is versus how large the image is, how the label will wrap lines (if it wraps at all or maybe truncates) and so on.
Another way is just subclass the UITableviewCell and set frame's in "layoutSubviews" and also make sure to pass correct row height for each cell.
By subclassing you will get full flexibility.
hope this helps
I guess there's an issue with your CGRect X and Y, in this case here 0 and 5. Maybe trying to set them dinamically can fix this. Let me know

How to display tableview images as soon as they are downloaded rather than after reloading cells

I have a table view that displays a list of users. The avatar images in each cell are downloaded asynchronously using UIImageView+AFNetworking and displayed using UIImage+TPAdditions. Here is my code snippet, from cellForRowAtIndexPath:
if (cell==nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:SimpleTableIdentifier];
}
cell.textLabel.text = [[global.people objectAtIndex:indexPath.row]name];
// setImageWithUrl:placeholderImage: is taken from UIImageView+AFNetworking
NSString* imgURL = [[global.people objectAtIndex:indexPath.row]avatar_url];
UIImageView* imgV = [[UIImageView alloc]init];
[imgV setImageWithURL:[NSURL URLWithString:imgURL] placeholderImage:[UIImage imageNamed:#"icon.png"]];
//These are just for formatting and are taken from UIImage+TPAdditions
cell.imageView.image = [imgV.image imageScaledToSize:CGSizeMake(43,43)];
cell.imageView.layer.masksToBounds = YES;
cell.imageView.layer.cornerRadius = 5.0;
Now when the app loads we just see the placeholder images until the user scrolls the tableview up and down. Then the avatar images from the URLs are loaded into each cell's image view. I want to make it so that this scrolling is not required- I want the avatar images to "pop" into their respective cells' tableviews as soon as they are downloaded. I know NSNotification might help me, but I'm not really sure where/how to use that. I'm fairly new to iOS. Can anyone walk me through it?
Thanks
You'll want to call setNeedsDisplay on your view to force a refresh. You would call this in your asynchronous call's completion handler.

Advice for horizontal scroll view IOS

I'm trying to create horizontal scroll view(s). Each view containing one image. [done]
Initially when app is opened I'd display couple of images i.e 3, so user can scroll back and forth between images. [done]
However I want to be able to go to another view controller and pick another image(s) maybe two for example and display five images in the scroll view instead of displaying 3 initially.
How would one do that? to "re-refresh" the initial scroll view ?
Update
Should I use delegate for this communication between view controllers? or how is this done?
1 main controller, other containing image selection?
This part above and much more explained by article here.(not advertising, I hope it will help someone as well).
Bounty update part 1 :
I think now that I found my way around delegates, I have additional question that I cannot find answer to, all examples I saw were about updating table views.
Bounty part 2 :
If I were to have a scrollview inside my view controller and some nsimages inside scroll view. i.e :
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *images = ...some images array;
for (int i = 0; i < images.count; i++) {
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIImageView *subview = [[UIImageView alloc] initWithFrame:frame];
subview.image = [images objectAtIndex:i];
[self.scrollView addSubview:subview];
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * images.count, self.scrollView.frame.size.height);
}
And let say my view controller implemented some delegate method didAddImage or didRemoveImage.
Meaning that about images array would get updated.
Actual bounty question :
How would one actually "tell" the view controller, O.K now your scrollview has one more image to display, please re-fresh or reload?
If I were to have a table view instead scroll view and was inserting images I'd do it something like this(in my delegate method) :
-(void) mockDelegatetablemethod:(...) ...{
[self.images addObject:image];
NSIndexPath *indexPath =
[NSIndexPath indexPathForRow:[self.images count] - 1
inSection:0];
[self.tableView insertRowsAtIndexPaths:
[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
[self dismissViewControllerAnimated:YES completion:nil];
}
How would one do this to the scrollview?
Bounty update part 3:
This is "simple" case described above, naturally I'd have to support removing images also as well as if one wants to remove all images and add some new.
How would one actually "tell" the view controller, O.K now your
scrollview has one more image to display, please re-fresh or reload?
Well, you would just add the new image as a subview of the scroll view. So something like:
- (void)addImage:(UIImage*)image {
[images addObject:image];
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * images.count;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIImageView *subview = [[UIImageView alloc] initWithFrame:frame];
subview.image = image;
[self.scrollView addSubview:subview];
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * images.count, self.scrollView.frame.size.height);
}
Or you could have a method that goes and "resets" the scroll view by removing all subviews and then re-adds all the images in your images array. Then call this method in viewDidLoad instead of your code there so that you're not duplicating code.
Basically, there's no silver bullet here. You roll your own.
You're going to need make your image scroller a class that you can tell to load up certain images. You'll need a reference to the existing image scroller, pass that pointer into your other "pick more images" controller. Then the "pick more images" controller can tell the image scroller that there is a new list of images.
This is already implemented by Apple in their iOS sample project "PhotoScroller". It has view reuse as well. They even have a WWDC 2010 video on this. I think its advanced scrollview techniques OR designing apps with scrollviews.
Shouldn't be hard to port over to mac

How to refresh view in objective-c

I wanted to create a gallery. It loads different images based on the category, that a user selects. I used to populate images in UIImageViews.
My when selecting different categories is that it does not clear the previously selected images. This is my code for populating images.
-(void)refresh{
categoryLabel.text = treatment.treatmentName;
NSMutableArray *galleryImages =[NSMutableArray alloc] ;
galleryImages = [[PatientImage alloc]find:treatment.treatmentId];
int imgCount = [galleryImages count];
for(int i=0;i<imgCount;i++){
PatientImage *apatientImage = [galleryImages objectAtIndex:i];
UIImage *img1 = [UIImage imageNamed:apatientImage.imageBefore];
UIImageView *myImageView = [[UIImageView alloc] initWithImage:img1];
myImageView.contentMode = UIViewContentModeTopRight;
myImageView.frame = CGRectMake(120+i*240,120.0,100.0, 100.0);
[self.view addSubview:myImageView];
UIImage *img2 = [UIImage imageNamed:apatientImage.imageAfter];
UIImageView *myImageView2 = [[UIImageView alloc] initWithImage:img2];
myImageView2.contentMode = UIViewContentModeTopRight;
myImageView2.frame = CGRectMake(120+i*240+300,120.0,100.0, 100.0);
[self.view addSubview:myImageView2];
}
}
First things first, You have some memory leaks there. You are allocating UIImageViews but are not releasing them anywhere, after you have added them to your view. I don't know if that applies to ARC, though. Same applies to your Mutable array, but I suppose you are releasing it after the 'for' loop somewhere, since it seems you posted code after omitting some of it.
As far as your actual question is concerned, I wouldn't do this this way. I would make the mutable array an object variable, and then fill it with my image views. When calling refresh again, I would first call -removeFromSuperview on each image view, then empty the array, then repopulate it and add the new subviews to my view. That is the simple way.
I don't know if you are using ARC, but you should be careful about memory management when using dynamically loaded views. Each time you add a view to another one, you increase its retain counter. You must then call release to remove ownership, and let the iOS runtime handle the rest.
Also note that operations such as this using views are expensive in terms of memory. So, another way of repopulating the gallery view is to just change the image an imageView holds. That will save you some memory, and time. In case the view doesn't have a constant number of images to be displayed, you can refine your algorithm to change the images on the already created image views, and then add more image views if necessary or delete the remaining ones, if any.
I hope I helped.
try at the start of refresh call
[[self subviews] makeObjectsPerformSelector: #selector(removeFromSuperview)];
or
for (id imageView in self.subviews){
if([imageView isKindOfClass:[UIImageView class]]) [imageView removeFromSuperview];
}
call [tableview reloadData] if You are using tableview to show your gallery images
or call view's
[self.view setNeedsDisplay] method for refreshing the view.