0

I am trying to convert this swift code to Objective-C

convenience init(fromString string: String, format:DateFormat)
    {
        if string.isEmpty {
            self.init()
            return
        }

        let string = string as NSString

        switch format {

        case .DotNet:

            let startIndex = string.rangeOfString("(").location + 1
            let endIndex = string.rangeOfString(")").location
            let range = NSRange(location: startIndex, length: endIndex-startIndex)
            let milliseconds = (string.substringWithRange(range) as NSString).longLongValue
            let interval = NSTimeInterval(milliseconds / 1000)
            self.init(timeIntervalSince1970: interval)

So far, I am doing this:

-(id) initFromString: (NSString *) string format: (DateFormat *) format{
    if (string == nil) {
        self = [self init];
        return self;
    }


    switch (format) {
        case .DotNet:
            NSRange *startIndex = [[string rangeOfString:@"("] location]+1;

    }
}

and have already run into the following errors:

for the switch(format): statement requires expression of integer type (DateFormat * __strong' invalid)

and for the 2 following lines: Expected expression

Any ideas ?

  • was DateFormat an enum in the swift code? you've changed it to a class in the objc code, passing in `format` as a pointer to an instance of DateFormat. The compiler doesn't want you to switch on a pointer like that. – Patrick Goley Apr 12 '16 at 15:03
  • Slightly off-topic, but in the current world your init should return "instancetype" instead of id. Just a handy hint for the compiler. – Scott Thompson Apr 12 '16 at 15:06

2 Answers2

2

In Objective-C, the string is impliedly optional. Testing for nil merely tests whether a string was supplied. It doesn't check whether an empty string was supplied. You probably want to switch to string.length == 0 as, by the magic of nil-messaging, that'll work to check for either an empty string or no string at all.

Objective-C uses C's switch statement. So you can switch on integral types only. If this were Objective-C code originally, DateFormat would probably be an NS_ENUM — an integral type rather than an object type. It looks like the original was an enumeration from your use of dot syntax? If you can make it an Objective-C enumeration then do so and simply use:

- (id)initFromString:(NSString *)string format:(DateFormat)format {
    ....
    switch(format)
    {
        case DateFormatDotNet: {
            ....
        } break;
    }

(with the curly brackets within the case being because you want to declare variables in there).

Otherwise, if it must be an object format then you're looking at a painful construction like:

if([format isEqual:[DateFormat dotNetFormat]]) {
}
else if([format isEqual:[DateFormat otherFormat]]) {
}
... etc ...

Also Objective-C has a syntactic distinction between structs, which are exactly what they are in C — named fields but no built-in behaviour — and object types, which is again because it's a strict superset of C. NSRange is a struct. So square bracket messaging syntax doesn't work on it. Instead of:

[[string rangeOfString:@"("] location]

Use:

[string rangeOfString:@"("].location

Square brackets around the rangeOfString call because it's a message dispatch to an object, then a dot for location because you get back a C struct as a value, and that's how one accesses a field in a C struct.

(dot syntax also works for properties on Objective-C objects, but explicitly to alias to getter and setter calls, and only for about the most recent of Objective-C's three decades)

Tommy
  • 99,986
  • 12
  • 185
  • 204
  • What about the startIndex error ? tells me: Bad receiver type "NSRange" (aka "struct_NSRange") –  Apr 12 '16 at 15:27
  • Another piece of residue from Objective-C leaving the programmer to parse the difference between `struct`s (which are the C sort, i.e. named-field storage with no logic that are either value or reference types, so quite different from the Swift sort) and objects. I'll update the answer. – Tommy Apr 12 '16 at 19:02
  • One last question: how do you convert this in Objective-C ? self.init(timeIntervalSince1970: interval) –  Apr 13 '16 at 12:57
  • @CodeOxO the first parameter becomes part of the method name, with a 'with' conjunctive. If it's `NSDate` then it's `[self initWithTimeIntervalSince1970:interval]` (and, normally, you'd want a `[[self alloc] initWith...]`, but if you had subclassed and added a new `init` that was just doing a conversion and calling the main `init` then you wouldn't want the `alloc`, as the memory is already allocated). – Tommy Apr 13 '16 at 13:40
  • Thx ! And you answered fast ! –  Apr 13 '16 at 13:50
0

Assuming this code is related to How to convert a Swift enum: String into an Objective-C enum: NSString?

Since your DateFormat variable is an object with a dateFormatType that is an NSString, you are going to have to use a chained if-else construct to select from the various possibilities:

if([format.dateFormatType compare: DotNetDateFormatType] == NSOrderedSame) {
    [self handleDotNetDateFormat: format]
} else if ([format.dateFormatType compare: RSSDateFormatType] == NSOrderedSame) {
   [self handleRSSDateFormat: format]
...

Objective-C has no concept of the dot-value syntax for enum values (so ".DotNet" is not a valid term in Objective-C). That's why the compiler is complaining about those either lines.

Community
  • 1
  • 1
Scott Thompson
  • 22,629
  • 4
  • 32
  • 34
  • What about the startIndex error ? tells me: Bad receiver type "NSRange" (aka "struct_NSRange") –  Apr 12 '16 at 15:25
  • An NSRange is a struct, not an objective-C object. You are using it in a message passing structure `[[string rangeOfString:@"("] location]`. Just use `[string rangeOfString:@"("].location` – Scott Thompson Apr 12 '16 at 16:40
  • Thank you for your help ! I wish I could give +1 but my rep is not high enough :/ EDIT: I actually could do it but it will only show up once I reach 15 rep. –  Apr 12 '16 at 20:13