I'm trying to figure out a way to determine whether a Mac has a MagSafe charging port programmatically. If that's not possible, alternatively, I suppose detecting whether any USB-C ports exist (and thus MagSafe is not present).
I've searched around the web for APIs for this as well as shell commands but haven't found any good solutions. I need this to work in a sandboxed environment distributed through the Mac App Store. Ideally, any solution would be in pure Cocoa/Objective-C, but I am also fine with achieving this via NSTask or similar.
Thank you so much in advance for any suggestions!
I ended up compiling a list from EveryMac.com of all the models with MagSafe:
- (bool) macHasMagSafe
{
NSString *macModel = #"";
size_t len = 0;
sysctlbyname("hw.model", NULL, &len, NULL, 0);
if (len)
{
char *model = malloc(len*sizeof(char));
sysctlbyname("hw.model", model, &len, NULL, 0);
macModel = [NSString stringWithUTF8String:model];
free(model);
}
else
{
macModel = #"UNKNOWN";
}
NSArray *magSafeModels = [[NSArray alloc] initWithObjects:
// MACBOOK MODELS
#"MacBook7,1",
#"MacBook6,1",
#"MacBook5,2",
#"MacBook5,1",
#"MacBook4,1",
#"MacBook3,1",
#"MacBook2,1",
#"MacBook1,1",
// MACBOOK PRO MODELS
#"MacBookPro11,5",
#"MacBookPro11,4",
#"MacBookPro12,1",
#"MacBookPro11,3",
#"MacBookPro11,2",
#"MacBookPro11,1",
#"MacBookPro10,1",
#"MacBookPro10,2",
#"MacBookPro9,1",
#"MacBookPro9,2",
#"MacBookPro8,3",
#"MacBookPro8,2",
#"MacBookPro8,1",
#"MacBookPro6,1",
#"MacBookPro6,2",
#"MacBookPro7,1",
#"MacBookPro5,2",
#"MacBookPro5,3",
#"MacBookPro5,4",
#"MacBookPro5,5",
#"MacBookPro5,1",
#"MacBookPro4,1",
#"MacBookPro3,1",
#"MacBookPro2,1",
#"MacBookPro2,2",
#"MacBookPro1,2",
#"MacBookPro1,1",
// MACBOOK AIR MODELS
#"MacBookAir7,2",
#"MacBookAir7,1",
#"MacBookAir6,2",
#"MacBookAir6,1",
#"MacBookAir5,2",
#"MacBookAir5,1",
#"MacBookAir4,2",
#"MacBookAir4,1",
#"MacBookAir3,2",
#"MacBookAir3,1",
#"MacBookAir2,1",
#"MacBookAir1,1",
nil];
if ([magSafeModels containsObject:macModel])
{
return YES;
//NSLog(#"This Mac has a MagSafe port");
}
else
{
return NO;
//NSLog(#"This Mac DOES NOT have a MagSafe port");
}
}
I'm working on a Mac app that should distinguish MacBook and Mac desktops (iMac/Mac Pro).
I think I can get it done with model number. Then how I can get the model number? And which letter indicates it's a notebook or desktop? Or is there any other easier or better way?
You can use this little program. NSLog the output to test it.
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/sysctl.h>
+ (NSString *)machineModel
{
size_t length = 0;
sysctlbyname("hw.model", NULL, &length, NULL, 0);
if (length) {
char *m = malloc(length * sizeof(char));
sysctlbyname("hw.model", m, &length, NULL, 0);
NSString *model = [NSString stringWithUTF8String:m];
free(m);
return model;
}
return #"Unknown model";
}
It will provide the same output as entering sysctl hw.model on the terminal.
You haven't specified a language, but from Terminal sysctl hw.model will return with an identifier for the current Mac. For example, on my computer it returns MacBookPro5,5.
Is there any way to get the device type as a #define? I want to get this for an Universal app and I want to be able to know if it is an iPad, iPhone4 or iPhone5.
Thanks!
#define IS_WIDESCREEN ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
#define IS_IPHONE ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone )
#define IS_IPHONE_5 ( IS_IPHONE && IS_WIDESCREEN )
#define IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
Counter question:
Why use a macro, when there are methods available?
The macro translates into a method call any way, as you cannot know at compile time what device you’ll be confronted with at run time.
The device you’re running on is an iPad, if it says so:
BOOL isThisAnIPad = [[UIDevice currentDevice] userInterfaceIdiom] == UIInterfaceIdiomPad;
Apart from that, you automatically get the right resources by suffixing them with the correct values in combination with the usual #2x for retina graphics.
I have read many definitions of # if and # define statement.
I tried to use the way I read, but only with the error "Invalid token at start of a preprocessor expression" on the line that defines it as a comment below:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#define is_ipad (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define is_ipad_hd ( (is_ipad == 1 && [UIScreen mainScreen].bounds.size.width > 1024 ) ? YES : NO)
#define is_iphone_hd ([UIScreen mainScreen].bounds.size.width > 480 ? YES : NO)
#define device_width 480.0f
#define device_height 320.0f
#if (is_ipad_hd == YES) // Error here
#define device_width = 2048.0f
#define device_height = 1496.0f
#endif
Why it works in simple tutorials and when we try something more complex these things happen!
These are preprocessor directives, so you don't have access to [UIScreen mainScreen] methods and all other objects that are defined upon compilation!
Macro evaluation happens at compile time.
However, (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) or [UIScreen mainScreen] can only be interpreted at run time.
Beyond that, you should not be relying on the screen size to do your dirty work for you. You should instead be relying on the user interface idiom and the scale of the main screen:
BOOL isiPad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
BOOL isHD = [[UIScreen mainScreen] scale] == 2.0;
if (isiPad) {
if (isHD) {
// retina iPad
} else {
// non-retina iPad
}
} else {
if (isHD) {
// retina iPhone/iPod touch
} else {
// non-retina iPhone/iPod touch
}
}
Agree with others here although I'm not as well versed in the C preprocessor a quick googling came back with this:
expression is a C expression of integer type, subject to stringent restrictions. It may contain....
much better formatting than I can quickly achieve here on the source.
I want to identify my mac system uniquely via code. I find the Hardware UUID in my About this Mac.
So how to programmatically access the unique uuid from MAc OS X.
Kindly provide me if there are any alternative suggestion for my problem.
So, if you don't care about the new AppStore rules etc... here you go:
- (NSString *)getSystemUUID {
io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault,IOServiceMatching("IOPlatformExpertDevice"));
if (!platformExpert)
return nil;
CFTypeRef serialNumberAsCFString = IORegistryEntryCreateCFProperty(platformExpert,CFSTR(kIOPlatformUUIDKey),kCFAllocatorDefault, 0);
IOObjectRelease(platformExpert);
if (!serialNumberAsCFString)
return nil;
return (__bridge NSString *)(serialNumberAsCFString);;
}
Please Note:
You need to add IOKit.framework to your project in order for this
to work.
This code is ARC compliant;
This code is safe and it will return a nil NSString if something goes wrong;
Apple does not guarantee that all future systems will have a software-readable serial number.
Developers should not make any assumptions about the
format of the serial number such as its length or what characters it
may contain.
From here: https://stackoverflow.com/a/2754563/610351
void get_platform_uuid(char * buf, int bufSize) {
io_registry_entry_t ioRegistryRoot = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/");
CFStringRef uuidCf = (CFStringRef) IORegistryEntryCreateCFProperty(ioRegistryRoot, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);
IOObjectRelease(ioRegistryRoot);
CFStringGetCString(uuidCf, buf, bufSize, kCFStringEncodingMacRoman);
CFRelease(uuidCf);
}
You can replace the CFStringGetCString with a simple conversion to NSString*.