UIScrollView scrolling lags - iphone

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)

Related

Creat PDF of UITableView within UIView so all rows print

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;
}

Disable the parent view when subview opened

I have two views. viewController and myCustomAlert. i have added myCustomAlert as a subview in viewController.
this is the function which is called when myCustomAlert is added as a subview.
-(void)ratingAction:(id)sender
{
if ([sender isKindOfClass:[UIButton class]])
{
[[NSBundle mainBundle] loadNibNamed:#"myCustomAlert" owner:self options:nil
];
Custom_view.frame = CGRectMake(10, 100, 287, 165);
[self.view addSubview:Custom_view];
self.view.userInteractionEnabled = false;
Custom_view.userInteractionEnabled = true;
}
}
i want parent view to be disabled so i disable the userinteraction but it disable the subview too. how to do that?? i want my subview to work like an alert.
One approach you can try is set subviews frame in a way that it completely hides its super view controller i.e. 0,0,320,460 and make sure that the content on subviews are properly placed at position where you want, and then make the background color of subview transparent.
myCustomAlert.backgroundColor = [UIColor clearColor];
when you add a subview to a specific view, the subview and parent become one view collectively, i.e. the parent view. so disabling interaction will disable both.
for you is to present modelview controller with animated property as false and disable parent view interaction. tell me if you achieve your goal

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.

Swipe to Reveal Menu like Tweetie

I've been working on a new app and was really hoping to implement a swipe to reveal more options menu inside my application. I've searched and searched, but it seems no one else has successfully made it work (aside from Loren). What I'm trying to do is swipe the cell, and simultaneously use CABasicAnimation to push it to x: 320, and add a subview below this that would have the buttons etc.. I'm using willBeginEditing to detect the swipe to avoid subclassing. Here's the code:
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
CABasicAnimation *theAnimation;
theAnimation=[CABasicAnimation animationWithKeyPath:#"transform.translation.x"];
theAnimation.duration=0.0;
theAnimation.repeatCount=0;
theAnimation.autoreverses=NO;
theAnimation.removedOnCompletion = NO;
theAnimation.fillMode = kCAFillModeForwards;
theAnimation.fromValue=[NSNumber numberWithFloat:0];
theAnimation.toValue=[NSNumber numberWithFloat:+320];
[cell.layer addAnimation:theAnimation forKey:#"animateLayer"];
CGRect frame = CGRectMake(0, 59 * indexPath.row, 320, 59);
UIView *menu = [[[UIView alloc] initWithFrame:frame] autorelease];
NSString *path = [NSString stringWithFormat:#"%#%#",
[[NSBundle mainBundle] resourcePath],
#"/flick.wav"];
SystemSoundID soundID;
NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID);
AudioServicesPlaySystemSound(soundID);
self.menu.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"dots.png"]];
[self.view addSubview:menu];
[self.view sendSubviewToBack:menu];
}
- (void)animationDidStop:(NSString*)animationID finished:(BOOL)finished context:(void *)context
{
// Release
[self release];
}
#pragma mark - Swipe Menu II
- (void)scrollViewDidScroll:(UIScrollView *)tableView {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:nil];
CABasicAnimation *theAnimation;
theAnimation=[CABasicAnimation animationWithKeyPath:#"transform.translation.x"];
theAnimation.duration=0.2;
theAnimation.repeatCount=0;
theAnimation.autoreverses=NO;
theAnimation.fromValue=[NSNumber numberWithFloat:320];
theAnimation.toValue=[NSNumber numberWithFloat:0]
;
[cell.layer addAnimation:theAnimation forKey:#"animateLayer"];
}
The problem is the sliding back of the cell - I want to do it when any touch outside the menu view is received, but because it is a scrollView, I can't. The ScrollViewdidScroll Method only animates the cell back to its normal place once it is scrolled of the viewport. (As in, under the NavigationBar or object that obscures it) The last key issue is the ability to detect if a menu is already visible or active and a cell is already off of the screen, slide the cell back to its original position, remove the menu view, and then slide the other cell out and add the menu.
I would like to be the first beside Loren to implement this as so many others have tried, especially on StackOverflow.
I apologize for the poor formatting in the code.
Thanks in advance,
Kolin
I've actually made this work quite nicely, you can check out the project here: http://www.thermoglobalnuclearwar.com/opensource/
It also overcomes the problem in Tweetie where you cannot swipe the same cell twice without first swiping something else.
If you make any constructive changes, or need any help, let me know!
Loren's implementation has a fatal flaw, which is if you swipe on a cell, then scroll the table, you cannot re-swipe the same cell until you swipe a different cell. I believe this is because the tableview believes the cell is still being edited until you try and "edit" another cell.
You may want to investigate doing something else instead, like using a UISwipeGestureRecognizer attached to the cell to detect the swipe.
I can think of 2 approaches to try and detect taps outside of the cell as well. The first is to subclass UIApplication and override -sendEvent:. You can use this to detect the tap event and dismiss the cell "editing". The main problem here is giving the UIApplication subclass knowledge about your cell. The second approach is to slap a custom UIView subclass over the entire screen and in -hitTest:withEvent: you can test to see if the touch belongs to the area over your cell. If it doesn't, dismiss the cell "editing". In both cases, return nil to allow the event to proceed to the underlying views (and don't forget to remove this overlay view after the event happens). You may also want to test the UIEvent to make sure it contains a new touch before dismissing the cell.

How to create view from a nib file in xcode?

I have the following code to create a view and put it in scrollview to allow paging
the code works fine however what I couldn't do is loading views from a nib file
in other words
I want to use "initWithNibName" instead of "initWithFrame"?
- (void)createPageWithColor:(UIColor *)color forPage:(int)page
{
UIView *newView = [[UIView alloc] initWithFrame:CGRectMake(0, 300,400)];
newView.backgroundColor = color;
[scrollView addSubview:newView];
}
Thanks alot
I know this is an old post, but I wanted to create a UIView as a separate file and add a xib so I could use it in several places in my app (almost like using it as a custom table view cell). And I couldn't get it quite right, but this post helped me get to the result I wanted.
So just if anyone wants to do it the same way, this is what I did:
Add this to the initialization code in your UIView's .m file:
- (id)initWithFrame:(CGRect)frame
{
self = [NSBundle mainBundle] loadNibNamed:NSStringFromClass(self.class) owner:self options:nil][0];
if (self)
{
self.frame = frame;
}
return self;
}
Then in interface builder/xib editor you have to assign the class you created for the UIView so you can add IBOutlets.
Hope it helps someone out, cuz it took me a bit!
I think the thing you're missing is that you can set the frame of your new UIView after loading the nib. Load/Init time isn't your only shot at that. I'm also breaking the load function into its pieces, in the code below, so you can see more easily what's going on.
Observe:
NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:#"yournib"
owner:self
options:nil];
//I'm assuming here that your nib's top level contains only the view
//you want, so it's the only item in the array.
UIView *myView = [nibContents objectAtIndex:0];
myView.frame = CGRectMake(0,0,300,400); //or whatever coordinates you need
[scrollview addSubview:myView];
Don't forget that for that UIScrollView to actually scroll, you need to set its contentSize property to the size of the goods inside it, which is likely bigger than the .frame property of the scroll view itself.
Try something like this (adapted from "The iPhone Developers Cookbook", pg. 174):
UIView *newView = [[[NSBundle mainBundle] loadNibNamed:#"yournib" owner:self options:nil] lastObject];
This assumes a single view object in your .xib, but you could modify it if your .xib is more complicated.