WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

Magic Numbers

Forums > Swift

I have asked this sort of before. In our apps I've heard that using magic numbers is frowned upon. So you dont want to see alot of the following:

Text("Something Here")
  .opacity(1)

So for this I was using someting I wrote in thats just a big enum called Constants with static properites like so:

  enum Constants {
    static let i1: Int = 1
  }

However, its come to my attention that thats not good idea because i1 is still 1.

So my question is this, what do you all do with magic numbers when using them. I've been trying to convert my code for say things like a views width and height. Just not sure how to handle all those magic numbers, because writing .opacity(1) is the same as .opacity(Constants.i1)

Love to hear everyones thoughts Taz

   

Consider this

enum Constants {
    static let partialOpacity: Double  = 0.75
}

If you used partialOpacity many times in your code and decided to change it to 0.6 instead, how much easier it is to change it one place than in many. To make it a habit you could even define the enum just for one case.

Do we sometimes write the magic numbers? Of course we do, especially when we are just trying out some code. But at some point we might transistion to writing constants, as you are discovering.

Ultimately, it is up to you. A judgement call. As long as you can justify why, even if it is just to yourself, why you chose one approach above another, then it is your code to write.

But it is better to write constants when you can. Just my opinion.

   

@Greenamberred

Thanks for the reply. The only thing I have an issue with in my code is the Constants.i1 meaning an integer 1. I think you got that. I just need to go through and figure out what each one is suppose to be doing and write a better description the i1, i2 etc etc...

Again thanks for the reply.

Still would love to hear others opinions on this? Just trying to get a range of view points....

   

Mark asks for other opinions:

Still would love to hear others opinions on this? Just trying to get a range of view points....

You asked this same question in May? And received excellent, friendly, complete responses then.

Same Question

   

I have been converting my code to do things like @Greenamberred suggested. Thats going well.

After some more thought on my end, what I'm really concerned with are numbers inside for loops or things of that sort.

for 0...12 { 
  // some code here
}

I read a while back on StackOverflow (can't find the thread now) that we shouldn't even do that. We should always create constants for them, you don't ever want to see these numbers just floating around in code. I am assuming because of readability. I will admit that goes contrary to what my professors taught me all those years ago in class. Thats where I struggle with this concept. Coming up with good names for them and deciding when to use a constant and not.

So, my new solution for when I really want a number is to create a enum with static properties for one, two, three etc etc... At this point not sure if its the right way, but as pointed out to me, if it makes sense to me then go ahead.

   

Firstly by using static let i1: Int = 1 you are in danger of changing some code that you did not want to. If you change static let i1: Int = 2 then all the i1 have changed which might cause some problem. I think what people say in using numbers in code is not about making it easier to read but easier to change.

Say you have a Button

Button("Do Something") {
  // do something
}
.padding(10)
.background(.blue)
foregroundColor(.white)

How ever you have a few buttons in your app across different views and you now want to change the padding to 20 you would then have to look for every time you use a button how then you can do

enum Constant {
    static var buttonPadding = 10.0
}

and then do the buttons like

Button("Do Something") {
  // do something
}
.padding(Constant.buttonPadding)
.background(.blue)
foregroundColor(.white)

Now if you change the buttonPadding to 20 all the button change in the app.

So my thinking is if you use it more then once then look at finding a way to replace the number however if only once then l think it just as easy to read.

PS I would probably use a ViewModifier to this and then use eg

struct customButtonStyle: ViewModifier {
    let color: Color

    func body(content: Content) -> some View {
        content
            .padding(10) // <- note the use of number
            .background(color)
            .foregroundColor(.white)
    }
}

extension View {
    func myButtonStyle(with color: Color) -> some View {
        modifier(customButtonStyle(color: color))
    }
}

Then my buttons would have this

 Button("Do Something") {
    // do something
}
.myButtonStyle(with: .blue)

If I then want to change the padding to 20 for the the button would only have to change it in the ViewModifier.

   

@NigelGee

Thanks for the reply. I appreciate the your take on it.

So let me ask you this. You wouldn't ever create something like the following just to enter numbers in the app. You'd just write the number.

enum Numbers {
  static let one: Int = 1
}

I'm getting that that might be overkill. I can also see your point that if its not being used more than once then why create a constant for only one thing.

On view modifiers I have never really considered that. That might be the way to go as it would apply to all button, pickers etc....

Once again thanks for the insight. I know that I've asked this before and have gotten anwsers on it before, so I appreciate everyones patience with my asking again. I'm just trying to understand and come up with something that works for me and that makes sense to me.

   

Hi @TazmanCoder

You ask

So let me ask you this. You wouldn't ever create something like the following just to enter numbers in the app. You'd just write the number.

No I would not as Numbers.one is it a Int or Double etc therefore hard to read. Also you do not have to make enums for it you can just use it as a property. This is a a code snippet from an app.

class AppStore: ObservableObject {
    let threshold = 10 // <- as you can see this is used twice in following code but only in this class

    @AppStorage("runsSinceLastRequest") var runsSinceLastRequest = 1

    @Published var showingOverlay = false
    // Some other code

    func check() {
        // Some other code

        runsSinceLastRequest += 1

        if runsSinceLastRequest >= threshold {
            if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
                SKStoreReviewController.requestReview(in: scene) // <- This will change in iOS16
            }
        } else if runsSinceLastRequest == threshold - 3 {
            showingOverlay = true
        }
    }
}

so if I want to to change the threshold I can without having to change it in the method twice.

Do not get to hung up on people say do not use this or that eg NEVER force unwrap but there are times that you can safely do it. NEVER use magic number but again there are times that it makes sense to to it. Just you do what you feel comfortable with.

   

Hi @NigelGee

Thanks for all the clarification. i have taking what you've said and what @Greenamberred has said and made a few modications to one of my apps. Specifically, I added a couple view modifiers and I completely eliminated the enum Constants where I had those static let i1: CGFloat = 1 properties.

Actually, I find the code a little easier to read now and its more clear whats happening to a view etc.....

So, now on to another app to fix all its bad code... but i guess thats what we do, we learn something new then apply what we've learned. Always improving our code.

Thanks again for all your help with the explanations etc....... @Greenamberred, thanks again for your advice as well.......

Taz

   

Hacking with Swift is sponsored by Emerge

SPONSORED Why are Swift reference types bad for app startup time, and what’s the performance cost of protocol conformances? That’s just a couple of the topics you can learn about on the Emerge blog — written by the app performance experts behind Emerge’s advanced app optimization and monitoring tools, based on their experience of working at companies like Apple, Airbnb, Snap, and Spotify.

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.