I'm one month into self-learning Swift, and I would like some advice to improve my coding skills.

I have listed 2 situations that I think I need to improve. I'd like some feedback focusing on my use of static variables for changing data between ViewControllers and subviews.

1.0 Image 1 shows the app flow (Left = HomeController), middle = MenuController, Right = FavouritesController)

Image 1 Image 1

In HomeController there is a UIView subview. From this subview the current quote (HomeController.homeControllerCurrentQuote) displayed can be saved to favourites array. This is a static array defined in FavouritesController.

The functions below are called from the subview within HomeController. I made HomeController.homeControllerCurrentQuote static because the subview needs access to it. Likewise for FavouritesController.favourites.

In FavouritesController the data contained in FavouritesController.favourites array is used to populate a tableVIew.

// FavouritesController.favourites is static variable!
// HomeController.homeControllerCurrentQuote is static variable! updated as user scrolls

func handleFavourite() {
    let favourites = FavouritesController.favourites
    if favourites.contains(HomeController.homeControllerCurrentQuote) { 
    } else { FavouritesController.favourites.append(HomeController.homeControllerCurrentQuote)
        UserDefaults.standard.set(try? PropertyListEncoder().encode(FavouritesController.favourites), forKey:"myKey")

func removeFromFavourites() {
    var tempArray: [Quote] = [.init(category: "", quote: "", author: "")]
    tempArray = FavouritesController.favourites
    let searchString = HomeController.homeControllerCurrentQuote.quote
    var filteredArray = [Quote]()
    filteredArray = tempArray.filter( { !$0.quote.contains(searchString) } )
    UserDefaults.standard.set(try? PropertyListEncoder().encode(filteredArray), forKey:"myKey")

// update static variable on HomeController
internal override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    HomeController.homeControllerCurrentQuote = Quote(category: cell.categoryLabel.text ?? "", quote: cell.quoteLabel.text ?? "", author: author)

Should I change how this is done? I don't like the use of static variables but as it's my first app I was more focused on getting it done rather than how it was done. Is it a good case for using a delegate and protocol to communicate between the views (I've never used this before)? If so how would I start to think about implementing it or, as it works, is what I've done satisfactory?

2.0 When the app launches on HomeController required data is generated and is stored in a static variable.

                          //  [category : [quote  : author]]
static var xQuotesByCategory: [String   : [String : String]] = [:]

I make this data static because when I instantiate HomeController again from another controller, I don't want to have to refetch the data. I want to retrieve it once. Then when a new instance of HomeController is called I can make this check which should return false. Is this an appropriate use of a static variable?

if HomeController.xQuotesByCategory.values.isEmpty {
    ... fetchJson()

Following on from this, as HomeController.xQuotesByCategory is static, on CategoriesController I can call

var categories = Array(HomeController.xQuotesByCategory.keys)

This gets only the outer keys (categories) which I use to create the collectionView cells with the text and images shown in image 2. Again, same question, is this appropriate use of a static variable? Is there better way to ensure data is loaded only once and then pass the keys to CategoriesController in a different way when it's required?

image 2

If you'd like to try running the app, there is a test version available on TestFlight. Let me know and I can add you in TestFlight!



Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.