Get User Preferred Temperature Setting in Macos

Get user preferred temperature setting in macOS

The official API is documented under the Preferences Utilities:

let key = "AppleTemperatureUnit" as CFString
let domain = "Apple Global Domain" as CFString

if let unit = CFPreferencesCopyValue(key, domain, kCFPreferencesCurrentUser, kCFPreferencesAnyHost) as? String {
print(unit)
} else {
print("Temperature unit not found")
}

If you wonder how I found it, I used the defaults utility in the Terminal:

> defaults find temperature
Found 1 keys in domain 'Apple Global Domain': {
AppleTemperatureUnit = Fahrenheit;
}
Found 1 keys in domain 'com.apple.ncplugin.weather': {
WPUseMetricTemperatureUnits = 1;
}

Determine user's Temperature Unit setting on iOS 10 (Celsius / Fahrenheit)

There is this article by Alexandre Colucci that I found: http://blog.timac.org/?tag=nslocaletemperatureunit

First, expose the NSLocaleTemperatureUnit NSLocaleKey:

FOUNDATION_EXPORT NSLocaleKey const NSLocaleTemperatureUnit;

Then check the unit with this:

temperatureUnit = [[NSLocale currentLocale] objectForKey:NSLocaleTemperatureUnit]

Or Swift (2.3):

if let temperatureUnit = NSLocale.currentLocale().objectForKey(NSLocaleTemperatureUnit) {
...
}

It will return a string which is either "Celcius" or "Fahrenheit".

But there is an issue: it's not backwards compatible with iOS versions earlier than 10. If you run your app on an iOS 9 or earlier device, you'll get an error "dyld: Symbol not found: _NSLocaleTemperatureUnit" during app startup.

The solution is to use weak linking for the NSLocaleTemperatureUnit variable definition. Like this:

FOUNDATION_EXPORT NSLocaleKey const NSLocaleTemperatureUnit  __attribute__((weak_import));

This will let the app pass the dyld checks. But now you will have to check for the OS version before using NSLocaleTemperatureUnit, or your app will crash with an exception.

if #available(iOS 10,*) {
if let temperatureUnit = NSLocale.currentLocale().objectForKey(NSLocaleTemperatureUnit) {
...
}
}

EDIT:

I tried it in my app, but Apple rejected the app for it when I uploaded it to Testflight. So they definitely don't want us to use the setting for our own formatter classes. I find that pretty annoying.

Change the displayed unit instantly after user changes it using UISegmentedControl

Try to add that line of code before the end of - (IBAction)temperatureSelection:(UISegmentedControl *)sender method.

- (IBAction)temperatureSelection:(UISegmentedControl *)sender{
//..etc
temperatureSetting = [[temperaturePreferences valueForKey:@"temperature setting"]intValue];
if (temperatureSetting == 0) {
temp = (temp * 1.8) + 32;
temperatureLabel.text = [NSString stringWithFormat:@"%i°F", temp];
} else {
temperatureLabel.text = [NSString stringWithFormat: @"%iºC", temp];
}
[self.view setNeedsDisplayInRect:temperatureLabel.frame];//probably is not needed it forces the view to redraw itself as it mark as dirty
}

Find metric Speed, Degree, etc... standard by location

Some operating systems expose an API to find the preferred measurement standard.

  • For Android apps, use LocaleData.MeasurementSystem
  • For MacOS, use CFPreferencesCopyValue (guide)
  • For Windows, use GetLocaleInfo
  • For IOS, use NSLocaleUsesMetricSystem (guide)

Otherwise, if you know their location, you can default to Imperial in the United States, Liberia or Myanmar and use Metric in other locations:

The Imperial system is used in the United States, Liberia and Myanmar

Regardless, you should still allow users to manually choose their preference.

How to get battery info on Mac?

I created an open-source and easy to use framework called SystemInfoKit to get all system info, CPU, memory, and network usage, and temperatures.

Here is all the code that is needed to get all the battery info:

// At top of file
#import <SystemInfoKit/SystemInfoKit.h>

JSKSystemMonitor *systemMonitor = [JSKSystemMonitor systemMonitor];

JSKMBatteryUsageInfo batteryUsageInfo = systemMonitor.batteryUsageInfo;

NSLog(@"Battery Installed: %hhd", batteryUsageInfo.present);
NSLog(@"Battery Fully Charged: %hhd", batteryUsageInfo.full);
NSLog(@"Battery Connected To Charger: %hhd", batteryUsageInfo.acConnected);
NSLog(@"Battery Charging: %hhd", batteryUsageInfo.charging);

NSLog(@"Battery Voltage: %f V", batteryUsageInfo.voltage);
NSLog(@"Battery Amperage: %f A", batteryUsageInfo.amperage);

NSLog(@"Battery Design Capacity: %f mAh", batteryUsageInfo.designCapacity);
NSLog(@"Battery Maximum Capacity: %f mAh", batteryUsageInfo.maximumCapacity);
NSLog(@"Battery Current Capacity: %f mAh", batteryUsageInfo.currentCapacity);

NSLog(@"Battery Design Cycle Count: %lu Cycles", batteryUsageInfo.designCycleCount);
NSLog(@"Battery Cycle Count: %lu Cycles", batteryUsageInfo.cycleCount);
NSLog(@"Battery Age: %lu Days", batteryUsageInfo.ageInDays);

More info is here.

What is the standard method for writing a continuously running app that is allowed on the Mac App Store

The MAS guidelines have several prohibitions that would impact you. Go to the guidelines and read section 2. In particularly consider 2.15, 2.23, and 2.27. I don't know any way to get your application running prior to login without at some point requesting admin privileges (even if you don't use the privilege when you run).

I would probably make it a Login Item (System Preferences>Users>Login Items), probably as an LSUIElement app as sudo rm -rf suggests. Definitely if it's your first app, I wouldn't go diving into launchd in any case. It is one of the most infuriating system processes I've ever dealt with.



Related Topics



Leave a reply



Submit