जवाबों:
आप rootViewController
एक संक्रमण एनीमेशन ब्लॉक में स्विचिंग को लपेट सकते हैं :
[UIView transitionWithView:self.window
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{ self.window.rootViewController = newViewController; }
completion:nil];
newViewController.view.layoutIfNeeded()
एनीमेशन ब्लॉक से पहले कॉल करने से आलसी-लोडेड तत्वों के साथ समस्याएं ठीक हो जाती हैं।
मैंने यह पाया और पूरी तरह से काम करता है:
अपने appDelegate में:
- (void)changeRootViewController:(UIViewController*)viewController {
if (!self.window.rootViewController) {
self.window.rootViewController = viewController;
return;
}
UIView *snapShot = [self.window snapshotViewAfterScreenUpdates:YES];
[viewController.view addSubview:snapShot];
self.window.rootViewController = viewController;
[UIView animateWithDuration:0.5 animations:^{
snapShot.layer.opacity = 0;
snapShot.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5);
} completion:^(BOOL finished) {
[snapShot removeFromSuperview];
}];
}
आपके ऐप में
if (!app) { app = (AppDelegate *)[[UIApplication sharedApplication] delegate]; }
[app changeRootViewController:newViewController];
क्रेडिट:
मैं यीशु के उत्तर को तेजी से लागू कर रहा हूं। यह एक तर्क के रूप में व्यूकंट्रोलर के पहचानकर्ता को ले जाता है, स्टोरीबोर्ड से वांछित व्यूवॉन्ट्रोलर से लोड होता है और एनीमेशन के साथ रूटव्यूकंट्रोलर को बदलता है।
स्विफ्ट 3.0 अपडेट:
func changeRootViewController(with identifier:String!) {
let storyboard = self.window?.rootViewController?.storyboard
let desiredViewController = storyboard?.instantiateViewController(withIdentifier: identifier);
let snapshot:UIView = (self.window?.snapshotView(afterScreenUpdates: true))!
desiredViewController?.view.addSubview(snapshot);
self.window?.rootViewController = desiredViewController;
UIView.animate(withDuration: 0.3, animations: {() in
snapshot.layer.opacity = 0;
snapshot.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5);
}, completion: {
(value: Bool) in
snapshot.removeFromSuperview();
});
}
स्विफ्ट 2.2 अपडेट:
func changeRootViewControllerWithIdentifier(identifier:String!) {
let storyboard = self.window?.rootViewController?.storyboard
let desiredViewController = storyboard?.instantiateViewControllerWithIdentifier(identifier);
let snapshot:UIView = (self.window?.snapshotViewAfterScreenUpdates(true))!
desiredViewController?.view.addSubview(snapshot);
self.window?.rootViewController = desiredViewController;
UIView.animateWithDuration(0.3, animations: {() in
snapshot.layer.opacity = 0;
snapshot.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5);
}, completion: {
(value: Bool) in
snapshot.removeFromSuperview();
});
}
class func sharedAppDelegate() -> AppDelegate? {
return UIApplication.sharedApplication().delegate as? AppDelegate;
}
के बाद, आप कहीं से भी बहुत सरल उपयोग कर सकते हैं:
let appDelegate = AppDelegate.sharedAppDelegate()
appDelegate?.changeRootViewControllerWithIdentifier("YourViewControllerID")
स्विफ्ट 3.0 अपडेट
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.changeRootViewController(with: "listenViewController")
स्विफ्ट 2
UIView.transitionWithView(self.window!, duration: 0.5, options: UIViewAnimationOptions.TransitionFlipFromLeft, animations: {
self.window?.rootViewController = anyViewController
}, completion: nil)
स्विफ्ट 3, 4, 5
UIView.transition(with: self.window!, duration: 0.5, options: UIView.AnimationOptions.transitionFlipFromLeft, animations: {
self.window?.rootViewController = anyViewController
}, completion: nil)
बस यह कोशिश करो। मेरे लिए ठीक काम करता है।
BOOL oldState = [UIView areAnimationsEnabled];
[UIView setAnimationsEnabled:NO];
self.window.rootViewController = viewController;
[UIView transitionWithView:self.window duration:0.5 options:transition animations:^{
//
} completion:^(BOOL finished) {
[UIView setAnimationsEnabled:oldState];
}];
संपादित करें:
यह बेहतर है।
- (void)setRootViewController:(UIViewController *)viewController
withTransition:(UIViewAnimationOptions)transition
completion:(void (^)(BOOL finished))completion {
UIViewController *oldViewController = self.window.rootViewController;
[UIView transitionFromView:oldViewController.view
toView:viewController.view
duration:0.5f
options:(UIViewAnimationOptions)(transition|UIViewAnimationOptionAllowAnimatedContent|UIViewAnimationOptionLayoutSubviews)
completion:^(BOOL finished) {
self.window.rootViewController = viewController;
if (completion) {
completion(finished);
}
}];
}
UIViewAnimationOptionAllowAnimatedContent|UIViewAnimationOptionLayoutSubviews
, या पहले संस्करण, या किसी अन्य विधि का उपयोग करें।
आदेश में संक्रमण फ्लिप के साथ समस्या नहीं है बाद में अनुप्रयोग में पुराने दृश्य को भी स्टैक से साफ़ करने के लिए अच्छा है
UIViewController *oldController=self.window.rootViewController;
[UIView transitionWithView:self.window
duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{ self.window.rootViewController = nav; }
completion:^(BOOL finished) {
if(oldController!=nil)
[oldController.view removeFromSuperview];
}];
सही उत्तर है कि आपको rootViewController
अपनी खिड़की पर बदलने की आवश्यकता नहीं है । इसके बजाय, एक कस्टम बनाएं UIViewController
, इसे एक बार असाइन करें और इसे एक बार में एक चाइल्ड कंट्रोलर प्रदर्शित करें और ज़रूरत पड़ने पर एनीमेशन से बदल दें। आप एक प्रारंभिक बिंदु के रूप में कोड के निम्नलिखित टुकड़े का उपयोग कर सकते हैं:
स्विफ्ट 3.0
import Foundation
import UIKit
/// Displays a single child controller at a time.
/// Replaces the current child controller optionally with animation.
class FrameViewController: UIViewController {
private(set) var displayedViewController: UIViewController?
func display(_ viewController: UIViewController, animated: Bool = false) {
addChildViewController(viewController)
let oldViewController = displayedViewController
view.addSubview(viewController.view)
viewController.view.layoutIfNeeded()
let finishDisplay: (Bool) -> Void = {
[weak self] finished in
if !finished { return }
oldViewController?.view.removeFromSuperview()
oldViewController?.removeFromParentViewController()
viewController.didMove(toParentViewController: self)
}
if (animated) {
viewController.view.alpha = 0
UIView.animate(
withDuration: 0.5,
animations: { viewController.view.alpha = 1; oldViewController?.view.alpha = 0 },
completion: finishDisplay
)
}
else {
finishDisplay(true)
}
displayedViewController = viewController
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return displayedViewController?.preferredStatusBarStyle ?? .default
}
}
और जिस तरह से आप इसका उपयोग करते हैं वह है:
...
let rootController = FrameViewController()
rootController.display(UINavigationController(rootViewController: MyController()))
window.rootViewController = rootController
window.makeKeyAndVisible()
...
ऊपर दिए गए उदाहरण से पता चलता है कि आप UINavigationController
अंदर घोंसला बना सकते हैं FrameViewController
और यह ठीक काम करता है। यह दृष्टिकोण आपको उच्च स्तर का अनुकूलन और नियंत्रण प्रदान करता है। बस FrameViewController.display(_)
किसी भी समय कॉल करें आप रूट कंट्रोलर को अपनी विंडो पर बदलना चाहेंगे, और यह आपके लिए वह काम करेगा।
यह स्विफ्ट 3 के लिए एक अपडेट है, यह विधि आपके ऐप के प्रतिनिधि में होनी चाहिए, और आप इसे किसी भी दृश्य नियंत्रक से, ऐप प्रतिनिधि के साझा उदाहरण के माध्यम से कहते हैं
func logOutAnimation() {
let storyBoard = UIStoryboard.init(name: "SignIn", bundle: nil)
let viewController = storyBoard.instantiateViewController(withIdentifier: "signInVC")
UIView.transition(with: self.window!, duration: 0.5, options: UIViewAnimationOptions.transitionFlipFromLeft, animations: {
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()
}, completion: nil)
}
जो भाग ऊपर विभिन्न प्रश्नों से गायब है, वह है
self.window?.makeKeyAndVisible()
आशा है कि यह किसी की मदद करता है।
AppDelegate.h में:
#define ApplicationDelegate ((AppDelegate *)[UIApplication sharedApplication].delegate)]
आपके नियंत्रक में:
[UIView transitionWithView:self.window
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
ApplicationDelegate.window.rootViewController = newViewController;
}
completion:nil];
मैं अपने तरीके का प्रस्ताव करता हूं जो यह मेरी परियोजना में ठीक काम कर रहा है, और यह मुझे अच्छे एनिमेशन प्रदान करता है। मैंने इस पोस्ट में पाए गए अन्य प्रस्तावों का परीक्षण किया है, लेकिन उनमें से कुछ उम्मीद के मुताबिक काम नहीं करते हैं।
- (void)transitionToViewController:(UIViewController *)viewController withTransition:(UIViewAnimationOptions)transition completion:(void (^)(BOOL finished))completion {
// Reset new RootViewController to be sure that it have not presented any controllers
[viewController dismissViewControllerAnimated:NO completion:nil];
[UIView transitionWithView:self.window
duration:0.5f
options:transition
animations:^{
for (UIView *view in self.window.subviews) {
[view removeFromSuperview];
}
[self.window addSubview:viewController.view];
self.window.rootViewController = viewController;
} completion:completion];
}
अच्छा मीठा एनीमेशन (स्विफ्ट 4.x के साथ परीक्षण):
extension AppDelegate {
public func present(viewController: UIViewController) {
guard let window = window else { return }
UIView.transition(with: window, duration: 0.5, options: .transitionFlipFromLeft, animations: {
window.rootViewController = viewController
}, completion: nil)
}
}
के साथ बुलाना
guard let delegate = UIApplication.shared.delegate as? AppDelegate else { return }
delegate.present(viewController: UIViewController())