How to get actual name of Mac Operating System instead of version? - objective-c

I am able to get the version of OSX by using the code given below however what I want is the name of operating system (using Objective C).
Thanks in advance!!!
NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];
NSString* major = [NSString stringWithFormat:#"%d", version.majorVersion];
NSString* minor = [NSString stringWithFormat:#"%d", version.minorVersion];
NSString* patch = [NSString stringWithFormat:#"%d", version.patchVersion];

There is no API that I know of that would produce the product name of the current OS version. Even grepping for the product name in system locations yields surprisingly few results, and most of those in private frameworks. The only promising non-private match I found is in the Setup Assistant.app, and requires a horrible kludge to extract from a longer string:
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:#"/System/Library/CoreServices/Setup Assistant.app/Contents/Resources/en.lproj/Localizable.strings"];
NSString *productName = [dict objectForKey:#"INSTALLATION_COMPLETE"];
if (productName) {
NSRange r = [productName rangeOfString:#" has been"];
if (r.location != NSNotFound) {
productName = [productName substringToIndex:r.location];
} else {
productName = nil;
}
}
This happens to work for Yosemite and El Capitan, and produces "OS X Yosemite" and "OS X El Capitan". But even with these two versions the kludgey nature reveals itself; the El Capitan string contains non-breakable spaces…
Apart from this (or a similar kludge using other files not meant to be used this way), one can of course obtain the numeric version and match it against a list of known product names, which would be my recommended solution, perhaps with the above kludge as a fallback.

Silly, but this should work.
public extension ProcessInfo {
func osName() -> String? {
let version = self.operatingSystemVersion
switch version.minorVersion {
case 15: return "Catalina"
case 14: return "Mojave"
case 13: return "High Sierra"
case 12: return "Sierra"
case 11: return "El Capitan"
case 10: return "Yosemite"
case 9: return "Mavericks"
case 8: return "Mountain Lion"
case 7: return "Lion"
case 6: return "Snow Leopard"
case 5: return "Leopard"
case 4: return "Tiger"
case 3: return "Panther"
case 2: return "Jaguar"
case 1: return "Puma"
case 0: return "Kodiak"
default: return nil
}
}

for the sake of one more option to figure out the OSX Name i am providing a work-around below:
// this function will return os name
-(NSString *)getOSName{
// get major version
NSString* majorVersion = [self getMajorVersion];
// get minor version
NSString* minorVersion= [self getMinorVersion];
NSString* OSName = #"";
// figure out the name using versions
if([minorVersion isEqualTo:#"11"])
{
OSName = #"El Capitan";
}
else if([minorVersion isEqualTo:#"10"])
{
OSName = #"Yosemite";
}
else if([minorVersion isEqualTo:#"9"])
{
OSName = #"Mavericks";
}
else if([minorVersion isEqualTo:#"8"])
{
OSName = #"Mountain Lion";
}
else if([minorVersion isEqualTo:#"7"])
{
OSName = #"Lion";
}
else if([minorVersion isEqualTo:#"6"])
{
OSName = #"Snow Leopard";
}
else if([minorVersion isEqualTo:#"5"])
{
OSName = #"Leopard";
}
else if([minorVersion isEqualTo:#"4"])
{
OSName = #"Tiger";
}
else if([minorVersion isEqualTo:#"3"])
{
OSName = #"Panther";
}
else if([minorVersion isEqualTo:#"2"])
{
OSName = #"Jaguar";
}
else if([minorVersion isEqualTo:#"1"])
{
OSName = #"Puma";
}
else if([minorVersion isEqualTo:#"0"])
{
OSName = #"Kodiak";
}
return OSName;
}
-(NSString*)getMajorVersion{
NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];
NSString* ver = [NSString stringWithFormat:#"%d", version.majorVersion];
return ver;
}
-(NSString*)getMinorVersion{
NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];
NSString* ver = [NSString stringWithFormat:#"%d", version.minorVersion];
return ver;
}

Related

NSDictionary get value as string does not complain but lenngth or isEqualToString crashes

I got a Json like below as a response message.
data:{
type = DATA;
version = "4.51";
}
Which i process in below method, from the debugger it looks like that version no is string.
-(void)processResponse:(NSDictionary *)responseDictionary{
NSString *version = [responseDictionary valueForKey:#"version"];
if([version isEqualToString:#"4.51"]){ //line 3
NSLog(#"do something"); //crashes
}
}
But line 3 crashes.
My question is why this line crashes? And what is the best way to handle this type of dictionary message?
If this is data that originates outside your program, you must always check the types.
-(void)processResponse:(NSDictionary *)responseDictionary {
id value = responseDictionary[#"version"];
if ([value isKindOfClass: [NSString class]]) {
NSString *version = value;
if ([version isEqualToString: #"4.51"]) {
NSLog(#"do something"); //crashes
}
}
}
If this is all you're going to do, then you can shorten it a little bit with && short-circuiting, if you're careful.
-(void)processResponse:(NSDictionary *)responseDictionary {
NSString *version = responseDictionary[#"version"];
if ([version isKindOfClass: [NSString class]]
&& [version isEqualToString: #"4.51"]) {
NSLog(#"do something"); //crashes
}
}
Just be very careful with this, because it means that version exists beyond this if block and may not be the correct type.
Again, if this is precisely your problem, you can also simplify it by using isEqual:, which applies to all NSObject:
-(void)processResponse:(NSDictionary *)responseDictionary {
id version = responseDictionary[#"version"];
if ([version isEqual: #"4.51"]) {
NSLog(#"do something"); //crashes
}
}

Control reach end of non-void function

Please consider following code:
-(NSString*)getNextOvulationString{
if (self.daysToNextOvulation < 0){
return [NSString stringWithFormat:#"Овуляция была %li дней назад", labs(self.daysToNextOvulation)];
} else if (self.daysToNextOvulation == 0){
return [NSString stringWithFormat:#"Овуляция началась"];
} else if (self.daysToNextOvulation > 0){
return [NSString stringWithFormat:#"Овуляция началась"];
}
}
There is 3 cases, and obvious, we will get one guaranteed.
Still, compiler not allow me to build, because of error:
Control reach end of non-void function
How to fix that?
Since the final condition is the exhaustive case, change the final else if to an else and call it a day. If you want, add your condition as a same-line comment to keep it clear.
The end result would be something like this:
- (NSString *)getNextOvulationString
{
if (self.daysToNextOvulation < 0)
{
return [NSString stringWithFormat:#"Овуляция была %li дней назад", labs(self.daysToNextOvulation)];
}
else if (self.daysToNextOvulation == 0)
{
return [NSString stringWithFormat:#"Овуляция началась"];
}
else // self.daysToNextOvulation > 0
{
return [NSString stringWithFormat:#"Овуляция началась"];
}
}
You could also drop the final else altogether like this:
- (NSString *)getNextOvulationString
{
if (self.daysToNextOvulation < 0)
{
return [NSString stringWithFormat:#"Овуляция была %li дней назад", labs(self.daysToNextOvulation)];
}
else if (self.daysToNextOvulation == 0)
{
return [NSString stringWithFormat:#"Овуляция началась"];
}
// self.daysToNextOvulation > 0
return [NSString stringWithFormat:#"Овуляция началась"];
}
And since the last two conditions both return the same thing you could even write it this way:
- (NSString *)getNextOvulationString
{
if (self.daysToNextOvulation < 0)
{
return [NSString stringWithFormat:#"Овуляция была %li дней назад", labs(self.daysToNextOvulation)];
}
else // self.daysToNextOvulation >= 0
{
return [NSString stringWithFormat:#"Овуляция началась"];
}
}
Or this way, again dropping the else entirely:
- (NSString *)getNextOvulationString
{
if (self.daysToNextOvulation < 0)
{
return [NSString stringWithFormat:#"Овуляция была %li дней назад", labs(self.daysToNextOvulation)];
}
// self.daysToNextOvulation >= 0
return [NSString stringWithFormat:#"Овуляция началась"];
}
Note: All of the above pieces of code are functionally equivalent given the current conditions and return values.
You need to add else at last to return the NSString, so change you if condition like this.
-(NSString*)getNextOvulationString{
if (self.daysToNextOvulation < 0){
return [NSString stringWithFormat:#"Овуляция была %li дней назад", labs(self.daysToNextOvulation)];
}
else if (self.daysToNextOvulation == 0){
return [NSString stringWithFormat:#"Овуляция началась"];
}
else //No need to compare here
return [NSString stringWithFormat:#"Овуляция началась"];
}
}

Always returning null in NSString return function

I have the following code where I want to convert decimal odds to fractional odds. However the function findNearestWholeInteger always returns null.
- (NSString *)displayOddWithFormat:(NSString *)decimalOdd {
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"FractionalOdds"] == YES) {
float oddsF = decimalOdd.floatValue;
oddsF = oddsF - 1.0f;
return [self findNearestWholeInteger:oddsF andInitial:oddsF andBottom:1];
} else {
return odd;
}
}
- (NSString *)findNearestWholeInteger:(float)odds andInitial:(float)initial andBottom:(float)bottom {
NSNumber *numberValue = [NSNumber numberWithFloat:odds];
NSString *floatString = [numberValue stringValue];
NSArray *floatStringComps = [floatString componentsSeparatedByString:#"."];
if (floatStringComps.count == 1) {
return [NSString stringWithFormat:#"%.f/%.f", odds, bottom];
} else {
bottom += 1;
odds += initial;
[self findNearestWholeInteger:odds andInitial:initial andBottom:bottom];
return nil;
}
}
Any ideas where I need to adapt my code? Thanks in advance!
Don't you want:
return [self findNearestWholeInteger:odds andInitial:initial andBottom:bottom];
//return nil;
(not that I really understand what the method is doing).

custom Sorting objective-c OSX

I'm trying to sort an array of version numbers that might look like this properly sorted:
1.0.1
1.1.2
1.2.0
1.10.3
2.1.1
2.2.2
2.10.2
I have an array and I do the following:
NSArray *allUpdatekeys = [allUpdatekeystmp sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
This produces a list like:
1.0.1
1.1.2
1.10.3
1.2.0
...
So I tried writing a custom selector and I got this far by looking at examples I found:
- (NSComparisonResult)versionCompare:(NSString*) secondVersion {
NSArray *secondVer = [secondVersion componentsSeparatedByString:#"."];
NSString *firstVersion = [];
NSArray *firstVer = [firstVersion componentsSeparatedByString:#"."];
NSUInteger firstPri = [firstVer[0] integerValue];
NSUInteger firstSec = [firstVer[1] integerValue];
NSUInteger firstTer = [firstVer[2] integerValue];
NSUInteger secondPri = [secondVer[0] integerValue];
NSUInteger secondSec = [secondVer[1] integerValue];
NSUInteger secondTer = [secondVer[2] integerValue];
NSLog(#"In the version compare method");
NSLog(#"first %# second %# ", self, secondVersion);
if (firstPri < secondPri) {
return NSOrderedAscending;
}
else if (firstPri secondPri) {
return NSOrderedDescending;
} else {
if (firstSec < secondSec) {
return NSOrderedAscending;
}
else if (firstSec secondSec) {
return NSOrderedDescending;
}
else {
if (firstTer < secondTer) {
return NSOrderedAscending;
}
else if (firstTer secondTer) {
return NSOrderedDescending;
}
else {
return NSOrderedSame;
}
}
} }
My question: What is the way to reference the first version? I need what essentially is the first string from the array. I have been racking my brain to understand this, but all of the examples I have found don't work either. I'm using Xcode 4.4 on 10.8 if that helps or matters.
I think localizedStandardCompare is what you're looking for:
NSArray *theArray = [NSArray arrayWithObjects:
#"1.0.1",
#"1.1.2",
#"1.2.0",
#"1.10.3",
#"2.1.1",
#"2.2.2",
#"2.10.2",
nil];
NSArray *sortedArray = [[NSArray alloc] initWithArray:[theArray sortedArrayUsingSelector:#selector(localizedStandardCompare:)]];
NSLog(#"%#", sortedArray);
Output:
(
"1.0.1",
"1.1.2",
"1.2.0",
"1.10.3",
"2.1.1",
"2.2.2",
"2.10.2"
)
Another solution to get a sorted array in which 1.2.0 is less than 1.10.3, which means that
the array is numerically sorted, is:
allUpdatekeys = [allUpdatekeystmp sortedArrayUsingFunction:cmp context:NULL];
with the function:
NSComparisonResult cmp( id val1, id val2, void *context ){
return [val1 compare:num2 options:NSNumericSearch | NSCaseInsensitiveSearch];
}

How to Compare between Objects property's then sort using ( sortusingselector:#selector)?

I'm trying to write a simple function == " compareGPA" that compares between the GPA of two students , then sorting them in descending order by using selector as that : [array sortUsingSelector:#selector(compareGPA:)];
I've tried to write the function in 2 different ways , but nothing works ,
First way :
+(NSComparisonResult) compareGPA: (Student *) OtherStudent{
Student *tmp =[Student new];
if ([OtherStudent getGpa] < [tmp getGpa]){
return (NSComparisonResult) tmp;
}
if([tmp getGpa] < [OtherStudent getGpa])
{ return (NSComparisonResult) OtherStudent; }
}
2nd way :
+(NSComparisonResult) compareGPA: (Student *) OtherStudent{
NSComparisonResult res;
res = [[self getGpa] compare: [OtherStudent getGpa]];
return res;
Switch (res)
{
case NSOrderedAscending:
return NSOrderedDescending;
break;
case NSOrderedDescending:
return NSOrderedAscending;
break;
default:
return NSOrderedSame;
break;
}
}
Output : Nothing
Any suggestions ??
You should make your caparison method
+(NSComparisonResult) compareGPA: (Student *) OtherStudent
an instance method (not a class method, + becomes -), so that it compares the receiver's GPA with OtherStudent's GPA), like this
-(NSComparisonResult) compareGPA: (Student *) OtherStudent {
// if GPA is a float int double ...
if ([OtherStudent getGpa] == [self getGpa]
return NSOrderedSame;
if ([OtherStudent getGpa] < [self getGpa]){
return NSOrderedAscending;
return NSOrderedDescending;
// if GPA is an object which responds to the compare: message
return [[self getGPA] compare:[OtherStudent getGPA]]
}
Then sort your array of Student objects using selector #selector(compareGPA:)
As you're using compare: I have to assume that getGPA returns an NSNumber, in which case all you'd need would be this:
NSArray *students = ...;
NSArray *sortedStudents = [students sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"getGPa" ascending:NO]]];
If getGPA however was to return some primitice C type (such as float in your case), then you could do it this way:
NSArray *students = ...;
NSArray *sortedStudents = [students sortedArrayUsingComparator:^NSComparisonResult(Studen *student1, Studen *student2) {
float student1GPA = [student1 getGPA];
float student2GPA = [student2 getGPA];
if (student1GPA < student2GPA) {
return NSOrderedAscending;
} else if (student1GPA > student2GPA) {
return NSOrderedDescending;
}
return NSOrderedSame;
}];
If if you need the compareGPA: elsewhere, too:
- (NSComparisonResult) compareGPA:(Studen *otherStudent) {
float student1GPA = [self getGPA];
float student2GPA = [otherStudent getGPA];
if (student1GPA < student2GPA) {
return NSOrderedAscending;
} else if (student1GPA > student2GPA) {
return NSOrderedDescending;
}
return NSOrderedSame;
}