Animating UIPickerView - iphone

Hi I am developing an iPhone app which uses pickerview, Upon shaking app selects one random choice. Everything works well but I was wondering is there any way to animate the UIPIckerView as Urban Spoon has done it.

Confession time: when I posted the other answer, I hadn't ever used Urban Spoon, and I assumed you were being lazy. I'm not overwriting my earlier answer, because such a rude response deserves the downvotes it got.
If I were going to make an animation like the ones on urban spoon's picker wheels, I'd probably use UIImageView's flipbook-style animation, as demonstrated here: http://iosdevelopertips.com/graphics/animated-gif-animated-images-iphone-style.html
Short version: the property UIImageView.animationImages can be loaded with an NSArray of UIImages. You can set properties like .animationRepeatCount and .animationDuration. And then [UIImageView startAnimating] will make that thing start animating.
I'd guess Urban Spoon does that for a second with the "fast rolling" set of images, replaces that with the "medium-speed rolling" set of images, and then gets rid of the UIImageView entirely and replaces it with a UIPickerView that's animating its way to a pre-selected random position.

The method you want is
- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated
All else fails, you could always try looking at the docs. http://developer.apple.com/iphone/library/documentation/uikit/reference/UIPickerView_Class/Reference/UIPickerView.html

Related

What is a UIGobblerGestureRecognizer?

I have just a regular UITableView, and I ran this code:
UITableView *tableView = [[UITableView alloc] init];
for(UIGestureRecognizer *gesture in tableView.gestureRecognizers)
{
NSString *className = NSStringFromClass([gesture class]);
NSLog(#"ClassName:%#", className);
}
One of the output lines is: ClassName:UIGobblerGestureRecognizer
Surprisingly Google has nothing on this. Anyone have any idea what it is?
Most likely this is an internal class that Apple uses. I've come across custom subclasses of UIGestureRecognizers that Apple created for some specific use. I'm sure they have needed to create custom gesture recognizers for various reasons, just as I have and not all of those classes are exposed for us to use.
Check out http://oleb.net/blog/2013/02/new-undocumented-apis-ios-6-1/
BJ Homer believes UIGobblerGestureRecognizer is used to avoid
recognition while animations are in progress. Otherwise, it’s
inactive. In an interesting Twitter conversation, Filippo Bigarella
and Conrad Kramer discovered that UIGobblerGestureRecognizer can
“gobble” touches in order to prevent other gesture recognizers from
receiving them in certain situations. What situations those are, I
don’t know.
I'm very sure it is used to prevent normal interaction while a particular cell is showing a delete confirmation button, and recognise any touch down as triggering that cell to return to a non-editing state.
It has this method and I'm assuming that excludedView is the cell that is showing a delete confirmation button, since you can normally still interact with cells in this state.
- (id)initWithTarget:(id)arg1 action:(SEL)arg2 excludedView:(id)arg3;
https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/UIKit.framework/UIGobblerGestureRecognizer.h
In short, from what I've read and what my experiments have shown, the "gobbler" seems to gobble up the swipes and touches on a table view (actually table cells) when a state transition (initiated by the user's touch or swipe) is in progress, so that the state transition can be completed before the user can touch the table again. Apple may use it in other cases but it is on the table view that I have observed the gobblers.
Now the long story: Suppose your table view implements a "drawer" on the table cell, like Apple's mail app or message app. When you open the drawer with a back swipe and take an action on any of the buttons in the drawer, all is well. But if you just close the draw with a forth swipe, you'll likely find that your next back swipe on a random cell doesn't work. But if you keep doing the back swipes, the next swipe usually will work again to show the drawer. Simply put, if you just open and close the drawer on random cells by using swipes, you'll find sometimes the drawer doesn't open.
I see this behavior on my table and thought I did something wrong. I tried many things and eventually implemented my own subclass of UITableView which also supports UIGestureRecognizerDelegate. In my subclass I implemented the delegate's shouldBeRequiredToFailByGestureRecognizer function, just to print out the gestureRecognizer and otherGestureRecognizer pairs. Then I found that when the back swipe is recognized, the gobbler is NOT present in the pairs. But when the back swipe is not working, the gobbler definitely IS present.
The general opinion on the web is that the gobbler is used to prevent the user from causing another state transition on the table while one transition is already in progress. That is fine if the user indeed takes some action (by touching a button in the drawer). But when the user just closes the drawer, the gobbler should be cancelled. Or the gobbler should be added ONLY when the user takes an action. After my realization, I went on to try my theory on Apple's apps. I already knew the Mail app behaves perfectly responding to every swipe. But the Message app behaves intermittently to repeated drawer opening swipes, much like my app. So I guess the developers of Mail are more careful and used internal knowledge to get it right. My observation is done on iOS 8.4 on iPhone 6 and iPad 2. And I believe the same gobbler issue dates back at least from the first iOS 8 release because I know my app had the issue from day 1 (months ago) but I just got around to look into the problem.
it should definitely be part of private API ..
i will suggest to stay out of it

UIWebView: Tracking screen updates (dirty regions)

I'm trying to detect animations and other screen updates as they happen inside a UIWebView. I would like to get the rectangles of areas in the UIWebView that have been modified since the last refresh.
I think really what I'm looking for is for a way to "trap" the calls that UIWebView makes to setNeedsDisplayInRect. Is there a way to do that? Can I somehow subclass UIWebView's underlying CALayer object in a way that would allow me to catch those calls as they come in from UIWebView?
There's no good way of doing that. You can try grabbing a snapshot of the UIWebView's CALayer and comparing it to the previous snapshot, but I've had a lot of trouble getting reliable snapshots of UIWebViews.
Use an Objective-C category (#implementation CALayer (MyCALayer)) - like you're already doing based on your update - to trap the calls going from UIWebView to CALayer.
Then, use Method Swizzling to relay your category overrides to the original CALayer object.

UIImageView Intro Animation issue

I am trying to create an intro animation for my iOS app and am having issues with timing. In particular I would like to change screens after the intro animation plays. I currently use a UIImageView and there does not appear to be a way to do this. Many stackoverflow questions say to use an NSTimer or performSelector:afterDelay but these are not accurate timers and in my case are completely wrong. Here is what I am doing.
Set UILaunchImageFile to LaunchImage.png
AppDelegate allocs an IntroViewController
IntroViewController.LoadView allocs IntroView
IntroView.initWithFrame performs the following
UIImageView* iv =
iv.animationImages =
iv.animationDuration = 2.0
iv.animationRepeatCount = 1
[iv startAnimating]
Set NSTimer/performSelector:afterDelay?
When timer triggers change from IntroViewController to something else.
If I perform either step 5 or 6 it does not work correctly. It does correctly play the animation and it will correctly change the view/view controller, but the timing is horribly horribly wrong. When you call startAnimating in this manner it may not actually start the animation for a full second or two. I presume because the app is still loading in resources somehow. This time however is not consistent across the simulator or all devices. Infact several runs on the same device may have different results. Thus I can not hard code some delay.
All I want to do is detect that a UIImageView animation has played the last frame and do something. That's it. The best solution I've found so far is to set a timer in some manner and then do something, but in my situation a timer is not a solution.
Any ideas?
The long delay you observe is due to reading and decoding the images, which UIImageView does before the animation begins.
Core Animation performs the animation for you, and it does its drawing in the render server, which is in a separate process. Remember that what you see on the screen doesn't necessarily represent your app's instantaneous picture of your layer tree: Core Animation Rendering Architecture.
UIImageView doesn't provide facilities to give you accurate results here. I'd suggest:
Make a UIView of your own.
Create a CAKeyframeAnimation with discrete calculation mode and your images' CGImageRefs as its values.
Set the animation's delegate to your IntroViewController.
Add the animation to your view's layer for the "contents" key.
Your IntroViewController will get animationDidStop:finished: when it's done.
Two things to consider, though:
First, you'll get better results using a movie rather than a series of images, since the movie can be streamed from storage.
Second, and more importantly, this solution will improve the timing situation but will not totally mitigate it. animationDidStop:finished: is called when your app thinks the animation is done… which is not necessarily exactly when it appears to finish.
You'll do better if you don't rely on delegate callbacks for media timing: instead, add this animation and the animation transitioning your views (using a CAAnimationGroup if necessary) in the same turn of the run loop. Delay the latter with a beginTime of the first animation's duration. Depending on what you're doing, you may have to set the second animation's fill mode as well to get the correct behavior during the first.

UIViewController not responding to touches

Hey all, I'm completely stumped with this iPhone problem.
This is my first time building a view programmatically, without a nib. I can get the view displaying things just fine, but the darn ViewController isn't responding to touches the way it used to in programs where I used a nib. I should add that in the past, I started with the View-Based Application template, and this time I used the Window-Based Application template.
My thinking is that the View-Based template does something magical to let the iPhone know where to send the touch events, but I can't figure out what that would be even after several hours of bumbling around Google. Or I could be looking in an entirely wrong place and my troubles are related to something else entirely. Any thoughts?
There's nothing magical in the view-based template. The most likely reasons for failure to respond to touches are:
You've messed with touchesBegan:withEvent:, userInteractionEnabled, exclusiveTouch or something else, thinking you need to mess with these (generally you don't; the defaults are generally correct)
You created a second UIWindow
You put something over the view (even if it's transparent)
Simplify your code down to just creating a view programatically that responds to a touch and nothing else. It should be just a few lines of code. If you can't get that working, post the code and we'll look at what's going on.
Problem solved. touchesEnded != touchedEnded.
That'll teach me to program without my glasses on.
Another possible scenario for failure in response to touches is when your VC frame is not predefined and its boundaries are actually exceeding the window placeholder. It happens a lot when you just forget to define the frame property for the VC.
Once you define it correctly - User interaction returns to normal.
Good luck !

Custom view transition in OpenGL ES

I'm trying to create a custom transition, to serve as a replacement for a default transition you would get here, for example:
[self.navigationController pushViewController:someController animated:YES];
I have prepared an OpenGL-based view that performs an effect on some static texture mapped to a plane (let's say it's a copy of the flip effect in Core Animation). What I don't know how to do is:
grab current view content and make a texture out of it (I remember seeing a function that does just that, but can't find it)
how to do the same for the view that is currently offscreen and is going to replace current view
are there some APIs I can hook to in order to make my transition class as native as possible (make it a kind of Core Animation effect)?
Any thoughts or links are greatly appreciated!
UPDATE
Jeffrey Forbes's answer works great as a solution to capture the content of a view.
What I haven't figured out yet is how to capture the content of the view I want to transition to, which should be invisible until the transition is done.
Also, which method should I use to present the OpenGL view?
For demonstration purposes I used pushViewController. That affects the navbar, though, which I actually want to go one item back, with animation, check this vid for explanation:
http://vimeo.com/4649397.
Another option would be to go with presentViewController, but that shows fullscreen.
Do you think maybe creating another window (or view?) could be useful?
While I cannot completely answer your question without doing some more research of my own, I can help a bit:
-In order to get the view of a UINavigationController, you need to take a screenshot. The easiest way to do this is by grabbing it into a UIImage:
UIGraphicsBeginImageContext(self.view.frame.size);
[[self.view layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage* test = UIGraphicsGetImageFromCurrentImageContext();
UIImageView* view = [[UIImageView alloc] initWithImage:test];
UIGraphicsEndImageContext();
I am not sure if you can render a GLContext (not familiar on the phone) into a CGImage, but I would do something like that (and init a UIImage from that). I would prerender every frame of the animation you are trying to do and slap it into an UIImageView using the animation stuff provided within. That is, if your animation is simple enough. Otherwise, it might come down to writing your own animation function :-/
I have just put together a transition class to implement your own transition animation in OpenGL ES.
Feel free to read about it here
There are two example transitions in the project, feel free to add you own to it.
I think the function you might be thinking of is http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexImage2D.xml ... you set the viewport to the texture size and then draw as usual, then do glCopyTexImage2D to copy the scene onto a texture.
or you should look into FrameBuffer Objects. The default OpenGL template in XCode uses these. Just generate the example project to see how those work.
I recently write some transitioning animation betweeen view controllers like you. If you want to get any extra info from the invisible view, you can try delaying the transition like this :
- (void)animationFromModalView:(UIView *)modalView toMasterView:(UIView *)masterView
{
[masterView setNeedsLayout];
[masterView layoutIfNeeded];
[self performSelector:#selector(delayAnimationFromModalViewToMasterView) withObject:nil afterDelay:.1f];
}