Objective-c code equal to guard
Asked Answered
E

6

5

I have been implementing the home kit app in objective-c . I have converted all the swift code but stoped at one line called

guard let metadata = metadata else { return false }

Could any one please guide me to write the objective-c code equivalent to the above line of code. Thank you so much for reading my post.

Eastereasterday answered 13/11, 2015 at 4:14 Comment(0)
S
9

From a compiler perspective there is no exact equivalent, because the guard statement else block is guaranteed to return control (i.e., the guard statement must be true for the code to continue past the guard). You can read more about it here.

The closest you can get is:

if(metadata == nil) { return NO; }
Safar answered 13/11, 2015 at 4:19 Comment(0)
P
2

There is not guard equivalent in Objective-C.

The closest would be to do this:

if (metadata == nil) {
    return NO;
}

...But there is the limitation that metadata has to be of an object type (i.e., class); it can't be a struct or a C scalar (e.g., NSUInteger).

Paleolithic answered 13/11, 2015 at 4:21 Comment(5)
Oops! forgot the ( ) after if. Been doing too much Swift lately!Paleolithic
For a single line the curly braces are optional in Objective-C.Stuffed
I know. But it doesn't hurt to include them anyway. It is not so unlikely that the lack of curly braces might come back and bite you when you add a second line.Paleolithic
Agreed. I always use curly braces as a matter of style. I was simply commenting on your 1st comment since the lack of braces wasn't actually incorrect in this case.Stuffed
I was talking about the ( ) enclosing the tested condition, not the { } enclosing the statement executed when the condition is satisified. I forgot to include those in the first version of my answer!Paleolithic
K
1

It 's:

 if (metadata == nil){
       return false;
  }
Kaleidoscope answered 13/11, 2015 at 4:18 Comment(1)
You forgot the semicolon after the return line. And if it's a BOOL type you should return NO, not false.Stuffed
A
0

You can use the "let" define in Objective-C++ which is defined:

#define let const auto

To convert your class of Objective-C to Objective-C++ only it is necessary to change the extension of .m to .mm

//Similar to "guard" in Swift
let object = myObject;
if (!object) {
    return;
}

//Other use case
if (let object = myObject) {
    //Object is not nil
    //Do something
}
Alexine answered 15/6, 2017 at 11:45 Comment(1)
You can also use __auto_type in normal Objective-C if you want, ie. #define let const __auto_type. Some differences with C++'s auto - see link. Declaring variables in a conditional expression still requires Objective-C++ though.String
K
0

Easiest would be to reverse the 'guard' condition, and use a simple if statement that exits, like thus:

if (!metadata) { return NO; }

Of course Obj-C compiler won't remind you that you must exit there, like the swift compiler.

One could #define a 'guard' macro that will automatically reverse the condition and also return after executing some parameter, but it can be tricky to write such macro in a general fashion, not knowing the type of returned value in advance.

#define GUARD(CONDITION,DO_BEFORE_EXIT) { if (!(CONDITION)) { DO_BEFORE_EXIT; return; }

and later, in your code:

GUARD(metaData!=nil, NSLog(@"ouch, nil metaData! exiting!");)

but there is also another old technique, with another benefit - unified handling of "final" code before exit, which is this:

-(void)myMethod {
  do {
    if (metadata==nil) break;

    // do something

    if (somethingelsefailed) break;

    // do something else
    // until done.

  while (false);
  NSLog(@"here put your final handling");
  return;
};

Something I found more useful in C and Objective-C code than Swift guards.

Kacey answered 29/7, 2019 at 11:53 Comment(0)
D
0

You probably want to simply use a if not for early return

For those who want to simulate the guard syntax in Swift for early return, I have a neat solution with macro. The idea is just like those above solutions, but I will try to explain some usages and defects.

The solution:

#define guard(conditionStatement) if (conditionStatement) {}

The usage:

Simple usage:

guard (YES) else {
    return;
}

In action:

- (nullable NSString *)formatUserName:(NSString *)userName {
    guard (userName != nil && [userName isKindOfClass:[NSString class]]) else {
        return nil;
    }
    
    NSString *formatedUserName = [userName stringByReplacingOccurrencesOfString:@" " 
                                           withString:@""];
    
    guard (formatedUserName.length > 0) else {
        return nil;
    }
    
    return formatedUserName;
}

Testing for assignment:

NSString *firstUserName;
NSString *secondUserName;

/// wrap the assignment in a () for a assign success test
guard ((firstUserName = [self formatUserName:@"first _ 1"]) && 
       (secondUserName = [self formatUserName:@"second _ 2"])) 
else {
    // fallback if any of the assignment failed
    // stop and skip all remaining statements whenever a statement is false
    return;
}

/// firstUserName == first_1
/// secondUserName == second_2

The cons:

  • Easy to miss/break some statement while editing code
  • Compile-time warning is not available, including an extremely important warning when you forget to break from the guard statement in Swift:
/// In swift
guard let userName else {
    /// `'guard' body must not fall through, consider using a 'return' or 'throw' to exit the scope`
}
  • Weird syntax usages, such as:
// Standalone statement without warning and any actual benefit
guard (userName != nil)

// Resulting from cooking `if` into `guard`
guard (YES) else if (YES) { } else if (YES) { /* What? */ };
Desalvo answered 19/12, 2023 at 14:40 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.