-5

Inspired by this question:

Is there a way of getting a Mac's icon given its model number?

I was working around getting similar results but using the Mac's model identifier as a start, not the Mac's model number.

But I'm stuck with a weird problem when using my Mac's model identifier to find the related system icon.


On my office machine I get "iMac14,2" as a model identifier.

When I load this plist as a dictionary...

/System/Library/PrivateFrameworks/ServerInformation.framework/Versions/A/Resources/English.lproj/SIMachineAttributes.plist

...I see that it has keys for all Mac models, including "iMac14,2", and the values contain, among other things, the URL for the icon.

However, when I try to grab this dictionary's value for the identifier key ("iMac14,2") I got nil, although I get the actual value if I grab it with a literal key.

But the literal key and the key I get from my modelIdentifier function are the same. It looks like it anyway...


To grab the model identifier:

func modelIdentifier() -> String? {
    let service: io_service_t = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice").takeUnretainedValue())
    let cfstr = "model" as CFString
    if let model = IORegistryEntryCreateCFProperty(service, cfstr, kCFAllocatorDefault, 0).takeUnretainedValue() as? NSData {
        if let nsstr =  NSString(data: model, encoding: NSUTF8StringEncoding) {
            return String(nsstr)
        }
    }
    return nil
}

if let id = modelIdentifier() {
    println(id) // prints "iMac14,2"
}

Finding the value with this result fails:

if let dict = NSDictionary(contentsOfFile: "/System/Library/PrivateFrameworks/ServerInformation.framework/Versions/A/Resources/English.lproj/SIMachineAttributes.plist") as? [String:AnyObject] {

    if let id = modelIdentifier() {
        if let result = dict[id] as? [String:AnyObject] {
            print(result) // nil
        }
    }

}

But if I do the same with a literal string it works:

if let result = dict["iMac14,2"] as? [String:AnyObject] {
    print(result)
}

result:

[architecture: x86_64, LOCALIZABLE: { description = "iMac with 27\" widescreen LED-backlit display, introduced late 2013."; marketingModel = "27\" iMac (Late 2013)"; model = iMac; processor = "Quad-core Intel Core i5, Quad-core Intel Core i7"; }, hardwareImageName: /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/com.apple.imac-unibody-27-no-optical.icns]


What is wrong here?

The strings look the same but aren't the same?

Or am I missing something else?

Community
  • 1
  • 1
Eric Aya
  • 69,473
  • 35
  • 181
  • 253

1 Answers1

3

The NSData created by IORegistryEntryCreateCFProperty for the model key contains a NUL-terminated string. You're including that NUL in your NSString.

Create your string this way instead:

    if let nsstr = NSString(CString: UnsafePointer<Int8>(model.bytes), encoding: NSUTF8StringEncoding) {
        return String(nsstr)
    }
rob mayoff
  • 375,296
  • 67
  • 796
  • 848