¿Cómo puedo pasar un Block
a un Function
/Method
?Bloque de paso Objective-C como parámetro
Probé - (void)someFunc:(__Block)someBlock
pero no sirvió.
es decir. ¿Cuál es el tipo para un Block
?
¿Cómo puedo pasar un Block
a un Function
/Method
?Bloque de paso Objective-C como parámetro
Probé - (void)someFunc:(__Block)someBlock
pero no sirvió.
es decir. ¿Cuál es el tipo para un Block
?
El tipo de bloque varía según sus argumentos y su tipo de retorno. En el caso general, los tipos de bloque se declaran de la misma manera que los tipos de puntero a función, pero reemplazando el *
con un ^
. Una forma de pasar un bloque a un método es la siguiente:
- (void)iterateWidgets:(void (^)(id, int))iteratorBlock;
Pero como pueden ver, es complicado. en su lugar se puede utilizar un typedef
para hacer tipos de bloques más limpio:
typedef void (^ IteratorBlock)(id, int);
y luego pasar ese bloque a un método de este modo:
- (void)iterateWidgets:(IteratorBlock)iteratorBlock;
¿Por qué estás pasando id como argumento? ¿No es posible pasar fácilmente un NSNumber por ejemplo? ¿Cómo se vería eso? – bas
Definitivamente puede pasar un argumento fuertemente tipado como 'NSNumber *' o 'std :: string &' o cualquier otra cosa que pueda pasar como un argumento de función. Esto es solo un ejemplo. (Para un bloque que es equivalente excepto para reemplazar 'id' con' NSNumber', 'typedef' sería' typedef void (^ IteratorWithNumberBlock) (NSNumber *, int); '.) –
Esto muestra la declaración del método. Un problema con los bloques es que el estilo de declaración "desordenado" no hace que sea claro y fácil escribir la llamada al método real con un argumento de bloque real. – uchuugaka
también Invoque o llame a un bloque utilizando la sintaxis de función c habitual
-(void)iterateWidgets:(IteratorBlock)iteratorBlock{
iteratorBlock(someId, someInt);
}
Más información sobre bloques de aquí
El enlace a los documentos de los bloques me ayudó. –
También puede configurar como un simple bloque de la propiedad si es aplicable para usted:
@property (nonatomic, copy) void (^didFinishEditingHandler)(float rating, NSString *reviewString);
asegúrese de que la propiedad de bloque es "copia"!
y por supuesto también se puede utilizar typedef:
typedef void (^SimpleBlock)(id);
@property (nonatomic, copy) SimpleBlock someActionHandler;
usted puede hacer como este, pasando de bloques como un parámetro de bloque:
//creating a block named "completion" that will take no arguments and will return void
void(^completion)() = ^() {
NSLog(@"bbb");
};
//creating a block namd "block" that will take a block as argument and will return void
void(^block)(void(^completion)()) = ^(void(^completion)()) {
NSLog(@"aaa");
completion();
};
//invoking block "block" with block "completion" as argument
block(completion);
una forma más de pasar bloque usando funciones с en ejemplo a continuación. He creado funciones para realizar cualquier cosa en el fondo y en la cola principal.
archivo blocks.h
void performInBackground(void(^block)(void));
void performOnMainQueue(void(^block)(void));
archivo blocks.m
#import "blocks.h"
void performInBackground(void(^block)(void)) {
if (nil == block) {
return;
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), block);
}
void performOnMainQueue(void(^block)(void)) {
if (nil == block) {
return;
}
dispatch_async(dispatch_get_main_queue(), block);
}
Que blocks.h importación cuando sea necesario y invocarlo:
- (void)loadInBackground {
performInBackground(^{
NSLog(@"Loading something in background");
//loading code
performOnMainQueue(^{
//completion hadler code on main queue
});
});
}
A pesar de las respuestas dadas en este Hilo, realmente tuve problemas para escribir una función que tomara un Bloque como función, y con un parámetro. Eventualmente, aquí está la solución que se me ocurrió.
que quería escribir una función genérica, loadJSONthread
, lo que llevaría la URL de un servicio web JSON, cargar algunos datos JSON de esta URL en un subproceso de fondo, a continuación, devolver un NSArray * de los resultados de vuelta a la función de llamada.
Básicamente, quería mantener oculta toda la complejidad del hilo de fondo en una función reutilizable genérica.
Así es como me gustaría llamar a esta función:
NSString* WebServiceURL = @"http://www.inorthwind.com/Service1.svc/getAllCustomers";
[JSONHelper loadJSONthread:WebServiceURL onLoadedData:^(NSArray *results) {
// Finished loading the JSON data
NSLog(@"Loaded %lu rows.", (unsigned long)results.count);
// Iterate through our array of Company records, and create/update the records in our SQLite database
for (NSDictionary *oneCompany in results)
{
// Do something with this Company record (eg store it in our SQLite database)
}
} ];
... y este es el bit luché con: cómo declarar, y cómo conseguir que se llame a la función Bloquear vez que los datos se cargado, y pasar el Block
un NSArray * registros de carga:
+(void)loadJSONthread:(NSString*)urlString onLoadedData:(void (^)(NSArray*))onLoadedData
{
__block NSArray* results = nil;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
// Call an external function to load the JSON data
NSDictionary * dictionary = [JSONHelper loadJSONDataFromURL:urlString];
results = [dictionary objectForKey:@"Results"];
dispatch_async(dispatch_get_main_queue(), ^{
// This code gets run on the main thread when the JSON has loaded
onLoadedData(results);
});
});
}
Este StackOverflow cuestión se refiere a cómo llaman funciones, pasando de un bloque como un parámetro, por lo que he simplificado el código anterior, y no se incluye el loadJSONDataFromURL
función.
Pero, si usted está interesado, puede encontrar una copia de esta función de carga JSON en este blog: http://mikesknowledgebase.azurewebsites.net/pages/Services/WebServices-Page6.htm
Espero que esto ayude algunos otros desarrolladores XCode! (no se olvide de votar por esta pregunta y mi respuesta, si lo hace!)
Este es realmente uno de los mejores trucos que he visto para iOS y bloques. ¡Ámalo hombre! – portforwardpodcast
escribí un completionBlock para una clase que devolverá los valores de los dados después de que han sido sacudidas:
Definir typedef con returnType (.h
anteriormente @interface
declaración)
typedef void (^CompleteDiceRolling)(NSInteger diceValue);
definir un @property
para el bloque (.h
)
@property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
definir un método con finishBlock
(.h
)
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
método definido anterior Insertar en .m
archivo e finishBlock
a @property
definido antes
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
self.completeDiceRolling = finishBlock;
}
Para desencadenar completionBlock
pase predefinido variableType to it (No se olvide de comprobar si el completionBlock
existe)
if(self.completeDiceRolling){
self.completeDiceRolling(self.dieValue);
}
siempre tiendo a olvidar acerca de la sintaxis bloques. Esto siempre me viene a la mente cuando necesito declarar un bloque.Espero que ayude a alguien :)
La explicación más fácil para esta pregunta es seguir estas plantillas:
1. Bloque como parámetro
Plantilla
- (void)aMethodWithBlock:(returnType (^)(parameters))blockName {
// your code
}
Ejemplo
-(void) saveWithCompletionBlock: (void (^)(NSArray *elements, NSError *error))completionBlock{
// your code
}
Otro uso de los casos:
2. Bloquear como una plantilla de propiedades
@property (nonatomic, copy) returnType (^blockName)(parameters);
Ejemplo
@property (nonatomic,copy)void (^completionBlock)(NSArray *array, NSError *error);
3. Bloquear como un argumento método
Plantilla
[anObject aMethodWithBlock: ^returnType (parameters) {
// your code
}];
Ejemplo
[self saveWithCompletionBlock:^(NSArray *array, NSError *error) {
// your code
}];
4. Bloquear como una variable local
Plantilla
returnType (^blockName)(parameters) = ^returnType(parameters) {
// your code
};
Ejemplo
void (^completionBlock) (NSArray *array, NSError *error) = ^void(NSArray *array, NSError *error){
// your code
};
5.Bloquear como un typedef
Plantilla
typedef returnType (^typeName)(parameters);
typeName blockName = ^(parameters) {
// your code
}
Ejemplo
typedef void(^completionBlock)(NSArray *array, NSError *error);
completionBlock didComplete = ^(NSArray *array, NSError *error){
// your code
};
Una gran respuesta muchas gracias. –
Great answer man.Far mejor que el aceptado.Gracias. – abhi1992
Tan práctico y claro, que hace que esta respuesta sea la mejor, en mi opinión. – developermike
Una referencia que utilizo más de lo que importa a admitir: http: // goshdarnblocksyntax. com/ – oltman
http://fuckingblocksyntax.com/ :) – aryaxt