从 Objective-C 中的方法返回多个值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1692005/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 22:28:32  来源:igfitidea点击:

Returning multiple values from a method in Objective-C

iphoneobjective-creturn-value

提问by Ethan Mick

I asked a similar question, but I couldn't get it working exactly. I'm building an iPhone app, and there is a method that I want called from different files. I figured the easiest way would simply be to make a method in another file, and call the method from the other files.

我问了一个类似的问题,但我无法让它完全正常工作。我正在构建一个 iPhone 应用程序,我想从不同的文件中调用一个方法。我认为最简单的方法就是在另一个文件中创建一个方法,然后从其他文件中调用该方法。

Here are some problems. I need to return multiple values from the method, after passing it multiple values. For example, I'm passing it: (int, int, int, string, string). And it needs to return all of those values, after they have been changed. Someone showed me this code:

这里有一些问题。在传递多个值后,我需要从该方法返回多个值。例如,我正在传递它:(int, int, int, string, string)。并且需要在更改后返回所有这些值。有人给我看了这段代码:

- (NSDictionary *)EndOfTurn:(int)varTurns withFatness:(int)varFatness
{
    varTurns--;

    if (varTurns <= 0) {
        varFatness = varFatness - 5;
    }
    else {
        varFatness += 2;
    }

    return [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:varFatness], @"FATNESS", [NSNumber numberWithInt:varTurns], @"TURNS", nil];

}

However, this code doesn't work, and I need some more information to really understand it. Let's assuming I'm passing it these values:

但是,此代码不起作用,我需要更多信息才能真正理解它。让我们假设我将这些值传递给它:

int varMoney;
int varNumSheep;
int varNumShepherds;
NSString *test1;
NSString *test2;

So I need to get all of these values back from the method.

所以我需要从方法中取回所有这些值。

How do I declare this in the header file? This should be in an Objective-C file, but could you give me the code for the entire file so I can see where it would go with the @implementationand @end, whatnot. Also, how would I call this method?

我如何在头文件中声明它?这应该在一个 Objective-C 文件中,但是你能给我整个文件的代码,这样我就可以看到它会与@implementationand一起去哪里@end。另外,我将如何调用此方法?

采纳答案by Jim Puls

Since you can only return a single value from any method in C and C-derived languages, you simply need to return a single value that represents all of your other values. This is what your sample code is doing with an NSDictionary.

由于您只能从 C 和 C 派生语言中的任何方法返回单个值,因此您只需返回一个表示所有其他值的值。这就是您的示例代码对NSDictionary.

The sample code is correct, even if it's a bit contrary to common Objective-C style.

示例代码是正确的,即使它与常见的 Objective-C 风格有点相反。

What you declare in the header file is simply the declaration of the method, that is:

你在头文件中声明的只是方法的声明,即:

@interface MyClass : NSObject
- (NSDictionary *)EndOfTurn:(int)varTurns withFatness:(int)varFatness;
@end

In the source file, then:

在源文件中,然后:

@implementation MyClass
// code, as given above
@end

回答by Dave DeLong

What about passing in the values as pointers?

将值作为指针传递怎么样?

For example:

例如:

- (void) getValuesForInt:(int *)int1 anotherInt:(int *)int2 aBool:(BOOL *)bool1 anotherBool:(BOOL *)bool2 {
  if (*int1 == 42 && *int2 == 0) {
    *int1 = 0;
    *int2 = 42;
  }
  if (*bool1 == NO) {
    *bool2 = YES;
  }
}

Then you can invoke it like:

然后你可以像这样调用它:

int int1 = 42;
int int2 = 0;
BOOL bool1 = NO;
BOOL bool2 = NO;
[self getValuesForInt:&int1 anotherInt:&int2 aBool:&bool1 anotherBool:&bool2];
NSLog(@"int1: %d int2: %d bool1: %d bool2: %d", int1, int2, bool1, bool2);
//prints "int1: 0 int2: 42 bool1: 0 bool2: 1"

Edit:

编辑:

This works equally well with objects. You'll often see this used when dealing with NSErrorobjects:

这同样适用于对象。在处理NSError对象时,你会经常看到这个用法:

NSError *error = nil;
[anObject doSomething:foo error:&error];

Can be implemented as:

可以实现为:

- (void) doSomething:(id)terrible error:(NSError **)error {
  if ([terrible isEqual:reallyBad]) {
    if (error != nil) { *error = [NSError errorWithDomain:@"domain" code:42 userInfo:nil]; }
  }
}

回答by Richie Hyatt

You can use a block closure to pass back multiple values from a method like this. -rrh

您可以使用块闭包从这样的方法传回多个值。-rh

[self heyFunctionGiveMeBackTwoValuesFromThisFruitArray:@[@"apple", @"orange", @"banana", @"apple"] findThisFruit:@"apple" closureFunction:^(int fruitCount, NSString* fruitString)
{
    NSLog(@"Two values returned, int-fruitCount:%d, NSString-fruiteString:%@", fruitCount, fruitString);
}];

- (void)heyFunctionGiveMeBackTwoValuesFromThisFruitArray:(NSArray*)fruitsArray findThisFruit:(NSString*)findThisFruit closureFunction:(void (^)(int fruitCount, NSString *fruitString))passBackResultsUsingThisClosure
{
    NSInteger fruitsFound = 0;
    NSString* fruitsMessage = [NSString stringWithFormat:@"No %@ Found", findThisFruit];
    for (NSString* string in fruitsArray)
    {
        if ([string compare:findThisFruit] == NSOrderedSame)
        {
            fruitsFound++;
        }
    }
    if (fruitsFound > 0)
    {
        fruitsMessage = [NSString stringWithFormat:@"You have %@ on your list this many times:%d", findThisFruit, fruitsFound];
    }
    passBackResultsUsingThisClosure(fruitsFound, fruitsMessage);
}

Results: Two values returned, int-fruitCount:2, NSString-fruiteString:You have apple on your list this many times:2

结果:返回两个值,int-fruitCount:2,NSString-fruiteString:您的列表中多次出现苹果:2

回答by bbum

If you have that many different things that need to be returned from a method, either encapsulate it into an NSDictionary as others have suggested or consider just defining a class. You can declare the instance variables and properties to encapsulate the data, as needed.

如果你有很多不同的东西需要从一个方法中返回,要么像其他人建议的那样将它封装到 NSDictionary 中,要么考虑只定义一个类。您可以根据需要声明实例变量和属性来封装数据。

Defining a class to encapsulate such information proves to be quite efficient and maximizes flexibility. If you need to refactor your app such that the collection of data gains new fields, needs to be saved for later, or might need to gain functionality, a class will ease these changes.

定义一个类来封装这些信息被证明是非常有效的,并最大限度地提高了灵活性。如果您需要重构您的应用程序,以便数据集合获得新字段、需要保存以供以后使用,或者可能需要获得功能,则类将简化这些更改。

回答by Senseful

If you only need to return primitive values, then returning a struct may be the optimal solution. You get compile-time error checking (e.g. as opposed to an NSDictionary where you could attempt to read an invalid key), while not requiring all the code/files involved in creating a class.

如果您只需要返回原始值,那么返回一个结构体可能是最佳解决方案。您可以进行编译时错误检查(例如,与 NSDictionary 相比,您可以尝试读取无效密钥),同时不需要创建类所涉及的所有代码/文件。

typedef struct myStruct {
  int varMoney;
  int varNumSheep;
  int varNumShepherds;
} myStruct;

Apple uses structs in many of their methods too (e.g. CGPoint, CGRect).

Apple 在他们的许多方法中也使用了结构体(例如 CGPoint、CGRect)。

The reason this won't work with objects is because ARC forbids this.

这不适用于对象的原因是因为ARC 禁止 this

回答by MarkSWeiss

One slight improvement to the last point in some designs is to use a struct holding enum members. This gives you the compile-time checking already mentioned, something that looks like an object in the return value, and the benefit of clear cases if you need to check the values in the return.

在某些设计中对最后一点的一个小改进是使用一个结构体来保存枚举成员。这为您提供了已经提到的编译时检查,它看起来像返回值中的一个对象,以及如果您需要检查返回值中的清晰案例的好处。

The struct:

结构:

typedef struct _SIXRecorderStateChange {
    SIXRecorderState oldState;
    SIXRecorderState newState;
} SIXRecorderStateChange;

The client code:

客户端代码:

    SIXRecorderStateChange stateChange = [recorderState stop];
    if (stateChange.newState == SIXRecorderStopped) {
...
...