Is it possible to set a property application-wide to double the speed of transitions within an iOS app?
Application-wide?
Try setting the speed property on the backing layer for your view controllers' content views. speed=2 would be double-speed. You could probably set this in the viewDidLoad method for all your view controllers.
You might also be able to create a custom subclass of UIWindow, and have that window object set the speed property on it's view layer to 2.0 in a bottleneck method like makeKeyWindow. You'd need to make all your app's UIWindow objects use your custom class. I'd have to do some digging to figure out how to do that.
##Edit:
Or, better idea, set self.window.layer.speed = 2.0 in your app delegate after creating the window, as suggested by #Costique in the comment below.
Note that this approach will speed up ALL animations, not just transitions and segues. If you only want to speed up segues you would have to figure out how to target just those animations. I'd have to think about that.
Apple does not have a simple way to change that since it would make transitions too heterogenous amongst different apps. You could double the layer's speed, but that would mess up the timing on the rest of your animations. The best way is to implement your own transition using a category on UIViewControler.
UIViewController+ShowModalFromView.h
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
#interface UIViewController (ShowModalFromView)
- (void)presentModalViewController:(UIViewController *)modalViewController fromView:(UIView *)view;
#end
UIViewController+ShowModalFromView.m
#import "UIViewController+ShowModalFromView.h"
#implementation UIViewController (ShowModalFromView)
- (void)presentModalViewController:(UIViewController *)modalViewController fromView:(UIView *)view {
modalViewController.modalPresentationStyle = UIModalPresentationFormSheet;
// Add the modal viewController but don't animate it. We will handle the animation manually
[self presentModalViewController:modalViewController animated:NO];
// Remove the shadow. It causes weird artifacts while animating the view.
CGColorRef originalShadowColor = modalViewController.view.superview.layer.shadowColor;
modalViewController.view.superview.layer.shadowColor = [[UIColor clearColor] CGColor];
// Save the original size of the viewController's view
CGRect originalFrame = modalViewController.view.superview.frame;
// Set the frame to the one of the view we want to animate from
modalViewController.view.superview.frame = view.frame;
// Begin animation
[UIView animateWithDuration:1.0f
animations:^{
// Set the original frame back
modalViewController.view.superview.frame = originalFrame;
}
completion:^(BOOL finished) {
// Set the original shadow color back after the animation has finished
modalViewController.view.superview.layer.shadowColor = originalShadowColor;
}];
}
#end
This can easily be changed to use whatever animated transition you want. Hope this helps!
Related
Simple question about inheritance
I have a standard program with a master view:
MasterViewController.h
enter code here#interface MasterViewController : UIViewController
using a subview for drawing:
MasterViewController.m
frame = CGRectMake(xo, yo, side*width, side*height); // maxSide
backView = [[BackView alloc] initWithFrame:frame];
[backView setBackgroundColor:[UIColor whiteColor]];
[self infoToBackView];
[self.view addSubview:backView];
BackView.h
#interface BackView : UIView
and BackView.m has its drawRect:
- (void)drawRect {
:
:
}
The problem I have is that I want BackView to inherit from MasterViewController, i.e. I want
Backview.h to be
#interface BackView : MasterViewController
which allows it to inherit the variables it needs from MasterViewController.
The problem is that this does not work; BackView must inherit from UIView to be able to draw with DrawRect. Therefore, before calling the UIView BackView, I must send it the variables it needs for drawing:
[self infoToBackView];
[backView setNeedsDisplay];
where infoToBackView is a method sending the needed variables to BackView.
The $64,000 question: How can I have a BackView that inherits from MasterViewController AND has drawRect?
BackView is a View, it is design to DRAW something.
ViewController are design to manage a view Herarchy.
They are not the same things. One is a plane, the other is an aiport! You cannot fly an airport...
UIView's subclass are design to draw. If you want to draw (text, shapes..) on screen, create a subclass of UIView. If you want to manage a scene in your app storyboard, create a subclass of UIViewController.
drawRect: is a method of UIView
Now you can pass variable to your view from your viewController, like a label (another kind of View) received a text to know what to display.
For example in your ViewController, you can have:
self.myBackView.color = [UIColor blueColor];
self.myBackView.progress = .5;
self.myBackView.text = #"MVC is awesome";
For a better understanding of the MVC design pattern, please reffer to Apple doc : https://developer.apple.com/library/mac/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html
Newbie here,
With this code in the .m file I aimed to animate an UIImageView to the right
#interface ViewController ()
#property (strong, nonatomic) IBOutlet UIImageView *myImageView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
self.myImageView.center = CGPointMake(self.myImageView.center.x + 100, self.myImageView.center.y);
}
completion:^(BOOL finished){
}];
}
But what actually happens is that the image view shifts 100 points to the left and then animates to the right by 100 points back to its original position. I don't know why this happens. How can I achieve an animation that moves directly to the right?
Note: I'm not sure if this has to do with anything, but I added constraints in the interface builder to center this UIImageView in the middle.
Create IBOutlets for the constraints you want change. Just like you would for any other UIKit element. Then in your code instead of doing:
self.myImageView.center = CGPointMake(self.myImageView.center.x + 100, self.myImageView.center.y);
Do something like this:
self.imageViewTralingSpaceConstraint.constant = 100; //Or whatever value makes sense
Then in your animateWithDuration block add [self.view layoutSubViews];
you probably want to put this code in your viewDidAppear method rather than your viewDidLoad. this would make the animation happen after the view appears rather than before it. the viewDidLoad method is called after the view hierarchy is loaded into memory but not neccessarily after it is all laid out.
here is a link to the uiviewcontroller reference. https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/
check out these two methods there. if you continue doing iOS development you will get to know these methods really well.
I am making a game using spritekit and everything works perfectly except when I add the code to add an iAd. When I add the iAd everything works but it seems that the iAd is resizing the scene when it is being displayed.
This is my code to display the iAd, it is in the ViewController.m :
#import <iAd/iAd.h>
#import "ViewController.h"
#import "MainMenu.h"
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Configure the view.
SKView * skView = (SKView *)self.originalContentView;
skView.showsFPS = YES;
// Create and configure the scene.
SKScene * scene = [MainMenu sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
self.canDisplayBannerAds = YES;
// Present the scene.
[skView presentScene:scene];
}
Like I say, the iAd shows up, and all the function properly but the when the iAd is displayed it makes the scene smaller, is there a method or something that allows the scenes to not be resized?
An help is much appreciated, thanks!
Ok so I sort of figured it out, I was using scaleMode of SKSceneScaleModeAspectFit I have now changed it to SKSceneScaleModeFill this seems to make the scene shorter but it is not as noticeable as the aspectFit scale mode. I have also noticed that the iAd does not act like a sprite as it actually distorts or resizes the screen. If anyone knows how to create the iAd on top of the view, like sprite, please add a comment or solution.
EDIT
I have just figured out that one can add an ADBannerView to the viewcontroller in the interface builder, this will show the ad on all scenes. I am now trying to figure out how this can be set to not display on specific scenes seeing spritekit only uses one viewcontroller.
If you add the ad by adding in the AdBannerView then you have to create seperate methods in the view controller to turn the ads on or off, by creating these seperate methods it allows one to have manual control over the ads in the view controller from any scene.
In the view controller you have a scene that you create, this scene variable/object has a property of tag or userdata. So if your game goes to a different scene you can call
[super scene] setTag:x]
Every time that the NSTimer calls my control method it checks the value of the scenes tag in the view controller and based on that value it will remove or re-display the ad.
Just a thought, but you could also put the AdBannerView in via the Storyboard editor, and then set
self.canDisplayBannerAds = NO;
That way it will just overlay the SKScene instead of shrinking it.
Hope this helps!
There is another way to fix this problem. You might want to have a look at this Thread.
iAd in Spritekit
Just a sneak preview:
adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
adView.delegate = self;
[adView setFrame:CGRectMake(0, 0, 1024, 768)]; // set to your screen dimensions
[adView setBackgroundColor:[UIColor clearColor]];
[self.view addSubview:adView];
According to my project, I changed the default view that tied to one UIViewController from UIView to UIScrollView as it has to be changed its offset and content size. The way I change from UIView to UIScrollView was by Interface Builder > Custom Class
If I want to change its offset and content size programmatically within The Controller, It can't be done in usual way unless I cast it
[((UIScrollView *)self.view) setContentSize:CGSizeMake(1024, 2000)];
[((UIScrollView *)self.view) setContentOffset:CGPointMake(0, 150)];
But with other UIScrollView within the app, changing their offset and content size can be done like any other,
// Assume that sv is scroll view object
[sv setContentSize:CGSizeMake(1027, 2000)];
[sv setContentOffset:CGPointMake(0, 150)];
When I print that scroll view object, it shown as a UIScrollView
NSLog(#"%#", self.view);
NSLog(#"%#", [self.view class]);
-> <UIScrollView: 0x6d3d3f0; frame = (0 0; 1024 768); autoresize = RM+BM; layer = <CALayer: 0x6d52ce0>; contentOffset: {0, 0}>
-> UIScrollView
Anyone know what I did missing or forgot to do rather than change the view's custom class?
Best and Thank you,
Tar
P.S. Besides the extra code needed, everything works fine. But, I can't take the chance of possible bug in the future. This client is super crazy, no error will be accepted
An alternative to this (that would avoid the need for casting) would be to set the UIViewController custom class back to UIView in interface builder. Then, insert a new UIScrollView as a subview (simply drag and drop in Interface Builder), connecting the UIScrollView to the UIViewController subclass via an IBOutlet that looks something like:
#property (nonatomic, weak) IBOutlet UIScrollView *scrollView;
(When you connect the outlet that property declaration should be generated for you by XCode).
Then, in your UIViewController subclass, you can do something like:
[[self scrollView] setContentSize:CGSizeMake(1024, 2000)];
[[self scrollView] setContentOffset:CGPointMake(0, 150)];
I'm not sure what the best solution is but a quick workaround is to create a method that casts the view in the UIViewController. That is:
- (UIScrollView *)scrollView {
return (UIScrollView *)self.view;
}
Then, instead of referring to the view in the ViewController as self.view, refer to it as self.scrollView.
I'm still very new to iOS developing. In fact, if there is a super noob, I would be one :p. Currently I am working on creating an IBAction button that accesses a subview. I have 2 ViewControllers, AddClientVC and NewClientVC, both with .nib files. So basically, inside my AddClientVC I implement an IBAction button with the following code:
- (IBAction)buttonPressed:(id)sender
{
UIView *transparentBG = [[UIView alloc] initWithFrame:CGRectMake(-5, -5, 1500, 2500)];
transparentBG.backgroundColor = [UIColor blackColor];
transparentBG.opaque = NO;
transparentBG.alpha = 0.5;
[self.view addSubview:transparentBG];
transparentBG.center = transparentBG.center;
vc = [[NewClientVC alloc] initWithNibName:#"NewClientVC" bundle:nil];
[self.view addSubview:vc.view];
vc.view.center = self.view.center;
}
As you can see I implemented a UIView as a transparent background. Basically AddClientVC --> Transparent Background --> NewClientVC. Now I have created another IBAction button but this time inside NewClientVC as a function to dismiss the accessed subview which looks like this:
- (IBAction)saveDismiss:(id)sender
{
[self.view removeFromSuperview];
}
The problem I'm having right now is when I click the saveDismiss button it only removes the subview that I called previously on AddClientVC but it didn't remove the transparent background I have created as a UIView. So the problem is how do I implement an action which simultaneously removes my subview and the UIView transparent background I created.
I need all the help I can get :)
I'm not too sure I fully understand what you want to happen, but maybe you could try something like this?
- (IBAction)saveDismiss:(id)sender
{
[vc removeFromSuperView];
[self.view removeFromSuperview];
}
I recommend not to manage your screens by adding subviews manually but instead use
- (void)presentModalViewController: (UIViewController *)modalViewController
animated: (BOOL)animated
method on your root viewController.
Or better instantiate a UINavigationController and use push and pop methods to drill down/up your views.
See apple reference here
Do not worry about code execution speed and stay confident in apple's SDK. UIKit is optimized for best user experience. Trying to boost your code by doing inappropriate SDK use is, in my opinion, a risky strategy. ;) – Vincent Zgueb
Sorry Vincent but I don't agree with you. I reached here because I want to implement an gesture that adds a sub-view for my view, which will be the navigation of my app.
[self.view addSubview:ctrl.view];
is faster presenting the view than
[self.navigationController presentModalViewController:ctrl animated:NO]
and by the way, the solution to the topic in my case was:
[self.view sendSubviewToBack:ctrl.view];