How do you move a UIWebView offscreen?
Is that determined by the CGRect? Or some other property of UIView or UIWindow?
You can try:
[webView setFrame:CGRectMake(320.0f, 0.0f, 320.0f, 480.0f)];
or
[webView removeFromSuperview];
The first one just move it offscreen, you just cannot see it. The second one remove it from superview, maybe it still exist in memory, or maybe it'll removed when received memory warning.
UIWebView is a subclass of UIView (as are most visible objects in cocoa touch) which means you can use setBounds or setFrame in order to 'move' the view. If you use negative or large positive numbers the view will be moved offscreen.
Do remember that things offscreen also take up memory ;-)
Yes, you can do that. You could change the frame property of UIWebView to some coordinates which are off the screen.
You could do this but if you are done with the UIWebView & simply want to close it then this might not be the best solution as the memory allocated is still not released. First animate it off the screen then release it to free the memory. To release it do [YourWebView removeFromSuperview]; [YourWebView release]; YourWebView=nil;.
You can hide it by setting the hidden property to YES.
You can also move it off the screen with the frame, as you mentioned. A good place to start is CGRectMake(self.superview.frame.size.width,self.superview.frame.size.height,...) though it won't do well with rotations.
You can also set the alpha to 0, which is akin to making it hidden.
You can also send it the method removeFromSuperview.
There may be more ways.
Enjoy,
Damien
Related
I am trying to just do a simple view change for proof of concept.
here is the code
- (void)swipedScreen
{
if (self.secondView.superview == nil) {
[myView removeFromSuperview];
[self.view insertSubview:secondView atIndex:0];
}
}
when I swipe the screen what happens is the view area just goes black... and becomes unresponsive.
I started with a navigatoin app, replaced the tableview with just a standard uiviewcontroller class.. that worked fine..Then i added a secondView (xib only) and changed its class to match the viewcontroller of the first view.
The reason I am finding this difficult is because i am trying to animate the views inside the navigation controller and not push a whole view onto the stack which I am used to doing.
I'll bet that blank unresponsive view is, in reality, your secondView object. I always test by setting [secondView setBackgroundColor:[UIColor greenColor]] and checking if the massive green rectangle actually shows up.
EDIT: having looked at your code, there are multiple problems that arose:
You never actually +alloc or -init anything.
You never actually touch those nibs or make a reference to them in code
You declare two UIView's as IBOutlets and Strong (two exact opposites, as IBOutlets are __weak, __unsafe_unretained, or assign), yet do not link them to anything.
I've taken the liberty of revising it (sans nibs). Take a look.
Did you init the secondView? if init,you can try to set frame for the secondView
Your inserting the view at the bottom of the stack,
[self.view insertSubview:secondView atIndex:0];
Try using addSubview instead. Also you need to set the views frame somewhere.
When creating the content view of a tableViewCell, I used the drawInRect:withFont, drawAtPoint... and others, inside drawRect: since all I needed was to lay some text. Turns out, part of the text drawn need to be clickable URLs. So I decided to create a UIWebView and insert it into my drawRect. Everything seems to be laid out fine, the problem is that interaction with the UIWebView is not happening. I tried enabling the interaction, did not work. I want to know, since with drawRect: I am drawing to the current graphics context, there is anything I can do to have my subviews interact with the user?
here is some of my code I use inside the UITableViewCell class.
-(void) drawRect:(CGRect)rect{
NSString *comment = #"something";
[comment drawAtPoint:point forWidth:195 withFont:someFont lineBreakMode:UILineBreakModeMiddleTruncation];
NSString *anotherCommentWithURL = #"this comment has a URL http://twtr.us";
UIWebView *webView = [[UIWebView alloc] initWithFrame:someFrame];
webView.delegate = self;
webView.text = anotherCommentWithURL;
[self addSubView:webView];
[webView release];
}
As I said, the view draws fine, but there is no interaction with the webView from the outside. the URL gets embedded into HTML and should be clickable. It is not. I got it working on another view, but on that one I lay the views.
Any ideas?
You do not want to be creating a new UIWebView and adding it as a subview for each call to drawRect: This is an extremely bad idea:
It's going to be slow. Those are heavy objects, and you're creating thousands of them.
You're not getting rid of the old UIWebView objects. So you're essentially layering thousands and thousands of them on top of one another.
You should be creating the UIWebView once, probably in the initializer, or some other method that is only called once. You should also add it as a subview only once.
The act of creating thousands of those views could certainly be causing your problem.
If your view is changing position/size, then you can override setFrame: and in addition to calling the superclass' method, tweak the frame of the UIWebView, which you'll definitely want to maintain as an instance variable.
This is wrong. You shouldn't be instantiating UIWebView inside -drawRect: - which is, potentially, called repeatedly to refresh screen.
Instead, you should at least create a subclass of UITableViewCell and add to it a UIWebView to hold all of your text.
Even then, UIWebView is probably too heavyweight to be placed in each cell.
You might want to check this out.
I have a UIImageView property in my view controller set to "assign". Every time I hit a button, I set the image in the view to something new. Due to the way I am using another component, I have to removeFromSuperView and release the UIImageView every time I change images and then re add it. This doesn't seem to be contributing to the memory problem-- when using the existing UIImageView and not releasing it the memory still goes up (but there are sizing issues, which is why I am recreating it).
For some reason, using setImage will increase the memory usage of the app by about 0.8mb (the size of the image). When I do NOT set an image, the memory seems to stay relatively constant. Any ideas why?
[self.pictureView setImage: img];
[self.pictureView setFrame: CGRectMake(0,0,[img size].width, [img size].height)];
[img release];
I think you are leaking the UIImageView, and when you leak the UIImageView, you are leaking the image in it.
It depends how you recreate the UIImageView. Be sure that you are releasing the old image view before setting the new one to the property.
It may be best to set the property as retain, because when you set new value to retain property, it releases the old instance.
Maybe set the UIImageView to nil before setting the image to clear out the reference?
pictureView.image=nil;
I have a UIView with a bunch of subviews, all positioned using layoutSubviews. When the view is resized, the relative positions all change. I'd like these re-calculations to happen during an animated resize (using +[UIView beginAnimations:] calls). This doesn't seem to be happening. Any ideas?
Assumption: You want to have multiple animation steps (i.e. position doesn't change linearly with frame size).
This isn't possible with a single "standard" UIView animations. Why? The frame/bounds is only set once.
Core Animation has three "layer trees":
The model tree is where your app thinks things are.
The presentation tree is approximately what's being displayed on screen.
The render tree is approximately what Core Animation is compositing.
UIView is a (somewhat thin) wrapper around the model layer. During a UIView animation, Core Animation updates the presentation/render tree — the model tree represents the endpoint of animations. The upshot is that your code can (for the most part) treat animations as instantaneous — moving a view from A to B instantly moves it to B; the change just happens to be animated to the user.
There are more complicated things you can do with CALayer/CAAnimation directly, but I haven't investigated this much.
You could chain multiple animations together using -[UIView setAnimationDidStopSelector:]. (You could also try using multiple animations together with setAnimationDelay:, but I'm not sure what happens with multiple animations on the same property; you might have luck with setAnimationBeginsFromCurrentState:.)
If you want really fine-grained control, CADisplayLink (OS 3.1+) is a timer that fires after each screen refresh. A fallback option (for 3.0 support) is to use an NSTimer at 30/60 Hz or so.
I know this is an old question, but this code works for me very well (suited for your example of changing frame).
-(void)layoutSubviews{
[super layoutSubviews];
// layout your subviews here, or whatever
}
-(void)someMethod{
double duration=...;
[UIView animateWithDuration:duration animations:^{
self.frame = ...;
[self layoutIfNeeded];
}];
}
Of course you can call this method from another object. The "trick" is to call layoutIfNeeded (or layoutSubviews directly - same thing, if You change the frame the setNeedsLayout is called).
As tc. nicely explained the "layer trees", You just force the presentation layer to display the final stage of model layer with animation.
The advantage of this method is in possibility to control when the frame/bounds change is animated and when it's instant.
Hope this helps someone:).
Completing #GrizzlyNetch's anwer, you can set the UIViewAnimationOptionLayoutSubviews animation option, so you don't need to call layoutIfNeeded:
-(void)someMethod{
double duration = ...;
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^{
self.frame = ...;
} completion:nil];
}
Posting for completeness. Thanks to tc. for explaining that what I want to do, exactly, is not supported by Core Animation.
I eventually came up with a reasonable solution. Rather then layout my subviews in -layoutSubviews, I do so in -setBounds:. Then, when I wrap a -setBounds: call in a UIView +beginAnimations: block, those positioning calls are also animated, and the end result is everything properly animating to where it should god.
I have a UIWebView that I'm setting to some text and displaying and then hiding, changing the text, and displaying again. The issue I'm running in to is that when I make the view visible again I see the old text for an instant. Is there a way to force the UIWebView to show the new text when it displays?
The code is ordered correctly and looks like this:
[back assignLabelText:[facts getCurrentFact].answer];
[self doAnimation:back.view andViewToHide:front.view flipRight:YES];
You should wait until at least the webview's webViewDidFinishLoad: is fired before revealing the webview. Even then there can be some lag, so I add an additional 0.1 second delay before revealing the view.
Call setNeedsDisplay on back's view
[back assignLabelText:[facts getCurrentFact].answer];
[[back view] setNeedsDisplay];
[self doAnimation:back.view andViewToHide:front.view flipRight:YES];
I made some new functions to do my animations and used a delay of 0.1 to run them via performSelector.
It feels like a hack but it works and it takes care of the same issues I was having with UILabels that have their text change.