Nathan Winspear
Nathan Winspear

Reputation: 119

SwiftUI String formatting is rounding my values to nearest whole number?

I hope you're all well!

I have a (potentially) silly question. I'm attempting to learn SwiftUI development by recreating the Instagram UI.

Right now, I'm working on the user page that shows a single user and their profile statistics. I'm seeing some weird behaviour with my string formatting.

HStack (spacing: 24){
    VStack (alignment: .center, spacing: 2) {
        Text(postCountString)
            .font(.system(size: 16, weight: .bold))
        
        Text("Posts")
            .font(.system(size: 13, weight: .regular))
    }
    VStack (alignment: .center, spacing: 2) {
        Text(followerCountString)
            .font(.system(size: 16, weight: .bold))
        
        Text("Followers")
            .font(.system(size: 13, weight: .regular))
    }
    VStack (alignment: .center, spacing: 2) {
        Text(followsCountString)
            .font(.system(size: 16, weight: .bold))
        
        Text("Follows")
            .font(.system(size: 13, weight: .regular))
    }
}
.frame(maxWidth: .infinity)
.padding(.leading, 16)
.onAppear {
    postCountString = UIHelperFunctions.FormatCountNumber(number: creator.posts.count)
    followerCountString = UIHelperFunctions.FormatCountNumber(number: creator.followerCount)
    followsCountString = UIHelperFunctions.FormatCountNumber(number: creator.followsCount)
}

Above is the View component that shows the main statistics of a creator (Posts, Followers, Follows). When the view is displayed, it should run each statistic through my UIHelperFunction that formats the number into a nice readable string see function


import Foundation

class UIHelperFunctions {
    
     static func FormatCountNumber(number: Int) -> String {
        
         guard number > 1000 else {
             return String(number)
         }
         
         guard number > 10000 else {
             return String(format: "%.1fK", Double(number/1000))
         }
         
         guard number > 1000000 else {
             return String(format: "%dK", number/1000)
         }
         
         return String(format: "%.1fM", Double(number/1000000))

    }
    
}

// Example with input: 32495
print(UIHelperFunctions.FormatCountNumber(number: 32495)) // Output: 32K

However, when I input a value between 1000 and 10000, it returns a close value; however, it leaves the decimal place as 0. Below is an image that shows what I see on the screen when I input the value 6748. I would expect it to output 6.7K, but I'm seeing 6.0K.

XCode Preview of error

Am I doing something silly? If not, am I misunderstanding how floating point maths works in SwiftUI?

Any help would be greatly appreciated; let me know if you need more context or code.

Thanks in advance :)

Upvotes: 3

Views: 525

Answers (2)

malhal
malhal

Reputation: 30746

SwiftUI does formatting for us and it automatically updates the UILabel on screen when the region settings change, simply do:

Text(creator.posts.count, format: .number)

or

Text("Count: \(creator.posts.count, format: .number)")

To get the M, K etc. in the future this should work (if this ever gets approved)

extension NumberFormatter {
    static var compact: NumberFormatter = {
       let f =  NumberFormatter()
       f.numberStyle = .compact
       return f
    }()
}

Text(creator.posts.count, formatter: NumberFormatter.compact)

Upvotes: 2

Asperi
Asperi

Reputation: 258365

Int divided on Int will be Int, converting it to Double is too late, you need instead to divide double on double, like

 guard number > 10000 else {
     return String(format: "%.1fK", Double(number)/Double(1000)))
 }

Upvotes: 2

Related Questions