2

In swift, structs have an automatically generated memberwise initializer.

This means the following struct can be initialised without me having to write an init.

struct Activity  {
    
    let name: String
    let desc: String
    
    let category: Category
    let subcategory: Subcategory
    let emoji: Character
    
    let coordinate: CLLocationCoordinate2D
    
    let creationTime: Date = Date()
    let activityTime: Date
    
    let id: UUID = UUID()
    
    var comments: [Comment] = []
}

I have one single property called emojiwhich is computed by the subcategory. In other words, the value for emoji depends on the value of subcategory.

However this means that the value of emoji can only be assigned after the initialisation of subcategory.

How should I do this in code?

Approach 1:

Provide my own initialiser

init(name: String, desc: String, category: Category, subcategory: Subcategory,
     coordinate: CLLocationCoordinate2D, activityTime: Date) {
    self.name = name
    self.desc = desc
    self.category = category
    self.subcategory = subcategory
    self.coordinate = coordinate
    self.activityTime = activityTime
    self.emoji = AllCategories.categories[category]?[subcategory] ?? "❌"
}

I don't like this approach as it adds a lot of unecessary code that will only grow if I add more properties... I would like to use the generated initialiser of the struct. On the other hand, the code is still very simple.

Approach 2:

Use a lazy varthat is only computed when called.

lazy var emoji: Character = {
     AllCategories.categories[category]?[subcategory] ?? "❌"
}()

I also don't really like this approach, I find it overly complex for what I am trying to do. Also this makes emojia varinstead of letwhich it is not, I want it to remain a constant. On the other hand, I can continue using the automatically generated initialiser.

Questions:

  1. What other possibilities do I have?
  2. If there are none, which of the 2 approches is the best?
1
  • 1
    While I would tend to use @Sweeper’s answer with computed properties, there is nothing particularly wrong with using lazy var - Apple mention using it in this way in the Swift documentation on initialisation. Commented Nov 9, 2019 at 12:09

1 Answer 1

2

This sounds like a great chance to use computed properties:

var emoji: Character {
     AllCategories.categories[category]?[subcategory] ?? "❌"
}

Although it is declared a var, you can't actually set it. It's just how computed properties must be declared.

The expression AllCategories.categories[category]?[subcategory] ?? "❌" will be evaluated every time you use the property. It's not a too time-consuming expression, so IMO it's fine.

Sign up to request clarification or add additional context in comments.

6 Comments

I forgot to mention this in my approaches, but I also considered computed properties, however I ruled them out because they are evaluated every time. Are you sure this is not problematic once I have a lot of activities and a large amount of categories? It would have to find a key in a dictionary each time an acitivity is displayed, which does really not seem efficient to me.
@charel-f Accessing a value in a dictionary is O(1) time. It doesn't do a linear search.
@charel-f Also, don't optimise prematurely. Try using computed properties first, then see if it is actually the dictionary accesses that is slowing your app down using a profiler. The chances are, it's something else.
Thanks for the tips. My application is not slow (yet), however I would like to have some code that is robust and scalable, and I am just not sure whether the, albeit small, added complexity added by evaluating the property every time is worth it over just including the rather useless initialiser.
Evaluating the property every time doesn't make your code not-robust or not-scalable. As I said, dictionary accesses have time complexity O(1), so no matter how big a dictionary you have, accessing it is going to take the same amount of time. Writing an initialiser is not scalable because you'd have to add new lines to your initialiser every time you add a new property. @charel-f
|

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.