I'm looking to execute some code on any transitions away from my current UIView. The view itself is probably going to stick around and not be garbage collected, so viewDidUnload is probably not the appropriate event.
Is there another event, or method, for detecting when a given view is no longer being displayed?
-(void)viewWillDisappear:(BOOL)animated;OR
-(void)viewDidDisappear:(BOOL)animated;depends on business logic you want to implement
Related
This question seems to get asked a lot but I have never found a definitive answer as to whether or not it's possible to have custom transitions the same way UIKit does.
I know you can do tricks like take a screenshot of the current view and the upcoming view, and then animate those while you change view controllers under the animation. However, this takes quite a bit of memory, as you have basically 2 full extra screens worth of drawing (because of the screenshots).
I'm looking for a more elegant way of presenting view controllers with a custom animation. Or, is there a more memory-efficient way of doing the above approach?
There are several ways to accomplish this, depending on how you want to transition, whether your controllers are embedded in a container controller, etc. In the simplest case, where you have a single controller, and you want to transition to another controller, you can do it with the following steps:
instantiate the new controller (lets call it B, and the original one A)
add B's view as a subview of the window (gotten from self.view.window)
set B's frame to be off screen in which ever direction you want or make its alpha 0, or make it have zero size, depending on what kind of transition you want.
do what ever transition you want with animateWithDuration:animations:completion:
remove A's view (in the completion block)
in the completion block, make B the root view controller of the window
Essentially you're having the system automatically retain and release, along with do whatever is happening below the calls rdelmar's answer outlined. Transitioning a view controller is just animating a view while having the system keep your controller in memory.
But, to answer more of your questions, UIView animations create duplicates and cache the images, too. (Btw, the system cache doesn't unload its memory, so avoid UIImage imageNamed.
You will probably want to code it yourself using a timer if you want efficiency, and drum up all the graphics tricks you can think of.
And never, ever trust iOS to work the same way it did the last version. Everything I said is subject to being wrong the same way iOS 6 broke retain on annotating, and the manuals stated iOS 3 animations will become obsolete (and are now replaced instead?) gah, just saying be careful with efficiency, it may be broken or updated in the somewhat distant future if you try it.
I have two overlapping UIViews, and I want both to respond to user touches. At the moment, only the last view that was loaded responds.
How do I get both to respond to touch events?
you could provide a simple protocol which sends all touch events from the first view to the view in the background. So let the view in the background be a delegate of the first view would be a very simple approach.
Otherwise override the method touchesBegan:withEvent: of the view in the front and call the corresponding method of the view in the background.
Cheers,
anka
If you call touchesBegan/Moved/Ended on super after you handle them I think you will achieve what you want.
Finally, since I don't need that both responds at the same time, I made a workaround. I used the methods bringSubViewToFront: and sendSubViewToBack:. This methods made the work.
I'm trying to change the background view for cells that the user starts to drag with the handle out on the right hand side.
Apparently the selectedBackground view is not used in this state, is there any other solution?
This seems to be a tough one. It doesn't seem as if Apple has provided a way to notify the developer that the user has started reordering a table view cell. So I think this is what you'd have to do:
Subclass UITableViewCell.
Override the touchesBegan et al methods (this might get you started: http://devblog.wm-innovations.com/2010/03/30/custom-swipe-uitableviewcell/)
If you detect a "drag" touch event and the cell's showsReorderControl property (see http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewCell_Class/Reference/Reference.html) returns YES, swap out the backgroundView, remembering the previous one.
When the touch event ends, restore the old view.
Realize that it's not as easy as above 4 steps.
Custom touch handling inside a tableview is possible but hard. You might have to temporarily disable touch events in the UITableView (climbing up the responder chain) to make this work.
I hope these pointers get you moving in the right direction, though.
I'm using UITableView's selectRowAtIndexPath:animated:scrollPosition to slide some of my UITableViewCells into place when a user selects them. When the animation completes, I want to display some additional metadata over the cell. The problem I'm having is that I can't seem to figure out a way to determine whether or not the UITableView will actually scroll, so that my metadata drawing routine can be called (in scrollViewDidEndScrollingAnimation). If the position of the cell is exactly where it should be when a user selects one, then no animation is needed, and scrollViewDidEndScrollingAnimation never gets called. Is there an easy way to determine if the UITableView doesn't need to scroll, or do I need to do all of these calculations manually at the time when I call selectRowAtIndexPath? I can't help but think that I'm missing some easy way to make this determination.
(Note: One reason I'd prefer not to do the calculations myself is that my rows are of different sizes, and determining if the scroll offset is positioned where it should be is a bit of a hassle)
One way is to use delayed performance. Store the current contentOffset. Do the selection with selectRowAtIndexPath:animated:scrollPosition: and then immediately call performSelector:withObject:afterDelay: with a very small delay (0.1, say). In the method you call with performSelector:..., ask for the current contentOffset again. If it hasn't changed, I think you may assume it isn't going to - we are not going to scroll! So you may proceed with your metadata display now. If it has changed, then do nothing and let your scrollViewDidEndScrollingAnimation take care of it.
I know this seems sort of skanky, but I find myself using delayed performance a lot to work around automatic animations of this sort.
I'm about to start a new iPhone app that requires a certain functionality but I'm not sure if it's doable. I'm willing to research but first I just wanted to know if I should at least consider it or not.
I haven't seen this in an app before (which is my main concern, even though I haven't seen too many apps since I don't own an iPhone), but an example would be the iPhone shortcuts panels: you can hold on an app, and then drag it to another panel, sweeping while still dragging it. But this is the core app, is it possible to reproduce something similar within a normal app?
I only need to be sure it can be done before I start digging, I don't need code examples or anything, but if you have some exact resources that you consider helpful, that would be appreciated.
Thanks!
Yes. If you have your custom UIView subclass instance inside a UIScrollView, your view controller just needs to set the UIScrollView to delay content touches and not allow it to cancel touch events.
[scrollView setCanCancelContentTouches:NO];
[scrollView setDelaysContentTouches:YES];
When the user taps and holds in the custom view, the event goes to that custom view, which can process the touch events to drag an item around, but if the user quickly swipes, it scrolls the view.
The "panel" view that you're referring to appears to be a UIPageControl view — although, perhaps, the specific incarnation of this view that Apple uses for the iPhone's home page may be customized.
Instances of generic UIView views that you might touch-and-drag will receive touch events. By overriding methods in the view, these events can be processed and passed to the page control, in order to tell it to "sweep" between pages.
If I wanted to do what you're asking about, that's how I might approach it. It seems doable to me, in any case.
Start with this: Swip from one view to the next view
Try using a UIButton that tracks the time since the state of the button changed to "highlighted". You may need to do this in order to track the dragging and move the button around:
Observing pinch multi-touch gestures in a UITableView
Check to see if the button starts overlapping one side of the screen while being dragged. If s certain amount of time elapses since the button first started overlapping the edge and then manipulate the UIScrollView so that it switches to the next page on the corresponding side of the screen
You may need to use NSTimer to keep track of how long the button is held down, etc.
In any case there's no reason why this couldn't work.
If UIButton doesn't work then perhaps try a custom subclass of UIControl (which tracks the same touch down actions etc.). If that doesn't work then use the window event intercept thing to track everything.