Как дифференцировать возвращаемое значение функции, используя блок завершения в Objective C? - PullRequest
0 голосов
/ 29 июня 2018

У меня есть функция, которая дает 2 различных значения String, которые возвращаются:

-(NSString*)load:(NSDictionary *)dict
{

    NSDictionary *dataDict = [self objectForId:@"data" fromDict:dict withDefault:nil];
    if (dataDict) {
        NSDictionary *success = [self objectForId:@"success" fromDict:dataDict withDefault:nil];

        NSString *str = [NSString stringWithFormat:@"%@", success];

        if ([str isEqualToString: @"1"])
        {
            NSDictionary *idDict = [self objectForId:@"id" fromDict:dataDict withDefault:nil];
            if (idDict) {
                NSString *idString = [NSString stringWithFormat:@"%@", idDict];
                return idString;
            }

        } else {
            NSDictionary *messages = [self objectForId:@"messages" fromDict:dataDict withDefault:nil];
            if (messages) {
                NSDictionary *messageDict = (NSDictionary *)messages;
                NSArray *type = messageDict[@"type"];
                if (type.count > 0) {
                    NSString *messageString = type[0][@"message"];
                    return messageString;
                }
            }
        }
    }
    return  nil;
}

И получить доступ к строковому значению, как это:

 NSString *string = [className load:dict];

Теперь я хочу написать, если операторы else для "idString" и "messageString" возвращают значения. Как дифференцировать 2 возвращаемых значения?

Ответы [ 5 ]

0 голосов
/ 03 июля 2018

При возврате NSDictionary (см. @ решение Yihui Yang ) или пользовательского класса (см. @ решение Sulthan ) для него являются действительными решениями, возможно, это будет слишком много .
Вам нужно запомнить ключи возвращаемого словаря или, может быть, создать собственный класс только для этого.

Вот еще две возможности:

У меня будет образец dict для проверки:

NSDictionary *dictToTest1 = @{@"id": @"idString",
                              @"noiseKey": @"noiseValue"
                              };
NSDictionary *dictToTest2 = @{@"messages": @"messagesString",
                              @"noiseKey": @"noiseValue"
                              };

Я упросту ваш тест, чтобы проверять только наличие ключа / значения для ключа id или для messages.

Использование двойных указателей:

-(void)loadDict:(NSDictionary *)dict withRetKey:(NSString **)key andRetValue:(NSString **)value
{
    NSString *retKey = nil;
    NSString *retValue = nil;
    if (dict[@"id"])
    {
        retKey = @"id";
        retValue = dict[@"id"];
    }
    else if (dict[@"messages"])
    {
        retKey = @"messages";
        retValue = dict[@"messages"];
    }

    if (key)
    {
        *key = retKey;
    }

    if (value)
    {
        *value = retValue;
    }
}

Образец теста:

NSString *key1 = nil;
NSString *value1 = nil;
[self loadDict:dictToTest1 withRetKey:&key1 andRetValue:&value1];
NSLog(@"Key1: %@\t value1: %@", key1, value1);
NSString *key2 = nil;
NSString *value2 = nil;
[self loadDict:dictToTest2 withRetKey:&key2 andRetValue:&value2];
NSLog(@"Key2: %@\t value2: %@", key2, value2);

Выход:

$> Key1: id  value1: idString
$> Key2: messages    value2: messagesString

Где вы видели & для объектов?
Почти все время в управлении NSError. ( связанный вопрос )
Для примитива? Например, если вы хотите получить красный / синий / зеленый / альфа из UIColor ( связанный вопрос )

С блоками:

-(void)blockLoadDict:(NSDictionary *)dict withBlock:(void(^) (NSString *key, NSString *value))block
{
    NSString *retKey = @"";
    NSString *retValue = @"";
    if (dict[@"id"])
    {
        retKey = @"id";
        retValue = dict[@"id"];
    }
    else if (dict[@"messages"])
    {
        retKey = @"messages";
        retValue = dict[@"messages"];
    }

    if (block)
    {
        block(retKey, retValue);
    }
}

Пример:

__block NSString *key3 = nil;
__block NSString *value3 = nil;
[self blockLoadDict:dictToTest1 withBlock:^(NSString *key, NSString *value) {
    key3 = key;
    value3 = value;
}];
NSLog(@"Block Key3: %@\t value3: %@", key3, value3);

__block NSString *key4 = nil;
__block NSString *value4 = nil;
[self blockLoadDict:dictToTest2 withBlock:^(NSString *key, NSString *value) {
    key4 = key;
    value4 = value;
}];
NSLog(@"Block Key4: %@\t value4: %@", key4, value4);

Выход:

$> Block Key3: id    value3: idString
$> Block Key4: messages  value4: messagesString
0 голосов
/ 02 июля 2018

Вместо того, чтобы возвращать простую строку, создайте объект, который будет возвращен:

@interface Result: NSObject
@property (nonatomic) NSString *id;
@property (nonatomic) NSString *message;
@end

В идеале вы могли бы создать -initWithDictionary: инициализатор, который бы обрабатывал синтаксический анализ.

0 голосов
/ 29 июня 2018

Вы можете использовать NSException. Вместо того, чтобы возвращать idString, вы бросаете NSException

@throw [NSException exceptionWithName:idString reason:nil userInfo:nil];

Тогда вы можете вызвать свой метод так:

@try{
    NSString *messageString = [className load:dict];
    NSLog(@"Message String: %@", messageString);
}@catch (NSException *e){
    NSString * idString = e.name;
    NSLog(@"ID String: %@",idString);
}
0 голосов
/ 02 июля 2018

Я бы сделал 2 отдельных метода. Первый возвращает только строку идентификатора, второй возвращает сообщение.

Таким образом, вы можете сделать что-то вроде этого:

NSDictionary *dict = /* some code here */;
NSString *message = nil;
NSString *idString = [foo loadId:dict];
if (idString.length == 0) {
    message = [foo loadMessage:dict];
}
0 голосов
/ 29 июня 2018

Я понимаю, что вы хотите знать, возвращает ли метод загрузки idString или messageString.

Так что я рекомендую использовать хитрый метод.

Вместо того, чтобы возвращать строку, вы можете вернуть dict, который похож на

    return @{
         @"type":@"idString",
         @"content":idString
         }

И используя

NSDictionary * returnDict = [className load:dict]
if ([returnDict[@"type"] isEqualToString:@"idString"]) {
    //code here
}
else{
    //code here
}

Наконец, я знаю, что это не лучшее решение, но оно будет работать нормально.

...