Conditional Methods based on Operating System Version - objective-c

I am sure this is really simple, but I'm not sure even how to search for it, as I have seen example of what I think are called compiler flags?, but in general whats the best method in cocoa of condtionally running a specific method on Operating System Versions that support it. as an example the NSDateFormatter Class has the setDoesRelativeDateFormatting method which only works on 10.6 (on the Mac) and higher.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSLocale *enLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[dateFormatter setLocale:enLocale];
[dateFormatter setDoesRelativeDateFormatting:YES];

Here's how Adium detected that it was running on Snow Leopard or better to do stuff like this (this was in a category on NSApplication):
//Make sure the version number defines exist; when compiling in 10.5, NSAppKitVersionNumber10_5 isn't defined
#ifndef NSAppKitVersionNumber10_5
#define NSAppKitVersionNumber10_5 949
#endif
- (BOOL)isOnSnowLeopardOrBetter
{
return (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5);
}
Then all you have to do is
if ([NSApp isOnSnowLeopardOrBetter]) { ... }
You can find the version numbers for AppKit by command-clicking on NSAppKitVersionNumber to jump to its definition.

For this particular case, it should be easy enough to do the following:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSLocale *enLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[dateFormatter setLocale:enLocale];
if ([dateFormatter respondsToSelector:#selector(setDoesRelativeDateFormatting:)]) {
[dateFormatter setDoesRelativeDateFormatting:YES];
}
See NSObject protocol's -respondsToSelector: for more info.

Related

Swift 3 getting an optional value from objective-c class?

I have a project that still has a lot of objective-c code, like this one:
+ (NSString *)getDaysFromDateString:(NSString *)dateString
{
// Creating and configuring date formatter instance
NSLocale *ptBRLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"pt_BR"];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"];
[dateFormatter setLocale:ptBRLocale];
// Retrieve NSDate instance from stringified date presentation
NSDate *dateFromString = [dateFormatter dateFromString:dateString];
// Retrieve date with increased days count
NSDate *newDate = [dateFromString dateByAddingTimeInterval:-30*24*60*60];
return [dateFormatter stringFromDate:newDate];
}
This was working fine with my Swift 2.2 project (this project has both Swift and Objective-c) and always returned a value. Now, I have migrated my code to Swift 3.0 and for some reason the method above returns an optional value. How can I make the code above return a non-optional value again?

NSDateFormatter dateFromString:stringDate returning nil in iOS 8.3

I have this code
NSString *stringDate = #"2015-07-09 7:00 AM";
NSString *stringDateFormat = #"yyyy-MM-dd h:mm a";
NSTimeZone *timeZone = [NSTimeZone localTimeZone];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter setTimeZone:timeZone];
[dateFormatter setDateFormat:stringDateFormat];
NSDate *dateFormatted = [dateFormatter dateFromString:stringDate];
The problem now is dateFormatted keeps getting nil value. It is OK when I try it in Simulator iPhone5s 8.2 but, the problem occurs when I run it with device iPhone5s 8.3.
Can someone help me find why is dateFormatted is getting nil value?
It's almost a canned response but: QA1480. Set your formatter's locale to en_US_POSIX or its behaviour will be dependent upon the user's settings.

Is there a way to get Xcode's debugger to show dates in local timezone (i.e., not UTC)?

I'm trying to debug code that makes pretty heavy use of dates which has me comparing tons of different NSDate values in the debugger. The debugger is displaying those dates in UTC format--for example:
date1 = (NSDate *) 0x01b11460 #"2012-02-15 18:55:00 +0000"
It would be a lot easier for me if it would show them in my local timezone as that is what the test code I'm debugging seems to be using.
I do have feeling that I'm missing something much more basic here so I'm hoping someone can enlighten me. Thanks in advance.
While a little "hackish" you can create a subclass of NSDate and override just the
-(NSString *)description;
method to return a date formatted however you want.
The debugger isn't doing any special decoding for you, it's just calling the "description" method of the object it wants to display. A handy trick... (Which is why all my objects publish a concise description suitable for viewing in a debugger.)
In the end, what worked best was in fact adding a Category for NSDate that just overrides the description method to return a string that represents the NSDate in my current timezone. I also made it DEBUG only as I really just need this override in place when debugging.
Here's the .h file I used:
#ifdef DEBUG
#interface NSDate (DebugHelper)
-(NSString *)description;
#end
#endif
and the .m file:
#ifdef DEBUG
#import "NSDate+DebugHelper.h"
#implementation NSDate (DebugHelper)
-(NSString *) description
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
return [dateFormatter stringFromDate:self];
}
#end
#endif
Thanks to Jim Hayes and jrturton for the discussion and ideas that led to this answer.
Just did the same thing, however instead of systemTimeZone I used localTimeZone (see the docs as to why it is slightly better). Also I noticed you are alloc'ing the dateFormatter object but never releasing it which is a leak.
Here's my category method:
-(NSString *) description;
{
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init]autorelease];
NSLocale *enUSPOSIXLocale = [[[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"] autorelease];
[dateFormatter setLocale:enUSPOSIXLocale];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
[dateFormatter setDateStyle:NSDateFormatterLongStyle];
[dateFormatter setTimeStyle:NSDateFormatterLongStyle];
NSString *dateString = [dateFormatter stringFromDate:self];
return dateString;
}

How can I Convert a NSString to a valid NSDate (iOS)

I'm passing a string from javascript to Objective-C in the form of "2012-02-17 14:21:30 +0000".
My code is as follows:
NSString *firingDate = [_parameters objectForKey:#"fire"];
NSDate *notificationDate = [NSDate dateWithString:firingDate];
The issue is that I ended up reading the OS X reference instead of the iOS docs (doh!) so this throws a warning as dateWithString isn't present in iOS. In theory I suppose that this shouldn't work at all but it does, albeit with that warning.
What is the Correct way to convert the string to a NSDate?
The correct way is to use NSDateFormatter as a factory to create dates from strings (and vice versa).
Try:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = #"YYYY-MM-dd HH:mm:ss Z";
NSDate *notificationDate = [formatter dateFromString:firingDate];
Try this:
NSString *firingDate = [_parameters objectForKey:#"fire"];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSDate *notificationDate = [dateFormatter dateFromString:firingDate];
Check out the reference for parsing dates from multiple regions.
Don't forget to release your formatter when finished.

How to turn a NSString into NSDate?

Ive been racking my brains with no luck. Could someone please tell me how i would convert this string:
"2011-01-13T17:00:00+11:00"
into a NSDate?
The unicode date format doc is here
Also, for your situation, you could try this:
// original string
NSString *str = [NSString stringWithFormat:#"2011-01-13T17:00:00+11:00"];
// convert to date
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
// ignore +11 and use timezone name instead of seconds from gmt
[dateFormat setDateFormat:#"YYYY-MM-dd'T'HH:mm:ss'+11:00'"];
[dateFormat setTimeZone:[NSTimeZone timeZoneWithName:#"Australia/Melbourne"]];
NSDate *dte = [dateFormat dateFromString:str];
NSLog(#"Date: %#", dte);
// back to string
NSDateFormatter *dateFormat2 = [[NSDateFormatter alloc] init];
[dateFormat2 setDateFormat:#"YYYY-MM-dd'T'HH:mm:ssZZZ"];
[dateFormat2 setTimeZone:[NSTimeZone timeZoneWithName:#"Australia/Melbourne"]];
NSString *dateString = [dateFormat2 stringFromDate:dte];
NSLog(#"DateString: %#", dateString);
[dateFormat release];
[dateFormat2 release];
Hope this helps.
put the T part in single quotes, and check the unicode docs for the exact formatting. In my case, I have something similar, which I do this:
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"YYYY-MM-dd'T'HH:mm:ss.SSS"];
Again, not exactly the same, but you get the idea. Also, be careful of the timezones when converting back and forth between strings and nsdates.
Again, in my case, I use:
[dateFormat setTimeZone:[NSTimeZone timeZoneWithName:#"America/New_York"]];
Did you try this
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSDate *dateT = [dateFormatter dateFromString:str];
Cheers
You might check out TouchTime.
https://github.com/jheising/TouchTime.
It's a direct port of the awesome strtotime function in PHP in 5.4 for Cocoa and iOS. It will take in pretty much any arbitrary format of date or time string and convert it to an NSDate.
Hope it works, and enjoy!
Try using this cocoapods enabled project. There are many added functions that will probably be needed as well.
"A category to extend Cocoa's NSDate class with some convenience functions."
https://github.com/billymeltdown/nsdate-helper
Here's an example from their page:
NSDate *date = [NSDate dateFromString:#"2009-03-01 12:15:23"];