Unique Identifier of a Mac?
Asked Answered
W

3

31

On an iPhone I can use

[[UIDevice currentDevice] uniqueIdentifier];

to get a string which identifies this device. Is there anything equal in OSX ? I didn't find anything. I just want to identify the Mac which started the application. Can you help me ?

Wohlen answered 3/5, 2011 at 11:11 Comment(2)
Check this question: #933960Prognostication
Have an up-vote and a Swift 2-updated answer. ;-)Seraglio
S
38

Apple has a technote on uniquely identifying a mac. Here's a loosely modified version of the code Apple has posted in that technote... don't forget to link your project against IOKit.framework in order to build this:

#import <IOKit/IOKitLib.h>

- (NSString *)serialNumber
{
    io_service_t    platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault,

    IOServiceMatching("IOPlatformExpertDevice"));
    CFStringRef serialNumberAsCFString = NULL;

    if (platformExpert) {
        serialNumberAsCFString = IORegistryEntryCreateCFProperty(platformExpert,
                                                         CFSTR(kIOPlatformSerialNumberKey),
                                                             kCFAllocatorDefault, 0);
        IOObjectRelease(platformExpert);
    }

    NSString *serialNumberAsNSString = nil;
    if (serialNumberAsCFString) {
        serialNumberAsNSString = [NSString stringWithString:(NSString *)serialNumberAsCFString];
        CFRelease(serialNumberAsCFString);
    }

    return serialNumberAsNSString;
}
Stereophonic answered 3/5, 2011 at 11:45 Comment(8)
Thank you for your answer I'll try it out. I didn't work with the IOKit yet. But will take a look at it.Wohlen
That's great! I don't really understand the code yet. But it gives me a serial number. Thank you!Wohlen
This solution isn't working in 64-bit mode unfortunately. Maybe you know something about this issue ?Mallet
@KamilZieliński you need to import IOKit.framework most likelyTuneless
Be aware that many times if a machine has been repaired (i.e. the motherboard replaced) then the machine will have NO serial number. You might want to consider falling back to the MAC address of a network interface.Aundreaaunson
Is this valid for app store?Procrastinate
@Jarret Would this violate any guidelines set by Apple(as of now) for app store submissions ?Geostatic
Added a Swift 2 answer.Seraglio
S
20

Swift 2 Answer

This answer augments Jarret Hardie's 2011 answer. It's a Swift 2 String extension. I've added inline comments to explain what I did and why, since navigating whether or not an object needs to be released can be tricky here.

extension String {

    static func macSerialNumber() -> String {

        // Get the platform expert
        let platformExpert: io_service_t = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));

        // Get the serial number as a CFString ( actually as Unmanaged<AnyObject>! )
        let serialNumberAsCFString = IORegistryEntryCreateCFProperty(platformExpert, kIOPlatformSerialNumberKey, kCFAllocatorDefault, 0);

        // Release the platform expert (we're responsible)
        IOObjectRelease(platformExpert);

        // Take the unretained value of the unmanaged-any-object 
        // (so we're not responsible for releasing it)
        // and pass it back as a String or, if it fails, an empty string
        return (serialNumberAsCFString.takeUnretainedValue() as? String) ?? ""

    }

}

Alternatively, the function could return String? and the last line could not return an empty string. That might make it easier to recognize the extreme situations where the serial number could not be retrieved (such as the repaired-Mac-motherboard scenario harrisg mentioned in his comment to Jerret's answer).

I also verified proper memory management with Instruments.

I hope someone finds it useful!

Seraglio answered 21/11, 2015 at 15:24 Comment(0)
B
3

Thanks. Works perfectly after changing

serialNumberAsNSString = [NSString stringWithString:(NSString *)serialNumberAsCFString];

TO

serialNumberAsNSString = [NSString stringWithString:(__bridge NSString *)serialNumberAsCFString];

the __bridge is recommended by Xcode itself.

Boiler answered 19/6, 2014 at 5:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.