I think you're on the right track as far as mindset here. Whenever we're using strings, there's always the possibility of a typo, and that can be a real pain when it comes to random bugs you don't expect! So, great thinking on this one.
I think this would be a fantastic introduction to a practical use of Swift protocols. If you're unfamiliar, Swift protocols are like little rule books that any conforming type can obey. We can start with a simple protocol that can be expanded upon to add flexibility later.
Try this:
1.) Create a new Swift file and name it StoryboardIdentifiable.swift
2.) Copy and paste this into that file:
import Foundation
import UIKit
protocol StoryboardIdentifiable where Self: UIViewController {
static var storyboard: UIStoryboard { get }
static var viewController: UIViewController? { get }
}
extension StoryboardIdentifiable {
static var storyboard: UIStoryboard {
return UIStoryboard(name: "Main", bundle: nil)
}
static var viewController: UIViewController? {
return Self.storyboard.instantiateViewController(withIdentifier: NSStringFromClass(self))
}
}
What does this do? This sets some rules for what it means to beStoryboardIdentifiable. Any conforming class must obey these rules. Note the where Self: UIViewController portion. This says that only view controllers can conform to this protocol.
There are two "rules":
1.) Conforming classes must provided a UIStoryboard instance (the storyboard the controller lives inside)
2.) They must also provide a UIViewController? instance.
So what about the extension ? Well, this gives you built-in default behavior for any type conforming to StoryboardIdentifiable. This way you don't have to implement the two vars from the protocol yourself everywhere! Notice the viewController instance in the extension is using NSStringFromClass(self) This is because the name of the file, and the identifier of the view controller in the storyboard are typically made to be the same exact string. So all we have to do is...keep doing that.
Now, you can do this for example:
Instead of doing this:
(In HomeViewController.swift)
And you can delete this line from your StringsManager file
static let loginViewController = homeStoryBoard.instantiateViewController(withIdentifier: "LoginViewController") as? UIViewController
One last thing to note about NSStringFromClass in the extension, is this will prefix the class name with the module name, so you'll need to make sure you do the same when you implement this protocol. So, in your storyboard, change your LoginViewController storyboard identifier to Vegetarian_Food_Finder.LoginViewController
Then the last thing you have to do is conform LoginViewController to StoryboardIdentifier:
class LoginViewController: UIViewController, StoryboardIdentifiable {
You can repeat this process with Home/Search/SignUp view controllers as well.
https://github.com/Abdulla2022/Vegetarian-Food-Finder-/blob/66b99fc4c799f14952b17c78cbdcf4f2aa9632c7/Vegetarian-Food-Finder/StringsManger.swift#L15
I think you're on the right track as far as mindset here. Whenever we're using strings, there's always the possibility of a typo, and that can be a real pain when it comes to random bugs you don't expect! So, great thinking on this one.
I think this would be a fantastic introduction to a practical use of Swift protocols. If you're unfamiliar, Swift protocols are like little rule books that any conforming type can obey. We can start with a simple protocol that can be expanded upon to add flexibility later.
Try this: 1.) Create a new Swift file and name it
StoryboardIdentifiable.swift
2.) Copy and paste this into that file:What does this do? This sets some rules for what it means to be
StoryboardIdentifiable
. Any conforming class must obey these rules. Note thewhere Self: UIViewController
portion. This says that only view controllers can conform to this protocol.There are two "rules": 1.) Conforming classes must provided a
UIStoryboard
instance (the storyboard the controller lives inside) 2.) They must also provide aUIViewController?
instance.So what about the
extension
? Well, this gives you built-in default behavior for any type conforming toStoryboardIdentifiable
. This way you don't have to implement the two vars from the protocol yourself everywhere! Notice the viewController instance in the extension is usingNSStringFromClass(self)
This is because the name of the file, and the identifier of the view controller in the storyboard are typically made to be the same exact string. So all we have to do is...keep doing that.Now, you can do this for example:
Instead of doing this: (In
HomeViewController.swift
)You can replace this with:
And you can delete this line from your
StringsManager
fileOne last thing to note about
NSStringFromClass
in the extension, is this will prefix the class name with the module name, so you'll need to make sure you do the same when you implement this protocol. So, in your storyboard, change yourLoginViewController
storyboard identifier toVegetarian_Food_Finder.LoginViewController
Then the last thing you have to do is conform
LoginViewController
toStoryboardIdentifier
:You can repeat this process with Home/Search/SignUp view controllers as well.