Reputation: 2893
I was wondering if there is a way to have an enum and assign it different values from different classes for instance, I have 3 classes that instantiate a View Controller and I always start them like this
let placeAreaC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PlaceAreaC") as! PlaceAreaC
let notificationC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "NotificationC") as! NotificationC
let reportC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ReportC") as! ReportC
Each time I want to go to a new controller I have to do that, I was wondering if I can create an enum that can hold those values, right now I have this code
class ControllerEnum: NSObject {
enum InstantiateEnum: String {
case Report = "Report" // UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ReportC") as! ReportC
case Notification = "Notification" // UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "NotificationC") as! NotificationC
case PlaceArea = "PlaceArea" // UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ReportC") as! ReportC
}
}
I know the type is String but I am wondering how can I make it so that the type accepts those 3 different classes above ? So that then I can reference them doing something like
InstantiateEnum.Notification
That would be very useful because now I can change those values in just 1 place . Any suggestions would be great .
Upvotes: 0
Views: 2650
Reputation: 16426
You can have property that return ViewController in your enum
enum InstantiateEnum: String {
case Report = "Report" // UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ReportC") as! ReportC
case Notification = "Notification" // UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "NotificationC") as! NotificationC
case PlaceArea = "PlaceArea" // UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ReportC") as! ReportC
var viewController:UIViewController {
switch self {
case Report :
return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: self.rawValue)
...
}
}
}
OR
You can have one class Method in each of your View Controller return self object
like
class func viewController() -> ReportC {
return StoryBoard.main.instantiateViewController(withIdentifier: StoryBoard.controller.ReportC) as! ReportC
}
And create Constants of Your Identifier
struct StoryBoard {
static let main = UIStoryboard.init(name: "Main", bundle: nil)
static let otherStoryboard = UIStoryboard.init(name: "otherStoryboard", bundle: nil)
struct controller {
static let ReportC = "Report"
}
}
Upvotes: 1
Reputation: 2652
There is better way that I used:
Step 1: Just Copy this enum with extensions. And change the storyboards name with those you have in your project
enum AppStoryboard : String {
case Main
case Notification
case Profile
case Login
}
extension AppStoryboard {
var instance : UIStoryboard {
return UIStoryboard(name: self.rawValue, bundle: Bundle.main)
}
func viewController<T : UIViewController>(viewControllerClass : T.Type, function : String = #function, line : Int = #line, file : String = #file) -> T {
let storyboardID = (viewControllerClass as UIViewController.Type).storyboardID
guard let scene = instance.instantiateViewController(withIdentifier: storyboardID) as? T else {
fatalError("ViewController with identifier \(storyboardID), not found in \(self.rawValue) Storyboard.\nFile : \(file) \nLine Number : \(line) \nFunction : \(function)")
}
return scene
}
func initialViewController() -> UIViewController? {
return instance.instantiateInitialViewController()
}
}
extension UIViewController {
// Not using static as it wont be possible to override to provide custom storyboardID then
class var storyboardID : String {
return "\(self)"
}
static func instantiate(fromAppStoryboard appStoryboard: AppStoryboard) -> Self {
return appStoryboard.viewController(viewControllerClass: self)
} }
Step 2: Assign the storyboard id same as the class name of the view controller in storyboard.
Step 3: Now create the object of the viewcontroller like:
let notificationVC = NotificationVC.instantiate(fromAppStoryboard: .Notification)
/* Syntax:
let <yourObject> = <YourViewController's class name>.instantiate(fromAppStoryboard: <respected storyboard>) */
notificationVC
will be the objet of type NotificationVC
Now play with your object. :)
Upvotes: 0