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

Iphone 从Objective-C中的方法返回多个值,iphone,objective-c,return-value,Iphone,Objective C,Return Value,我问了一个类似的问题,但我不能让它完全正常工作。我正在构建一个iPhone应用程序,我想从不同的文件调用一个方法。我认为最简单的方法就是在另一个文件中创建一个方法,然后从其他文件中调用该方法 这里有一些问题。在传递多个值之后,我需要从方法返回多个值。例如,我正在传递它:(int,int,int,string,string)。它需要在这些值被更改后返回所有这些值。有人给我看了这个代码: - (NSDictionary *)EndOfTurn:(int)varTurns withFatness:(i

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

这里有一些问题。在传递多个值之后,我需要从方法返回多个值。例如,我正在传递它:
(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];

}
所以我需要从方法中得到所有这些值


我如何在头文件中声明它?这应该在Objective-C文件中,但是您能给我整个文件的代码吗?这样我就可以看到
@implementation
@end
,等等。另外,我该如何调用此方法?

将值作为指针传入怎么样

例如:

- (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;
  }
}
然后您可以像这样调用它:

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"
编辑:

这同样适用于对象。在处理
NSError
对象时,您经常会看到这一点:

NSError *error = nil;
[anObject doSomething:foo error:&error];
可实施为:

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

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

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

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

@interface MyClass : NSObject
- (NSDictionary *)EndOfTurn:(int)varTurns withFatness:(int)varFatness;
@end
在源文件中,然后:

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

如果你有很多不同的东西需要从一个方法中返回,或者把它封装成一个NS字典,就像其他人建议的那样,或者只是定义一个类。您可以根据需要声明实例变量和属性来封装数据


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

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

typedef struct myStruct {
  int varMoney;
  int varNumSheep;
  int varNumShepherds;
} myStruct;
苹果在许多方法中也使用了结构(例如CGPoint、CGRect)


这不适用于对象的原因是。

在某些设计中,对最后一点的一个小小改进是使用包含枚举成员的结构。这为您提供了前面提到的编译时检查、返回值中看起来像对象的东西,以及如果需要检查返回值中的值,则清除大小写的好处

结构:

typedef struct _SIXRecorderStateChange {
    SIXRecorderState oldState;
    SIXRecorderState newState;
} SIXRecorderStateChange;
客户端代码:

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

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

[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);
}
结果:
返回两个值,int-fructCount:2,NSString-fructestring:apple多次出现在您的列表中:2

我想指出的是,“withFatness”是一个非常棒的函数。您还需要保留此函数的结果。因为您返回的词典是通过一种方便的方法生成的,所以它会自动删除,如果不保留,很快就会消失。i、 e.当你叫它时,你会这样做:NSDictionary*myDic=[self EndOfTurn:turns with fatness:fatness];[保留多年电价];然后[myDic释放];当你做的很好并且完成了它。它应该是*int2==0。另外,您的NSLog行缺少参数。@Wayfarer edit answer提供了一个如何处理对象的示例。我对该方法的不满是,不能传入属性,因为作为属性的参数可能甚至没有底层内存位置,因此该语言禁止这样做。这意味着,除了在不需要返回时频繁传递nils之外,如果任何辅助值需要存储在属性中,则需要首先声明一个局部变量,然后将该值分配给属性。好的,调用此函数的语法是什么?我已经导入了头文件,但是当我尝试调用函数时,它会说“Expected:Before:token.This调用:(NSDictionary*)EndOfTurn:(int)varTurns withFatness:(int)varFatness;我将变量“varTurns”和“varFatness”传递给它,您的调用应该类似于[object EndOfTurn:varTurns withFatness:varFatness](int)bits只是用于定义,而不是调用。我很确定,自ARC以来,不再支持在struct中嵌入对象。可能最好像其他人提到的那样使用类或字典,即使它稍微不太“优化”“。如果您不担心工作负载,尤其是对帧敏感的应用程序,这将是一个好主意。如果你正在开发,比如说一款虚拟现实应用,每一点节省都会带来好处,所以我个人会在这些情况下使用DaveDeLong的答案。
[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);
}