iphone - lottie - Devolviendo múltiples valores desde un método en Objective-C
appcode vs xcode (7)
Hice una pregunta similar, pero no pude hacer que funcionara exactamente. Estoy creando una aplicación para iPhone y hay un método al que quiero llamar desde diferentes archivos. Pensé que la forma más sencilla sería simplemente crear un método en otro archivo y llamar al método desde los otros archivos.
Aquí hay algunos problemas. Necesito devolver varios valores del método, después de pasarle varios valores. Por ejemplo, lo estoy pasando: (int, int, int, string, string)
. Y debe devolver todos esos valores, después de que hayan sido cambiados. Alguien me mostró este código:
- (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];
}
Sin embargo, este código no funciona y necesito más información para entenderlo realmente. Supongamos que le estoy pasando estos valores:
int varMoney;
int varNumSheep;
int varNumShepherds;
NSString *test1;
NSString *test2;
Así que necesito recuperar todos estos valores del método.
¿Cómo declaro esto en el archivo de encabezado? Esto debería estar en un archivo de Objective-C, pero ¿podría darme el código para todo el archivo para que pueda ver dónde iría con @implementation
y @end
, todo eso? Además, ¿cómo llamaría a este método?
¿Qué pasa con pasar los valores como punteros?
Por ejemplo:
- (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;
}
}
Entonces puedes invocarlo como:
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"
Editar:
Esto funciona igualmente bien con los objetos. A menudo verá que se usa esto cuando se trata de objetos NSError
:
NSError *error = nil;
[anObject doSomething:foo error:&error];
Puede ser implementado como:
- (void) doSomething:(id)terrible error:(NSError **)error {
if ([terrible isEqual:reallyBad]) {
if (error != nil) { *error = [NSError errorWithDomain:@"domain" code:42 userInfo:nil]; }
}
}
Dado que solo puede devolver un solo valor desde cualquier método en los idiomas derivados de C y C, simplemente debe devolver un solo valor que represente todos sus otros valores. Esto es lo que hace su código de muestra con un NSDictionary
.
El código de muestra es correcto, incluso si es un poco contrario al estilo común de Objective-C.
Lo que declara en el archivo de encabezado es simplemente la declaración del método, es decir:
@interface MyClass : NSObject
- (NSDictionary *)EndOfTurn:(int)varTurns withFatness:(int)varFatness;
@end
En el archivo fuente, entonces:
@implementation MyClass
// code, as given above
@end
Puede utilizar un cierre de bloque para devolver varios valores de un método como este. -rr
[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);
}
Resultados: Se devolvieron dos valores, int-fruitCount: 2, NSString-fruiteString: Tienes Apple en tu lista tantas veces: 2
Si solo necesita devolver valores primitivos, entonces devolver una estructura puede ser la solución óptima. Obtiene una verificación de errores en tiempo de compilación (por ejemplo, a diferencia de un NSDictionary donde podría intentar leer una clave no válida), mientras que no requiere todos los códigos / archivos involucrados en la creación de una clase.
typedef struct myStruct {
int varMoney;
int varNumSheep;
int varNumShepherds;
} myStruct;
Apple también utiliza estructuras en muchos de sus métodos (por ejemplo, CGPoint, CGRect).
La razón por la que esto no funciona con los objetos es porque ARC prohíbe esto .
Si tiene tantas cosas diferentes que deben devolverse de un método, encapsúlelas en un NSDictionary como otros han sugerido o considere simplemente definir una clase. Puede declarar las variables de instancia y las propiedades para encapsular los datos, según sea necesario.
Definir una clase para encapsular dicha información resulta ser bastante eficiente y maximiza la flexibilidad. Si necesita refactorizar su aplicación de tal manera que la recopilación de datos obtenga nuevos campos, deba guardarse para más adelante o pueda necesitar funcionalidad, una clase facilitará estos cambios.
Una leve mejora del último punto en algunos diseños es usar una estructura que contenga miembros de enumeración. Esto le brinda la verificación en tiempo de compilación ya mencionada, algo que se parece a un objeto en el valor de retorno, y el beneficio de los casos claros si necesita verificar los valores en el retorno.
La estructura:
typedef struct _SIXRecorderStateChange {
SIXRecorderState oldState;
SIXRecorderState newState;
} SIXRecorderStateChange;
El código del cliente:
SIXRecorderStateChange stateChange = [recorderState stop];
if (stateChange.newState == SIXRecorderStopped) {
...
...
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)