Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling NSErrors returned from factory methods that produce errors. #326

Open
fatuhoku opened this issue Mar 9, 2015 · 4 comments
Open

Comments

@fatuhoku
Copy link
Contributor

fatuhoku commented Mar 9, 2015

By using -withFactory:selector: it's possible to invoke factory methods that throw errors. e.g.

- (MESFooBar *)foobar {
    return [TyphoonDefinition withFactory:[self foobarFactory] selector:@selector(foobarWithError:)]; // ...
}

The question is, how can the error be processed if it arises?

@fatuhoku fatuhoku changed the title Error handling Handling NSErrors returned from factory methods that produce errors. Mar 9, 2015
@alexgarbarev alexgarbarev self-assigned this Mar 9, 2015
@alexgarbarev
Copy link
Contributor

First of all, use HEAD version of Typhoon. (Recently I did minor change to get this feature working)
Then change your assembly like that:

- (MESFooBar *)foobarWithError:(NSValue *)error {
    return [TyphoonDefinition withFactory:[self foobarFactory] selector:@selector(foobarWithError:) parameters:^(TyphoonMethod *factoryMethod) {
               [factoryMethod injectParameterWith:error];
           }]]; 
}

NSValue with pointer would be unwrapped (old Typhoon feature to unwrap non-object values) for method invocation

Option 1 (Explicit ownership rules on caller side)
Method declaration:

- (MESFooBar *)foobarWithError:(NSError **)error

Caller:

__autoreleasing NSError *error = nil;
MESFooBar *foobar = [self.assembly foobarWithError:[NSValue valueWithPointer:&error]];
if (error) {
    // error handling
}

Option 2 (Explicit ownership rules on factory method side)

Method declaration:

- (MESFooBar *)foobarWithError:(NSError *__strong*)error

Caller:

NSError *error = nil;
MESFooBar *foobar = [self.assembly foobarWithError:[NSValue valueWithPointer:&error]];
if (error) {
    // error handling
}

IMPORTANT NOTICE
You have to be careful with ownership rules. ARC can't handle this case implicit, because it's too complex for ARC (object written by reference wrapped by NSValue). So you have to use explicit ownership rules:

  • if NSError on caller side is strong (have __strong attribute or empty), then factory method declaration must be like (NSError __strong)
  • if NSError on caller side is autoreleasing (have __autoreleasing attribute), then factory method declaration must be like (NSError __autoreleasing) or (NSError **)

Otherwise you'll get the crash

@jasperblues
Copy link
Member

@alexgarbarev Looks like tests are failing since last commits.

@alexgarbarev
Copy link
Contributor

@jasperblues, yes, reverted back. This failure related to #325 - not this ticket

@alexgarbarev
Copy link
Contributor

I think we should update documentation for that common case (just faced with that and had to search for that ticket)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants