Creat PDF of UITableView within UIView so all rows print - iphone

I have a UIView holding many things including a UITableView at the bottom. I need to print this page and have all rows show in the final product but I run into problems with rows that are not currently visible in the TableView.
My current attempt to get a final product is to convert my view to a PDF and I have ready Apple's Drawing and Printing guide but it does not give me all the steps I need.
How can I print a UIView and have all the TableView rows, within the UIView, show in the print?

Try the contentSize method, which is inherited from UITableView’s superclass, UIScrollView. However, you may find that contentSize returns an incorrect or out of date value, so you should probably call layoutIfNeeded first to recalculate the table’s layout.
[tableView layoutIfNeeded];
// Allows you to perform layout before the drawing cycle happens.
//-layoutIfNeeded forces layout early. So it will correctly return the size. Like dreaming before doing.
CGSize newTableSize=tableView.contentSize;

- (NSMutableData*)generatePDF {
NSMutableData * pdfData=[NSMutableData data];
[[NSBundle mainBundle] loadNibNamed:#"PDFView" owner:self options:nil];
UIGraphicsBeginPDFContextToData(pdfData, CGRectZero,nil);
CGContextRef pdfContext=UIGraphicsGetCurrentContext();
UIGraphicsBeginPDFPage();
// update the UI elements (IBOutlet on xib file)
//PDFView is main view on xib file containing uitableview too
[self.PDFView.layer renderInContext:pdfContext];
// end PDF context.
UIGraphicsEndPDFContext();
return pdfData;
}

Related

How can I size a UICollectionViewCell based on the content of a UIWebview?

I'm dynamically adding UICollectionViewCells to a UICollectionView using the delegate method cellForItemAtIndexPath. The UICollectionViewCell that is created every time that method runs contains a UIWebView with content that is of varying size. I cannot set the size of the UICollectionViewCell when creating it programmatically. Instead, I have to implement a method called sizeForItemAtIndexPath.
Unfortunately, this size-determining method seems to be called before the method that actually creates the cells. At this time, I cannot reference the size of the UIWebView to help find a good size for the cells. All I have is the actual content of the UIWebView, but I have no idea how to use this to find size, since the content includes styled HTML and images.
I tried to create UIWebViews in memory and to get sizes from them, but I always got 0 for dimensions. I'm somewhat relieved this didn't work because it seems like an ugly hack to me.
Is there something else I can try?
Maybe this helps:
- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
CGRect frame = aWebView.frame;
CGSize fittingSize = [aWebView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
aWebView.frame = frame;
}
My previous answer works not with UICollectionView but with UITableView. This worked for me in a UICollectionViewController:
NSString *webViewHeight = [webView stringByEvaluatingJavaScriptFromString:#"document.getElementById(\"idOfMainElementInHtml\").offsetHeight;"];
Use this in
- (void)webViewDidFinishLoad:(UIWebView *)webView
Remember the values in a NSMutableDictionary which maps NSIndexPath objects to height values. Compare the previous value with the new value every time in this method and then let the Layout object use this dictionary to calculate a new layout.
Have fun :-)

Scroll view with dynamically created thumbnails on iPhone and iPad

I need one long scrollable view with 2 thumbnails (wallpapers) in every row.
Every thumbnail has also a button to share and download photo, and when you click the thumbnail it shows full size wallpaper. So I was thinking about making a custom view (200x200) which will contain thumbnail and two buttons, and add them dynamically to scroll view depending how many wallpapers are on server.
Something like this:
NSUInteger i;
int xCoord=0;
int yCoord=0;
int thumbnailWidth=200;
int thumbnailHeight=200;
int buffer = 10;
for (i = 1; i <= [items count]; i++)
{
UIView *aView = [[ThumbnailView alloc] initWithThumnailAtIndex: i ];
aView.frame = CGRectMake(xCoord, yCoord, thumbnailWidth, thumbnailHeight );
[scrollView addSubview:aView];
xCoord += thumbnailWidth + buffer;
yCoord += thumbnailHeight + buffer;
}
[scrollView setContentSize:CGSizeMake(700, yCoord)];
Do you think that is a good way to do this?
Also, how would I handle lazy loading of thumbnails if there are a lot of thumbnails in scrollview?
As everybody else here has said, use a UITableView. I will add that you should use a custom UITableViewCell subclass. Create the class, then use Storyboards to make a table view scene with prototype cells. Set the class of the prototype cell to your cell subclass. Add as many imageview, labels, buttons, whatever nonsense you want to the prototype cell on the storyboard, then hook those up to your custom class using IBOutlets. Now when it's time to display something in the cell, just pass an object or dictionary containing all the info that's needed to the custom cell subclass, and have it populate the various view via the outlets. Here's a tutorial: http://www.techotopia.com/index.php/Using_Xcode_Storyboards_to_Build_Dynamic_TableViews_with_Prototype_Table_View_Cells
I would suggest you use the UITableView with custom UITableViewCell implementations. The tableview will automatically handle the recycling of the cells, so you would not need to worry as much about performance.
You could pre-load all your assets during the view initialization and then simply use them in the tableview's datasource.
I would use a UITableView and each cell would contain both images. Take a look at this answer.
About loading the images, try using EGOImageLoader, is very simple and effective. Here is the Github project.

UIScrollView scrolling lags

I Have UIScrollView and a few (about 10 "posts").
Post - custom view with UILabe loaded from nib and dinamically changed frame.
So I do:
[[NSBundle mainBundle] loadNibNamed:#"AWPostShortView"
owner:self
options:nil];
// calculate frame etc (doesn't matter)
self.shortPost.frame = frame;
// Add to scrollView
[self.scrollView addSubview:self.shortPost];
self.shortPost = nil;
The problem is that "scrolling" action has lags.
I mean - scroll view follow under cursor with delay
I do not any operations, calculations etc when posts appears.
Please, advise how to optimize it
(I can't use UITableView and reuse cells coz I have different cells heights)

why is my UIView subview not rendering within the parent? (code attached)

Why is my custom UIView not rendering within the UIView container of it's parent? So what I have is:
MainViewController - has a UIView "customViewContainer" (which doesn't take up the whole screen), and
CustomView - is a UIView with a XIB file - it is the UIView here that when it is rendered (with AspectFit) is rendering outside the bounds of the parent "customViewContainer"
The code used to setup the custom view is this extract from MainViewController:
<< cut - see Update2 below >>
So I can't see why the CustomView view is being rendered in a way that is larger in area than the parent customViewContainer? What I want is for the customview to fit into the parent "customViewContainer" entirely per the AspectFit type approach.
thanks
EDIT 1 (added clarification) - If I "clip subviews" in the parent view then it does then clip things, but what I really need to render the custom view within the parent view area (not the whole area of the screen). So I need (a) the center of the custom view to be in the center of the parent view, and (b) custom view to AspectFit into the parent view properly. Any ideas?
EDIT 2 - Update
sorry - made a copy/paste mistake with code in the original question - can't seem to edit it so I'll put a correct version below - so to clarify:
MainViewController - has a UIView "containerView" (which doesn't take up the whole screen), and CustomView - is a UIView with a XIB file - it is the UIView here that when it is rendered (with AspectFit) is rendering outside the bounds of the parent "containerView"
With the code below does this make sense now? The reason for this code is I have a custom UIView, BUT I have a XIB file associated with it, so this was the only way to get my MainController view to be able to use it. That is, have a container view in the MainController view, and then programmatically add the CustomView into the container view.
Re "So set the frame or center of the view that you're adding to be what you want it to be" - are you saying I have to programmatically/manually set the dimension of the CustomView to be what I want (in relation to the parent containerView)?
What I was hoping was there was a way using the declaritive layout setting to some how be able to say "Load the Custom View from it's XIB file, and the aspectFit this view into the self.containerView", however I'm starting to wonder if this is possible?
UPDATED CODE BELOW (made mistake in original question when I copy/pasted it in and changed variables names etc)
- (void)viewDidLoad
{
[super viewDidLoad];
// Load the custom Altimeter View into this UIControllerView's container UIView for it
NSArray *nibs = [[NSBundle mainBundle] loadNibNamed:#"Customview" owner:self options:nil];
for (NSObject *obj in nibs) {
if ( [obj isKindOfClass:[Customview class]]) {
Customview *cv = (Customview*)obj;
[self.containerView addSubview:cv];
break;
}
}
// UI Layout
self.containerView.layer.borderWidth = 2;
self.containerView.layer.borderColor = [[UIColor redColor] CGColor];
}
Check if the "Clip subviews" property of parent on the IB file is checked.
I think the equivalent code is self.view.clipsToBounds = YES.
if this is NO, subviews that draws outside will be visible as if it's drawn on the parent.

How to update a label of a custom view within a scroll view using a timer

Please help!
I define a custom UIControl with three labels, then on the viewDidLoad function of the main view controller, I repeatedly add multiple instances of that UIControl into the scroll view.
I need one of the label within the UIControl to be updated with new value each second. I have a question, how to clear the previously drawn custom view? Or what is the method for updating that label with best drawing performance?
- (void) updateMinuteLabel{
CustomIconControl *control = nil;
for (control in scrollView.subviews){
if ([view isKindOfClass:[CustomIconControl class]] && control.tag >0){
CustomIconControl *item = (CustomIconControl *) control;
item.intMinute += 1;
[item setNeedsDisplay];
}
}
}
In the drawRect: function of the CustomIconControl, I use the
[minuteString drawInRect: minuteRect withFont: [UIFont systemFontOfSize:10];
With this code, it continues to draw without clearing out the previously drawn controls.
Can someone help? Please tell me if you need more information, of course I have the code for custom drawing part of the CustomIconControl, the initialization of the timer, viewDidLoad etc.
You say your UIControl has three labels, do you mean you are adding three UILabel's as subviews of the UIControl? If so, you can just the text' property of the label to the value and it will automatically redraw itself - no need to [minuteString drawInRet...
Otherwise, if you're drawing the three "labels" in drawRect:, calling setNeedsDisplay: after intMinute is updated should cause drawRect: to be called, thus drawing the updated text.
Also, I recommend your CustomIconControl be responsible for calling setNeedsDisplay on itself when intMinute is updated.
Andrew