depreciated methods

Im trying to create a function to retrieve my Mac's RAM usage but I get alerts saying essentially that my 'scanDouble' and 'scanCharecters(from:into:)' methods have been depreciated and Xcode also throw me these alerts if I compile this code. what are the newer alternatives to these methods?


import Foundation


class RAMUsage {
    
    let processInfo = ProcessInfo.processInfo
    
    func getRAM() {
        
        let physicalMemory = processInfo.physicalMemory
        let formatter = ByteCountFormatter()
        formatter.countStyle = .memory
        
        let formattedMemoryUsage = formatter.string(fromByteCount: Int64(physicalMemory))
        parseAndPrint(formattedMemoryUsage: formattedMemoryUsage)
    }
    func parseAndPrint(formattedMemoryUsage: String) {
        print("Formatted RAM usage: \(formattedMemoryUsage)")
        
        
        if let gigsOfRAM = parseFormattedRAMUsage(formattedUsage: formattedMemoryUsage) {
            
            print("RAM Usage in Gigabytes: \(gigsOfRAM) GB")
        } else {
            print("Could not retrieve or parse RAM usage")
        }
    }
    func parseFormattedRAMUsage(formattedUsage: String) -> Double? {
        let scanner = Scanner(string:  formattedUsage)
        var value: Double = 0.0
        var unit: NSString?
        
        if scanner.scanDouble(&value) {
          
            scanner.scanCharacters(from: .letters, into: &unit)
            
            if let unitString = unit as String?, unitString.lowercased() == "GB" {
                print("Parsed RAM Usage: \(value) GB")
                
                return value
            } else {
                print("could not parse and return value")
            }
            
        }
        return nil
        
    }
}

Accepted Reply

Those functions do seem to be deprecated in current macOS versions. It's unclear why the documentation is out of date.

The solution is to use the newer versions of these functions such as scanDouble(representation: .decimal). The differ in that they return the scanned value, rather than taking a pointer to memory to store the value. Failure is indicated by a nil result instead of a false return value.

  • thank you, ill try using that instead UPDATE: is there also an updated version for scanCharecters()?

Add a Comment

Replies

scanDouble is not marked as deprecated in documentation of Xcode 15.0.

Which version of Xcode are you using ?

  • @Claude31 I'm on Xcode 15.1 which should be the latest version, so it very much appears be to depreciated.

Add a Comment

Those functions do seem to be deprecated in current macOS versions. It's unclear why the documentation is out of date.

The solution is to use the newer versions of these functions such as scanDouble(representation: .decimal). The differ in that they return the scanned value, rather than taking a pointer to memory to store the value. Failure is indicated by a nil result instead of a false return value.

  • thank you, ill try using that instead UPDATE: is there also an updated version for scanCharecters()?

Add a Comment

The updated version of scanCharacters is:

 public func scanCharacters(from set: CharacterSet) -> String?

https://developer.apple.com/documentation/foundation/scanner/3200281-scancharacters/

Incidentally, to check all this out, I used "Jump to Definition" on scanDouble in Xcode, from the right-click context menu. That took me to a "generated" Swift header that showed all of the relevant function declarations together, and from there I was able to see the deprecations and the new functions.

For example, though it's not directly relevant to your question, I figured out there are no replacements for the older scanHex… functions because they're subsumed by the scan…(representation:) functions where the parameter distinguishes between decimal and hex input.

  • this works thank you, Xcode however then throws an error "Cannot convert return expression of type 'Double' to return type 'String?'" for my return value.

Add a Comment

Can you post an updated code fragment for us to look at?

Taking a step back…

What mechanism are you using to “to retrieve my Mac's RAM usage” that involves parsing strings to get numeric values?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

@eskimo @Polyphonic UPDATE: here is my updated code that some of you were requesting. I have the updated methods implemented but im getting the error "Cannot convert return expression of type 'Double' to return type 'String?'"

import Foundation


class RAMUsage {
    
    let processInfo = ProcessInfo.processInfo
    
    func getRAM() {
        
        let physicalMemory = processInfo.physicalMemory
        let formatter = ByteCountFormatter()
        formatter.countStyle = .memory
        
        let formattedMemoryUsage = formatter.string(fromByteCount: Int64(physicalMemory))
        parseAndPrint(formattedMemoryUsage: formattedMemoryUsage)
    }
    func parseAndPrint(formattedMemoryUsage: String) {
        print("Formatted RAM usage: \(formattedMemoryUsage)")
        
        
        if let gigsOfRAM = parseFormattedRAMUsage(formattedUsage: formattedMemoryUsage) {
            
            print("RAM Usage in Gigabytes: \(gigsOfRAM) GB")
        } else {
            print("Could not retrieve or parse RAM usage")
        }
    }
    func parseFormattedRAMUsage(formattedUsage: String) -> Double? {
        let scanner = Scanner(string: formattedUsage)
        var value: Double = 0.0
        var unit: NSString?
        
        if let scannedValue = scanner.scanDouble(representation: .decimal) {
            value = scannedValue
            func scanCharacters(from set: CharacterSet) -> String? {
                
                if let unitString = unit as String?, unitString.lowercased() == "GB" {
                    print("Parsed RAM Usage: \(value) GB")
                    
                    return value
                } else {
                    print("could not parse and return value")
                }
                
            }
            return nil
            
        }
    }
}

I’m confused by this code snippet. You’re getting a binary value from the physicalMemory property, which makes sense. You then render it to a string and then parse that string. Why are you doing that? Normally folks want one of two things:

  • A binary value, in which can you can use physicalMemory directly

  • A string, in which case you render the binary value to a string using a formatter (like ByteCountFormatter)

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • from my research I thought im supposed to have it converted as a string to convert it to a double before displaying the number value in the form of gigabytes, im probably wrong but I thought this was ok practice.

Add a Comment