Back to root view controller in swift
You can just set a new RootController like this:
let storyboard = UIStoryboard(name: "sName", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "<YOUR ROOT CONTROLLER>")
self.window?.rootViewController = viewController
If you don't have a window at self.window
you need to instanciate one based on your AppDelegate.
If you're within a NavigationController
you can also use the answer of @Anshul Bhatheja
How to return to Root View Controller
You need to dismiss presented model then you can pop all the pushed view controllers. As presented model would not be in the stack of the navigation.
self.dismissViewControllerAnimated(true, completion: {});
Then you can pop to base view controller.
self.navigationController.popViewControllerAnimated(true);
How to move back to the root view controller in storyboard?
I got the resolution to the issues using the "Unwind Segues".
Step 1) The bare minimum you need is to subclass the view controller for your destination view (aka, a view that has popped up previously in navigation and you want to unwind to it) and add a method like this to it (the method name can be anything you want, but it should be unique because all unwind segues in your entire app are listed together):
- (IBAction)unwindToViewControllerNameHere:(UIStoryboardSegue *)segue {
//nothing goes here
}
Step 2) Now, in your source view (aka, the view that you want to unwind from) you simply drag a segue from your button or whatever down to the little green "EXIT" icon at the bottom of your source view. There should now be an option to connect to "- unwindToViewControllerNameHere"
That's it, your segue will unwind when your button is tapped. And we can move to any view controller we want and rest of the view controllers will be released.
Navigate to root view-controller from modally presented view controller
You can write following inside C
let presenting = self.presentingViewController ?? self.navigationController?.presentingViewController
let navCtrl1 = presenting as? UINavigationController // in case you presented C using b.navigationController.present...
let navCtrl2 = presenting?.navigationController // in case you presented c using b.present...
if let navCtrl = navCtrl1 ?? navCtrl2 {
self.dismiss(animated: true, completion: {
navCtrl.popToRootViewController(animated: true)
})
}
UPDATE
I would like to know if is there anyway to bypass the dismiss and direct pop to root view controller. I want to avoid showing View-controller B
let presenting = self.presentingViewController ?? self.navigationController?.presentingViewController
let navCtrl1 = presenting as? UINavigationController // in case you presented C using b.navigationController.present...
let navCtrl2 = presenting?.navigationController // in case you presented c using b.present...
if let navCtrl = navCtrl1 ?? navCtrl2 {
navCtrl.popToRootViewController(animated: false)
self.dismiss(animated: true, completion: nil)
}
How to pop back to root view controller but then push to a different view?
An easy way to accomplish what you want to do is to build some simple logic into your main root view controllers -(void)viewWillAppear method and use a delegate callback to flip the logic switch. basically a "back reference" to the root controller. here is a quick example.
main root controller (consider this controller a) - well call it controllerA
set a property to keep track of the jump status
@property (nonatomic) BOOL jumpNeeded;
setup some logic in
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.jumpNeeded ? NSLog(@"jump needed") : NSLog(@"no jump needed");
if (self.jumpNeeded) {
NSLog(@"jumping");
self.jumpNeeded = NO;
[self performSegueWithIdentifier:@"controllerC" sender:self];
}
}
Now, in your main root controller,when a tableview row is selected do something like this
when pushing to controllerB in your tableView did select method
[self performSegueWithIdentifer@"controllerB" sender:self];
then implement your prepare for segue method
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
//setup controller B
if([segue.identifier isEqualTo:@"controllerB"]){
ControllerB *b = segue.destinationViewController;
b.delegate = self; //note this is the back reference
}
//implement controller c here if needed
}
Now move on to controllerB
you need to set a property called "delegate" to hold the back reference
and you need to import the header file from the root controller
#import "controllerA"
@property (nonatomic,weak) controllerA *delegate;
then just before you pop back to controllerA, you set the flag
self.delegate.jumpNeeded = YES;
[self.navigationController popViewControllerAnimated:YES];
and that is about it. You don't have to do anything with controllerC. There are a few other ways to do, but this is pretty straight forward for your needs. hope it works out for you.
How to go back to RootViewController from presentView controller?
I found solution for my question is :
@IBAction func btnTrash(sender: AnyObject) {
let alert = UIAlertController(title: "Delete Image", message: "Are You Sure To delete this Image?", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "Yes", style: .Default, handler: {(alertAction)in
//Delete Photo
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
let request = PHAssetCollectionChangeRequest(forAssetCollection: self.assetCollection)
request.removeAssets([self.photosAsset[self.index]])
}, completionHandler: {(success, error )in
NSLog("\nDeleted Image -> %@", (success ? "Success" : "Error"))
alert.dismissViewControllerAnimated(true, completion: nil)
// here is the code for go back to root view controller
if(success){
// Move to the main thread to execute
dispatch_async(dispatch_get_main_queue(), {
self.photosAsset = PHAsset.fetchAssetsInAssetCollection(self.assetCollection, options: nil)
if(self.photosAsset.count == 0){
println("No Images Left!!")
self.navigationController?.popToRootViewControllerAnimated(true)
}else{
if(self.index >= self.photosAsset.count){
self.index = self.photosAsset.count - 1
}
self.displayPhoto()
}
})
}else{
println("Error: \(error)")
}
})
}))
alert.addAction(UIAlertAction(title: "Cancle", style: .Cancel, handler: {(alertAction)in
//Do not delete Photo
self.dismissViewControllerAnimated(true, completion: nil)
}))
self.presentViewController(alert, animated: true, completion: nil)
}
How to go back to the initial ViewController the right way?
It doesn't move to another view controller, because you are setting a simple view controller in your rootViewController.
What you need is:
let initialViewController = self.storyboard!.instantiateViewController(withIdentifier: "Initial")
let navController = UINavigationController.init(rootViewController: initialViewController)
UIApplication.shared.keyWindow?.rootViewController?.present(navController, animated: true, completion: nil)
This will create a navigationviewcontroller, so when on "Initial" you should be able to perform push, present actions of another view controllers.
Related Topics
Dyld: Library Not Loaded: @Rpath/Mydsk.Framework/Mydsk -> Swift iOS 8.0
Completely Unrelated Error Using Coredata
Xcode 9.3 - Nspredicate Bool Crash
Mapbox Navigation Pod Unable to Install with Objectivec Where I am Using Xcode 9.2
Uibezierpath Subclass Initializer
Swift/iOS Refreshing App Data When in Background
How to Make Async/Await in Swift
Change Uipopoverview Background + Arrow Color
Extending a Delegate from a Base Class
How to Draw a Just the Corners of a Rectangle (Without Lines Connecting Them)
Draw Button on Top of Avplayer
Firebase: Provided Bucket Does Not Match the Storage Bucket of the Current Instance in Swift
How to Convert Duration Form Youtube API in Swift
Uitableviewcell with Intrinsic Height Based on Width
Viewing Os_Log Messages in Device Console
Advise Where to Store Data for iOS App
Swift 4: Timer Crashing - Unrecognized Selector Sent to Instance