Coder1000 Coder1000 - 7 months ago 9
Swift Question

How would you convert these two Swift enums to Objective-C?

How would you convert both these enums below to Objective-C?

public enum ISO8601Format: String {

case Year = "yyyy" // 1997
case YearMonth = "yyyy-MM" // 1997-07
case Date = "yyyy-MM-dd" // 1997-07-16
case DateTime = "yyyy-MM-dd'T'HH:mmZ" // 1997-07-16T19:20+01:00
case DateTimeSec = "yyyy-MM-dd'T'HH:mm:ssZ" // 1997-07-16T19:20:30+01:00
case DateTimeMilliSec = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" // 1997-07-16T19:20:30.45+01:00

init(dateString:String) {
switch dateString.characters.count {
case 4:
self = ISO8601Format(rawValue: ISO8601Format.Year.rawValue)!
case 7:
self = ISO8601Format(rawValue: ISO8601Format.YearMonth.rawValue)!
case 10:
self = ISO8601Format(rawValue: ISO8601Format.Date.rawValue)!
case 22:
self = ISO8601Format(rawValue: ISO8601Format.DateTime.rawValue)!
case 25:
self = ISO8601Format(rawValue: ISO8601Format.DateTimeSec.rawValue)!
default:// 28:
self = ISO8601Format(rawValue: ISO8601Format.DateTimeMilliSec.rawValue)!
}
}
}

public enum DateFormat {
case ISO8601(ISO8601Format?), DotNet, RSS, AltRSS, Custom(String)
}


I am looking for a 100% Objective-C answer. No Swift code and bridging headers.

I tried this:

Dateformat.h



#import <Foundation/Foundation.h>

extern NSString * const ISO8601DateFormatType;
extern NSString * const DotNetDateFormatType;
extern NSString * const RSSDateFormatType;
extern NSString * const AltRSSDateFormatType;
extern NSString * const CustomDateFormatType;

extern NSString * const ISOFormatYear;
extern NSString * const ISOFormatYearMonth; // 1997-07
extern NSString * const ISOFormatDate; // 1997-07-16
extern NSString * const ISOFormatDateTime; // 1997-07-16T19:20+01:00
extern NSString * const ISOFormatDateTimeSec; // 1997-07-16T19:20:30+01:00
extern NSString * const ISOFormatDateTimeMilliSec; // 1997-07-16T19:20:30.45+01:00


@interface DateFormat : NSObject

+ (instancetype) ISODateFormat: (NSString *) isoFormat;
+ (instancetype) DotNetDateFormat;
+ (instancetype) RSSDateFormat;
+ (instancetype) AltRSSDateFormat;
+ (instancetype) CustomDateFormat: (NSString *) formatString;

@property (readonly) NSString *dateFormatType;
@property (readonly) NSString *formatDetails;


@end


DateFormat.m



#import "DateFormat.h"

@implementation DateFormat

NSString * const ISO8601DateFormatType = @"ISO8601";
NSString * const DotNetDateFormatType = @"DotNet";
NSString * const RSSDateFormatType = @"RSS";
NSString * const AltRSSDateFormatType = @"AltRSS";
NSString * const CustomDateFormatType = @"Custom";

NSString * const ISOFormatYear = @"yyyy";
NSString * const ISOFormatYearMonth = @"yyyy-MM"; // 1997-07
NSString * const ISOFormatDate = @"yyyy-MM-dd"; // 1997-07-16
NSString * const ISOFormatDateTime = @"yyyy-MM-dd'T'HH:mmZ"; // 1997-07-16T19:20+01:00
NSString * const ISOFormatDateTimeSec = @"yyyy-MM-dd'T'HH:mm:ssZ"; // 1997-07-16T19:20:30+01:00
NSString * const ISOFormatDateTimeMilliSec = @"yyyy-MM-dd'T'HH:mm:ss.SSSZ"; // 1997-07-16T19:20:30.45+01:00

- (instancetype) initWithType: (NSString *) formatType details: (NSString *) details {

if(self = [super init]) {
_dateFormatType = formatType;
_formatDetails = details;
}

return self;
}

+ (instancetype) ISODateFormat: (NSString *) isoFormat
{
return [[DateFormat alloc] initWithType: ISO8601DateFormatType details: isoFormat];
}

+ (instancetype) DotNetDateFormat
{
return [[DateFormat alloc] initWithType: DotNetDateFormatType details: nil];
}

+ (instancetype) RSSDateFormat
{
return [[DateFormat alloc] initWithType: RSSDateFormatType details: nil];
}

+ (instancetype) AltRSSDateFormat
{
return [[DateFormat alloc] initWithType: AltRSSDateFormatType details: nil];
}

+ (instancetype) CustomDateFormat: (NSString *) formatString
{
return [[DateFormat alloc] initWithType: CustomDateFormatType details: formatString];
}

@end


I am looking for an alternate way of converting those Swift enums to Objective-C.

I don't have a specific problem; I am just interested in alternate manners to convert those enums to Objective-C. The code I already have works fine. But maybe there are more elegant solutions ?

Answer

Edit: This is not relevant now that the question has been edited to clarify that what is needed is a pure Objective-C answer. I'll leave this answer around in case it's useful to others.


I'm a bit rusty on the Objective-C side so there may be easier ways to code this. It's all done in Swift code which gets bridged over to Objective-C:

import Foundation

/// enum ISO8601Format String for Swift
public enum ISO8601Format: String {
  case Year             = "yyyy"                       // 1997
  case YearMonth        = "yyyy-MM"                    // 1997-07
  case Date             = "yyyy-MM-dd"                 // 1997-07-16
  case DateTime         = "yyyy-MM-dd'T'HH:mmZ"        // 1997-07-16T19:20+01:00
  case DateTimeSec      = "yyyy-MM-dd'T'HH:mm:ssZ"     // 1997-07-16T19:20:30+01:00
  case DateTimeMilliSec = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" // 1997-07-16T19:20:30.45+01:00
}

/// Bridges ISO8601Format to class constants for Objective-C
@objc(ISO8601Format)
class ISO8601FormatBridge: NSObject {
  static let Year             = ISO8601Format.Year.rawValue
  static let YearMonth        = ISO8601Format.YearMonth.rawValue
  static let Date             = ISO8601Format.Date.rawValue
  static let DateTime         = ISO8601Format.DateTime.rawValue
  static let DateTimeSec      = ISO8601Format.DateTimeSec.rawValue
  static let DateTimeMilliSec = ISO8601Format.DateTimeMilliSec.rawValue
}

/// enum DateFormat for Swift
public enum DateFormat {
  case ISO8601(ISO8601Format?)
  case DotNet
  case RSS
  case AltRSS
  case Custom(String)

  /// Strings for each case
  var name: String {
    switch self {
    case ISO8601 : return "ISO8601"
    case DotNet  : return "DotNet"
    case RSS     : return "RSS"
    case AltRSS  : return "AltRSS"
    case Custom  : return "Custom"
    }
  }
}

/// Bridges DateFormat to class factory methods for Objective-C
@objc(DateFormat)
class DateFormatBridge: NSObject {
  class func ISO8601(details:String?) -> DateFormatBridge {
    return DateFormatBridge(DateFormat.ISO8601(nil).name, details: details)
  }

  class func DotNet() -> DateFormatBridge {
    return DateFormatBridge(DateFormat.DotNet.name, details: nil)
  }

  class func RSS() -> DateFormatBridge {
    return DateFormatBridge(DateFormat.RSS.name, details: nil)
  }

  class func AltRSS() -> DateFormatBridge {
    return DateFormatBridge(DateFormat.AltRSS.name, details: nil)
  }

  class func Custom(details: String) -> DateFormatBridge {
    return DateFormatBridge(DateFormat.Custom("").name, details: details)
  }

  /// Type of Swift enum DateFormat
  let type: String
  /// Associated value of the type
  let details: String?

  /// Create instances with associated values
  private init(_ format: String, details: String?) {
    self.type = format
    self.details = details
  }
}

It can be used like this:

NSLog(@"%@", [ISO8601Format Year]);       // => "yyyy"
NSLog(@"%@", [ISO8601Format YearMonth]);  // => "yyyy-MM"

DateFormat * date = [DateFormat ISO8601:[ISO8601Format Year]];
NSLog(@"%@, %@", [date type], [date details]); // => "ISO8601, yyyy"