Подтвердить что ты не робот

Возврат нескольких значений из метода в Objective-C

Я задал аналогичный вопрос, но я не мог заставить его работать точно. Я создаю приложение для 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];

}

Однако этот код не работает, и мне нужно еще немного информации, чтобы это понять. Предположим, что я передаю ему эти значения:

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

Поэтому мне нужно вернуть все эти значения из метода.

Как объявить это в файле заголовка? Это должно быть в файле Objective-C, но вы могли бы дать мне код для всего файла, чтобы я мог видеть, куда он пойдет с @implementation и @end, whatnot. Также, как бы я назвал этот метод?

4b9b3361

Ответ 1

Поскольку вы можете возвращать только одно значение из любого метода на языках C и C, вам просто нужно вернуть одно значение, которое представляет все ваши другие значения. Это то, что делает ваш пример кода с помощью NSDictionary.

Пример кода верен, даже если он немного противоречит стандарту Objective-C.

То, что вы объявляете в файле заголовка, - это просто объявление метода, то есть:

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

В исходном файле:

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

Ответ 2

Как насчет передачи значений в качестве указателей?

Например:

- (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"

Edit:

Это одинаково хорошо работает с объектами. Вы часто увидите, что это используется при работе с объектами 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]; }
  }
}

Ответ 3

Если у вас есть много разных вещей, которые нужно вернуть из метода, либо инкапсулируйте его в NSDictionary, как другие предложили или рассмотрели просто определение класса. Вы можете объявить переменные и свойства экземпляра для инкапсуляции данных по мере необходимости.

Определение класса для инкапсуляции такой информации оказывается достаточно эффективным и максимально гибким. Если вам нужно реорганизовать ваше приложение таким образом, чтобы сбор данных получал новые поля, их необходимо сохранить позже или, возможно, потребуется расширить функциональность, класс облегчит эти изменения.

Ответ 4

Вы можете использовать блокировку блоков для возврата нескольких значений из метода, подобного этому. -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-fruitCount: 2, NSString-fruiteString: у вас есть яблоко в вашем списке много раз: 2

Ответ 5

Если вам нужно только вернуть примитивные значения, то возвращение структуры может быть оптимальным решением. Вы получаете проверку ошибок во время компиляции (например, в отличие от NSDictionary, где вы можете попытаться прочитать недопустимый ключ), не требуя при этом всех кодов/файлов, участвующих в создании класса.

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

Apple также использует структуры во многих своих методах (например, CGPoint, CGRect).

Причина, по которой это не будет работать с объектами, заключается в том, что ARC запрещает это.

Ответ 6

Одним из незначительных улучшений для последней точки в некоторых проектах является использование элементов, содержащих перечисление структуры. Это дает вам уже упомянутую проверку времени компиляции, то, что выглядит как объект в возвращаемом значении, и преимущество четких случаев, если вам нужно проверить значения в возврате.

Структура:

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

Код клиента:

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

Ответ 7

In Swift 4:

func changeV( varMoney:inout Int, varNumSheep: inout Int, varNumShepherds: inout Int, test1: inout String, test2: inout String){
    varMoney = 10
    varNumSheep = 10
    varNumShepherds = 10
    test1 = "TEST1"
    test2 = "TEST2"
}
var varMoney = 1
var varNumSheep = 1
var varNumShepherds = 1
var test1 = "test1"
var test2 = "test2"

changeV(varMoney: &varMoney, varNumSheep: &varNumSheep, varNumShepherds: &varNumShepherds, test1: &test1, test2: &test2)

print(varNumSheep)