Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I currently have the following function, once clicked, it takes the user to the ‘homeViewController’
func transitionToHome() {
let homeViewController = storyboard?.instantiateViewController(identifier: Constants.Storyboard.homeViewController) as? HomeViewController
view.window?.rootViewController = homeViewController
view.window?.makeKeyAndVisible()
}
However, I am looking to use this function when a user logs out to take them to the ‘UIViewController’, however whenever I use UIViewController instead of homeViewController in the above code, it produces the following error.
Type 'Constants.Storyboard' has no member 'UIViewController'
What do I need to do in order to make this work and take the user to the very first viewcontroller for the app?
Here’s the view of the view controller I am trying to redirect the user to.
You need to change the Class value from ViewController to HomeViewController, as well as the Storyboard ID to HomeViewController for the initialisation to work.
Custom Class
Class HomeViewController
Identity
Storyboard ID HomeViewController
Then can instantiate the view controller like this:
func transitionToHome() {
let homeViewController = storyboard?.instantiateViewController(identifier: "HomeViewController") as? HomeViewController
view.window?.rootViewController = homeViewController
view.window?.makeKeyAndVisible()
}
Related
I'm trying to build a step by step questionnaire app with a View Controller called QuestionController whose content is dynamically populated via some globals in a constants file. When a user is done answering a question, I want to be able to be able to push another QuestionController for the next question.
#IBAction func goNext(_ sender: UIButton) {
let controller = QuestionController()
navigationController?.pushViewController(controller, animated: true)
}
As you can see, that is exactly as I have done but for whatever reason I'm getting a SIBABRT error. Any ideas why this might be? I don't have any lingering outlets and the only action is the next button callback you see here.
Instead of this
let controller = QuestionController()
load it like this with it's identifer in IB
let controller = storyboard.instantiateViewController(withIdentifier: "identifer") as! QuestionController
In case I have 4 items in Tabar.
When open app, default is in TabBarItem[0] - ViewControllerRoot
I push from ViewControllerRoot into ViewController A. From ViewController A, I switch to TabBarItem[3] - contain ViewController B.
The question is: How can I get name of ViewController A when I switch to TabBarItem[3]?
Thank you so much.
You can get your current viewcontroller using selectedViewController.
User delegate method of tabbar.
func tabBarController(_ tabBarController :UITabBarController, shouldSelect: UIViewController){
let currentVC = tabBarController.selectedViewController
let destinationVC = shouldSelect
}
I hope this will work for you.
When you change the view from UITabBar there is a delegate method that is invoked
tabBarController:animationControllerForTransitionFromViewController:toViewController:
This will help you to find the previous selected controller.
Your question is a bit unclear..please share some code.
if you wish to get an the instance of ViewController A:
window.rootViewController?.childViewControllers[0]
if you wish to get the class name of ViewController A:
a = window.rootViewController?.childViewControllers[0]
var className: String = a.self
I am new developer and I am struggling with my Walkthrough screen for my application.
I have created it, but when I click continue to my main screen, the app crashes.
Here is the code I have under my "continue" button:
#IBAction func skipButtonTapped(_ sender: AnyObject) {
let nextView: FirstViewController = self.storyboard?.instantiateViewController(withIdentifier: "FirstViewController") as! FirstViewController
let appdelegate = UIApplication.shared.delegate as! AppDelegate
appdelegate.window!.rootViewController = nextView
}
and the error I get is :
Could not cast value of type 'UITabBarController' (0x19f33c0d8) to 'Iwin.FirstViewController' (0x100057220).
I think the Problem is in the name of the name of the identifier which in my case is "FirstViewController"
This is the storyboard ID of my TabBarController, which should be the first screen of my app.
Attached I have uploaded a picture too.
The error you are seeing probably has to do with the forced conversion (as!) you do on the first line of the function. You're doing the following:
Calling instantiateViewController(withIdentifier:), which Apple API Documentation says returns UIViewController (in this case, it's returning UITabBarController, a subclass)
Force converting a UITabBarController to a FirstViewController, which fails.
This is because forced conversion guarantees that the resulting value won't be nil, but it doesn't guarantee that it won't fail (crash). UITabBarController is simply not convertible, because it does not extend/implement FirstViewController.
My guess is that even though you've given that view controller the identifier "FirstViewController", but it's just a regular old UITabBarController. Double check in Interface Builder that this View Controller is actually an instance of your FirstViewController class.
Looking at your photo, the "Class" field has the default value of UITabBarController -- this should be the first thing you try to change. Fill in FirstViewController, and let me know if it works.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I've build a second view controller for a radio app to send text's to the radiostation. So, when i press play on the first view controller it play's the stream and you can check what's playing now and coming up. I've made a button to the second view controller, the music is still playing, that's good! But i can't stop it in ControlCenter and when i go back to the first view controller the button is back to "Play" and not "Stop" in the app.
Seems like the first view controller is getting a "reset?" when you go to the second view controller. How can i fix this?
Image: http://imgur.com/wZtAyz6
Dennis
You can also declare your audioPlayer in the appDelegate :
// inside AppDelegate
var ap : AVAudioPlayer? = nil
then simply declare in your viewController :
var ap : AVAudioPlayer? {
get {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
return appDelegate.ap
}
set {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.ap = newValue
}
}
I think this is a beginner question. I currently have two view controllers:
class MainViewController: UIViewController {
var markersToDelete = Marker()
func deleteMarkers() {}
}
class MapViewController: UIViewController {
var markersToDelete = Marker()
func deleteMarkers() {}
}
The MapViewController is instantiated with a modal segue in the storyboard. I know that I can access MainViewController in AppDelegate.swift with this code:
var mainViewController = self.window!.rootViewController as! MainViewController
How can I do the same thing with MapViewController?
EDIT
Based on the comments below I am updating this to include more detail. Here is what I am trying to accomplish:
I have IBActions in both view controllers that appends Marker items to the
markersToDelete array. The method deleteMarkers is used to find the corresponding items in the Core Data persistent store and delete them; it is called by AppDelegate when applicationDidEnterBackground or when applicationWillTerminate.
This is the reason why I want to access both view controllers from app delegate. I am starting to think there could be a better way to do this.
Some other answers suggest ways of insantiating the controller, but they seem incorrect since you mentioned the controller is instantiated through a segue. There is no straight forward way of doing what you want, and for a good reason, it should be hard to access things from unrelated code. In your very simple example, this code would work, given the controllers have already been presented:
var mainViewController = self.window!.rootViewController as! MainViewController
let mapViewController = mainViewController.presentedViewController
But I would strongly discourage this type of code inside AppDelegate, it makes a lot of assumptions and will break easily if your navigation structure changes. Be more specific about what you're trying to achieve and you may get answers that lead you to a better architecture.
EDIT
Given the new information provided by the asker, this is a proposed solution to the more specific problem:
I understand you have Marker objects in your Core Data context, and you wish to batch delete some of them. What about adding a bool property to Marker class, and setting it to true for the objects you wish to delete. Then, in AppDelegate, you fetch the markers which have that property set to true, and delete them. This way you don't need to mantain an array, and there is no coupling between classes.
You can access your map controller by calling it's storyboard ID, which you'll need to set in Storyboard. Then just do:
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
var mapViewController = storyboard. instantiateViewControllerWithIdentifier("storyboardID") as! MapViewController
You need to set storyboard ID to your mapViewController. Then You can access it from appDelegate.
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main",bundle: nil)
var destViewController : UIViewController
destViewController = mainStoryboard.instantiateViewControllerWithIdentifier("YourViewController") as! UIViewController
You should start by encapsulating your code which is responsible for interaction with CoreData framework API.
Create a singleton class like below and use this class only for insertion/deletion/update operations. This way will ensure loose coupling among your view controllers .
You can get reference to the sharedInstance of DataManager in any class. . Using sharedInstance you can call methods related to your Database operations.
class DataManager {
class var sharedInstance : DataManager {
struct Singleton {
static let instance = DataManager()
}
return Singleton.instance
}
func deleteMarkers() {
//Your logic here
}
}