How to Capture Completion Blocks

43 views
Skip to first unread message

Joe Masilotti

unread,
Jul 20, 2015, 1:35:56 PM7/20/15
to cedar-...@googlegroups.com
I didn't see anything in the README or Wiki on how to do this. So I wrote a quick post on capturing completion blocks with Cedar.

tl;dr

__block MovieCompletion completion;

beforeEach(^{
    completion = nil;

    service stub_method(@selector(getMoviesWithCompletion:))
    .and_do_block(^(MovieCompletion localCompletion) {
        completion = localCompletion;
    });

    subject.view should_not be_nil;
});

context(@"when the service returns movies", ^{
    beforeEach(^{
        Movie *movie1 = [[Movie alloc] initWithName:@"Movie One"];
        Movie *movie2 = [[Movie alloc] initWithName:@"Movie Two"];
        completion(@[ movie1, movie2 ], nil);
    });

    it(@"should populate the table", ^{
        [subject.tableView.visibleCells valueForKeyPath:@"textLabel.text"] 
        should equal(@[ @"Movie One", @"Movie Two" ]);
    });
});

Can Berk Güder

unread,
Jul 20, 2015, 4:22:27 PM7/20/15
to cedar-...@googlegroups.com, cedar-...@googlegroups.com
Hi Joe,

While this is very helpful as some Apple APIs make it impossible to avoid callback blocks, I would suggest using promises instead when you can. They tend to make testing much easier.

Kurtis' Deferred library is a good implementation of promises: https://github.com/kseebaldt/deferred

CBG.


--
You received this message because you are subscribed to the Google Groups "Cedar Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cedar-discus...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Joseph Masilotti

unread,
Jul 20, 2015, 4:26:47 PM7/20/15
to cedar-...@googlegroups.com, cedar-...@googlegroups.com
Thanks Can.

I used KSDeferred on a few projects at Pivotal and I agree, it makes the code read quite nicely. However, I can’t get past the lack of strongly-typed parameters in the then: and error: callbacks. 

IMHO, having a service return an array over an id makes it much easier to reason about the code. Getting code completion with typed, named objects goes a long way. It also makes refactoring more seamless as you get build-time errors vs. runtime ones. (Xcode 7 bonus, typed arrays with generics!)

Can Berk Güder

unread,
Jul 20, 2015, 9:21:37 PM7/20/15
to cedar-...@googlegroups.com
I agree, strongly typed arguments are a big win. FWIW, on one project, we subclassed KSDeferred and KSPromise for every return type, so we would have MovieDeferred and MoviePromise in this case. The Swift fork of KSPromise also uses generics.

CBG.

Joseph Masilotti

unread,
Jul 21, 2015, 3:07:24 PM7/21/15
to cedar-...@googlegroups.com, cedar-...@googlegroups.com
Interesting, how did that work out in the long run? Sounds like it could be a viable solution but might scale poorly - but I wasn’t involved so would love to hear how it went.

Can you link to the Swift fork? The only one I can find hasn’t been updated since 2014 and looks to work with Swift 1.1.

Can Berk Güder

unread,
Jul 21, 2015, 10:27:54 PM7/21/15
to cedar-...@googlegroups.com
Yeah, it's extra work to create 2 new classes for every type, but we had precompiler macros. Ugly, but it worked =)

Yeah, I think we're talking about the same repo: https://github.com/kseebaldt/KSPromise-Swift

I have a fork that fixes the problem, but Kurtis hasn't accepted it yet: https://github.com/cbguder/KSPromise-Swift/tree/swift-1.2

I also started another repo to explore what a simpler implementation might look like, but it's quite limited right now: https://github.com/cbguder/CBGPromise

CBG.
Reply all
Reply to author
Forward
0 new messages