Guardar un manejador de finalización como un object

Me preguntaba si había una manera de "save" un handeler de finalización.

-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { } - (void)actionHere { completionHandler(UIBackgroundFetchResultNewData); } 

Quiero enviar el resultado en una function diferente como se muestra arriba.

tl dr

declarar una propiedad de copy (syntax extraña, lo sé … http://fuckingblocksyntax.com/ )

 @property (nonatomic, copy) void (^completionHandler)(UIBackgroundFetchResult fetchResult); 

y usarlo como sigue

 - (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { self.completionHandler = completionHandler; } - (void)actionHere { if (self.completionHandler) self.completionHandler(UIBackgroundFetchResultNewData); } 

Discusión

Los bloques son objects de pleno derecho en Objective-C, pero tienen una gran diferencia: por defecto se asignan a la stack.

Si desea save una reference a un bloque, debe copyrlo en el montón, ya que mantener un bloque en la stack no impedirá que se pierda cada vez que se desgarre el marco de la stack.

Para copyr un bloque en el montón, debe llamar a la function Block_Copy() . Opcionalmente puede llamar al método de copy (que invocará la function anterior para usted).

Declarar una propiedad con el atributo de copy hará que el comstackdor inserte automáticamente una llamada de copy cada vez que asigne el object a través del configurador de properties.

Los bloques son objects (sí, objects ObjC reales), lo único importante es que los copie (no los retenga) siempre que desee almacenarlos para su uso posterior.

Entonces, debes hacer lo siguiente:

 _myCompletionHandler = [completionHandler copy]; 

o:

 _myCompletionHandler = Block_copy(completionHandler); 

Deberá declarar una propiedad para su bloque. Aquí está la syntax:

 @property (nonatomic, copy) returnType (^blockName)(parameterTypes); 

Entonces puedes decir self.blockName = completionHandler .

Y en actionHere simplemente llamémoslo así:

 self.blockName();