I am trying to call a completion block in a unit test but it never reaches.
Here is the code:
[vc configureRecorder:^{
NSLog(#"Completion...");
}];
This is the method:
-(void)configureRecorder:(void(^)(void))callback {
NSLog(#"Method");
}
You need to call the completion block at the end of your method. like this:
-(void)configureRecorder:(void(^)(void))callback {
//#"Method"
callback()
}
Related
I'd like to implement method chaining in my swift code, likely to Alamofire methods. For example, if I have to use my function like below
getListForID(12).Success {
// Success block
}. Failure {
// Failure block
}
How would I create the function getListForID?
To expand on the great points #dasblinkenlight and #Sulthan have made – here's a small example of how you could achieve your request function to take a success and failure closure, in the convenient syntax that you want.
First, you'll have to define a new class to represent the 'result handler'. This is what your success and failure functions will pass around, allowing you to add multiple trailing closures to make up your completion block logic. You'll want it to look something like this:
class ResultHandler {
typealias SuccessClosure = RequestHandler.Output->Void
typealias FailureClosure = Void->Void
// the success and failure callback arrays
private var _successes = [SuccessClosure]()
private var _failures = [FailureClosure]()
/// Invoke all the stored callbacks with a given callback result
func invokeCallbacks(result:RequestHandler.Result) {
switch result {
case .Success(let output): _successes.forEach{$0(output)}
case .Failure: _failures.forEach{$0()}
}
}
// remove all callbacks – could call this from within invokeCallbacks
// depending on the re-usability of the class
func removeAllCallbacks() {
_successes.removeAll()
_failures.removeAll()
}
/// appends a new success callback to the result handler's successes array
func success(closure:SuccessClosure) -> Self {
_successes.append(closure)
return self
}
/// appends a new failure callback to the result handler's failures array
func failure(closure:FailureClosure) -> Self {
_failures.append(closure)
return self
}
}
This will allow you to define multiple success or failure closures to be executed on completion. If you don't actually need the capacity for multiple closures, then you can simplify the class down by stripping out the arrays – and just keeping track of the last added success and failure completion blocks instead.
Now all you have to do is define a function that generates a new ResultHandler instance and then does a given asynchronous request, with the invokeCallbacks method being invoked upon completion:
func doRequest(input:Input) -> ResultHandler {
let resultHandler = ResultHandler()
doSomethingAsynchronous(resultHandler.invokeCallbacks)
return resultHandler
}
Now you can call it like this:
doRequest(input).success {result in
print("success, with:", result)
}.failure {
print("fail :(")
}
The only thing to note is your doSomethingAsynchronous function will have to dispatch its completion block back to the main thread, to ensure thread safety.
Full project (with added example on usage): https://github.com/hamishknight/Callback-Closure-Chaining
In order to understand what is going on, it would help to rewrite your code without the "convenience" syntax, which lets you omit parentheses when a closure is the last parameter of a function:
getListForID(12)
.Success( { /* Success block */ } )
.Failure( { /* Failure block */ } )
This makes the structure of the code behind this API more clear:
The return value of getListForID must be an object
The object must have two function called Success and Failure*
Both Success and Failure need to take a single parameter of closure type
Both Success and Failure need to return self
* The object could have only Success function, and return a different object with a single Failure function, but then you wouldn't be able to re-order the Success and Failure handlers, or drop Success handler altogether.
I have a method with a callback that looks something like this:
- (void)doStuff:(void ^())callback
{
//Do a whole bunch of stuff
//Perform callback
callback();
}
I would then call this method later on like this:
[self doStuff:^{[self callbackMethod];}];
This works just fine when there is no data to pass, but now I have some data that I need to pass between the methods.
Take the following method:
- (void)showAViewWithOptions:(int)options
In this method, I show a view with certain options, but if there's something else already on the screen, I call the method to hide it with a callback back to this method.
So the implementation looks like this.
- (void)hideOldView:(void ^())callback
{
//Hide all objects in _oldViews and set _oldViews = nil
callback();
}
- (void)showAViewWithOptions:(int)options
{
if(_oldViews != nil)
{
[self hideOldView:^(int options){[self showAViewWithOptions:options];}];
return;
}
//Show the new view
}
This compiles and runs without issue, but options loses its value after being passed.
Quite frankly, it surprised me that it compiled, since I thought it wouldn't accept a block with arguments.
For instance, if I call [self showAViewWithOptions:4];, when the callback is fired, options = -1730451212.
How do I bind the value options to the block? Or a better question, is this simply not possible because when I call the callback:
callback();
I'm not putting anything into the parentheses?
If so, then a good follow-up question would be: why does this even compile in the first place?
This should work:
- (void)showAViewWithOptions:(int)options
{
if(_oldViews != nil)
{
[self hideOldView:^(){
// Recursion doesn't feel right; be careful!
// Why can't whatever is being done by this call be done
// within this block?
[self showAViewWithOptions:options];
}];
return;
}
//Show the new view
}
A block with a return value and parameters looks like this:
^ return_type (parameter1_type parameter1_name, parameter2_type parameter2_name, ...) {
do_stuff;
};
you can pass vairable into method... Callback method you call inside method:
- (void)hideOldViewWithId:(float)f callback:(void (^)(float f))callback{
f = f + 2.0f;
callback(f);
}
and then call
[self hideOldViewWithId:1.0f callback:^(float f) {
NSLog(#"callback with float: %f", f);
}];
I am going around blocks and try to discover the ways that they can be used.
So I am wondering is it possible to pass block to block like parameter?
Here is some sample code:
//declaration
static id (^someBlock)(id) = ^(id someClass) {
// do some stuff to obtain class some class instance
// check if class instance respond to #selector
// if yes - perform selector
}
//usage
+ (instancetype)someMethod {
someBlock(SomeClass.class);
// do additional work and return some instance type
}
This works fine, but is not good enough, because we obligate caller to respond to selector if caller want to do some additional stuff when someBlock is completed.
So my question is how I can invoke someBlock block with parameter block which I want to be executed when someBlock is completed.
Some like:
//declaration
static id (^someBlock)(id, <b>^otherBlock</b>) = ^(id someClass, <b>????</b>) {
// do some stuff to obtain class some class instance
otherBlock();
}
Any advice?
PS: Please note that the question is not about passing block to method as parameter.
Thanks,
Venelin
Is this what you are looking for?
static id (^someBlock)(id, void (^otherBlock)()) = ^id (id someClass, void (^otherBlock)()) {
otherBlock();
return nil; // just because you declares a `id` return type
};
And call it like
someBlock(someClass, ^() {
NSLog(#"other stuff");
});
Assume a method signature such as the following:
- (void)theMethod:(void(^)(BOOL completed))completionBlock;
I would like to mock this method signature to ensure the method is called, and just call the completion block. I see from other posts like this one that I can mock the method call and accept any block, but not run the block. I also know there is a andDo method that I might be able to use, but I can't figure out how to pass a block in and run it.
Any ideas?
Thanks.
You can use [[mock stub] andDo:] like this to pass another block that gets called when your mocked method is called:
void (^proxyBlock)(NSInvocation *) = ^(NSInvocation *invocation) {
void (^passedBlock)( BOOL );
[invocation getArgument: &passedBlock atIndex: 2];
};
[[[mock stub] andDo: proxyBlock] theMethod:[OCMArg any]];
The block gets a NSInvocation instance from which you can query all the used arguments. Note that the first argument is at index 2 since you have self and _cmd at the indices 0 and 1.
EDIT 2:
Use https://stackoverflow.com/a/32945785/637641 instead.
Using andDo: is perfectly fine, but personally I prefer [OCMArg checkWithBlock:].
[[mock expect] theMethod:[OCMArg checkWithBlock:^BOOL(id param)
{
void (^passedBlock)( BOOL ) = param;
// Normally I set some expectations here and then call the block.
return YES;
}]];
// Code to test
[mock verify];
You can use also [mock stub] but I prefer to verify that theMethod is called.
EDIT 1
OCMock 3 version:
OCMExpect([mock theMethod:[OCMArg checkWithBlock:^BOOL(void (^passedBlock)(BOOL))
{
// call the block...
return YES;
}]]);
// Code to test
OCMVerify(mock);
This is now supported in OCMock 3.2. You can use [OCMArg invokeBlock] and [OCMArg invokeBlockWithArgs:...] to invoke the block passed as an argument to a stubbed method.
Using andDo: blocks is sometimes required but for most cases you can use [OCMArg invokeBlock] or [OCMArg invokeBlockWithArgs:].
In your example you can do the following
If you don't care about the arguments:
// Call block with default arguments.
OCMStub([mock theMethod:[OCMArg invokeBlock]];
If you want to send specific arguments:
// Call block with YES.
OCMStub([mock theMethod:([OCMArg invokeBlockWithArgs:#YES, nil])];
Note the nil termination since you can pass multiple arguments to this method.
In addition the entire expression must be wrapped in parentheses.
You can read more about it in the OCMock documentation.
This is Sven's answer updated for OCMock 3.
OCMStub([myMock myMethodWithMyBlock:[OCMArg any]]).andDo(^(NSInvocation *invocation) {
void (^passedBlock)(BOOL myFirstArgument, NSError *mySecondArgument);
[invocation getArgument: &passedBlock atIndex: 2];
passedBlock(YES, nil);
});
Is this a bug?
I have the following block in the middle of my action method wrapped in the if statement:
withFormat {
json{
render returnMap as JSON
return
}
}
The returnMap is rendered to the client just fine, but the method continues to execute as if return was never processed. What's up?
I am using grails 1.3.7.
To answer my own question:
I found it has something to do with the withFormat block. If I remove it the return statement works just fine. When the withFormat is in place it seems that the return statement exits that block and continues the execution of the remaining method.
Edit:
Burt clarified below that it's the json{} closure that gets exited with the return statement (or without it I guess). If there are statements following that closure they will be executed.
The return exits the 'json' Closure, but not the whole method. It's like having methods with methods - you can only pop up one level. You'd need to set a flag inside the block and check it outside, something like
boolean renderedJson = false
...
withFormat {
json{
render returnMap as JSON
renderedJson = true
}
}
...
if (renderedJson) {
return
}